diff --git a/src/kite_estimation/ekf_node.cpp b/src/kite_estimation/ekf_node.cpp
index fa79975..9738305 100644
--- a/src/kite_estimation/ekf_node.cpp
+++ b/src/kite_estimation/ekf_node.cpp
@@ -1,267 +1,269 @@
 #include "ekf_node.h"
 
 using namespace casadi;
 
 void KiteEKF_Node::filterCallback(const geometry_msgs::PoseStamped::ConstPtr &msg)
 {
     /** update measurement */
     last_measurement_arrived = (*msg).header.stamp;
     //boost::unique_lock<boost::mutex> scoped_lock(m_mutex);
     /** @todo: revise sending mechanism instead */
     if ( !measurements.empty() )
     {
         double time_lapsed = (last_measurement_arrived - measurements.back().header.stamp).toSec();
         if( time_lapsed >= 0.01 )
         {
             measurements.push_back(*msg);
             //std::cout << "callback: measurement came at: " << last_measurement_arrived
             //          << " it was: " << convertToDM(*msg) << "\n";
         }
     }
     else
     {
         measurements.push_back(*msg);
         //std::cout << "callback: first measurement came at: " << last_measurement_arrived
         //          << " it was: " << convertToDM(*msg) << "\n";
     }
 }
 
 void KiteEKF_Node::controlCallback(const std_msgs::Int16MultiArray::ConstPtr &msg)
 {
     double throttle = static_cast<double>(msg->data[0]);
-    double elevator = static_cast<double>(msg->data[1]);
-    double rudder = static_cast<double>(msg->data[2]);
+    double elevator = static_cast<double>(msg->data[2]);
+    double rudder = static_cast<double>(msg->data[3]);
     control = DM::vertcat({throttle, elevator, rudder});
 }
 
 KiteEKF_Node::KiteEKF_Node(const ros::NodeHandle &_nh, const Function &Integrator, const Function &Jacobian)
 {
     /** @redo model initialization*/
     nh = std::make_shared<ros::NodeHandle>(_nh);
     measurements.set_capacity(2);
 
     kite_state.twist.resize(1);
     kite_state.transforms.resize(1);
     kite_state.joint_names.resize(1);
     kite_state.header.frame_id = "kite";
     kite_state.joint_names[0] = "lox";
 
     brf_offset = DMVector{-0.09, 0, -0.02};
     brf_rotation = DMVector{0.0, -1.0, 0.0, 0.0};
 
     /** create filter object */
     filter = std::make_shared<KiteEKF>(Integrator, Jacobian);
 
     /** initialize subscribers and publishers */
     state_pub = nh->advertise<sensor_msgs::MultiDOFJointState>("/kite_state", 100);
 
     /** @todo : parametrize topics */
     std::string pose_topic = "/optitrack/Kite/pose";
     std::string control_topic = "/chatter";
 
     pose_sub = nh->subscribe(pose_topic, 1000, &KiteEKF_Node::filterCallback, this);
     control_sub = nh->subscribe(control_topic, 1000, &KiteEKF_Node::controlCallback, this);
 
     m_initialized = false;
 }
 
 void KiteEKF_Node::initialize()
 {
     /** initialize kite state based on 2 sequential pose measurements */
     if (measurements.size() == 2)
     {
         DM m_prev, m_new;
         double dt;
 
         /** @todo: work out proper mutex lock */
         //boost::unique_lock<boost::mutex> scoped_lock(m_mutex);
         m_prev = optitrack2world(convertToDM(measurements[0]));
         m_new = optitrack2world(convertToDM(measurements[1]));
         dt = measurements[1].header.stamp.toSec() - measurements[0].header.stamp.toSec();
 
         std::cout << "time: " << measurements[0].header.stamp << " meas_prev: " << m_prev << "\n";
         std::cout << "time: " << measurements[1].header.stamp << " meas_new: " << m_new << "\n";
 
         /** linear velocity estimation */
         DM rdot = ( m_new(Slice(0, 3), 0) - m_prev(Slice(0, 3), 0) ) / dt;
         SX att = m_prev( Slice(3, 7), 0);
         DM att_inv = kmath::quat_inverse(att);
 
         SX rdot_b = kmath::quat_multiply(att_inv, SX::vertcat({0, rdot}));
         DM v_body = kmath::quat_multiply(rdot_b, att);
         v_body = v_body(Slice(1, 4), 0);
 
         /** estimate angular rates */
         SX att2 = m_new( Slice(3, 7), 0);
         DM dq = kmath::quat_multiply(SX(att_inv), att2);
         DM identity = DM::vertcat({1,0,0,0});
         DM qw = (2.0 / dt) * (dq - identity);
         DM w_body = qw(Slice(1, 4), 0);
 
         std::cout << "Initialized at: " << v_body << " " << w_body << "\n";
 
         std::vector<double> v_brf = v_body.nonzeros();
         std::vector<double> w_brf = w_body.nonzeros();
         std::vector<double> pose_irf = m_new.nonzeros();
 
         kite_state.twist[0].linear.x = v_brf[0];
         kite_state.twist[0].linear.y = v_brf[1];
         kite_state.twist[0].linear.z = v_brf[2];
 
         kite_state.twist[0].angular.x = w_brf[3];
         kite_state.twist[0].angular.y = w_brf[4];
         kite_state.twist[0].angular.z = w_brf[5];
 
         kite_state.transforms[0].translation.x = pose_irf[0];
         kite_state.transforms[0].translation.y = pose_irf[1];
         kite_state.transforms[0].translation.z = pose_irf[2];
 
         kite_state.transforms[0].rotation.w = pose_irf[3];
         kite_state.transforms[0].rotation.x = pose_irf[4];
         kite_state.transforms[0].rotation.y = pose_irf[5];
         kite_state.transforms[0].rotation.z = pose_irf[6];
 
         /** update filter time */
         filter->setTime( measurements.back().header.stamp.toSec() );
         /** initialize filter */
         filter->setEstimation( DM::vertcat({v_body, w_body, m_new}) );
 
         m_initialized = true;
     }
 
 }
 
 DM KiteEKF_Node::convertToDM(const geometry_msgs::PoseStamped &_value)
 {
     DM value = DM::zeros(7);
     value[0] = _value.pose.position.x;
     value[1] = _value.pose.position.y;
     value[2] = _value.pose.position.z;
     value[3] = _value.pose.orientation.w;
     value[4] = _value.pose.orientation.x;
     value[5] = _value.pose.orientation.y;
     value[6] = _value.pose.orientation.z;
 
     return value;
 }
 
 DM KiteEKF_Node::optitrack2world(const DM &opt_pose)
 {
     DM position = opt_pose(Slice(0, 3), 0);
     DM attitude = opt_pose(Slice(3, 7), 0);
 
     DM tmp = kmath::quat_multiply(attitude, DM::vertcat({0, brf_offset}));
     DM offset_b = kmath::quat_multiply(tmp, kmath::quat_inverse(attitude));
     position += offset_b(Slice(1, 4), 0);
 
     /** transform to world ref frame */
     tmp = kmath::quat_multiply(brf_rotation, DM::vertcat({0, position}));
     DM world_pos = kmath::quat_multiply(tmp, kmath::quat_inverse(brf_rotation));
     world_pos = world_pos(Slice(1, 4), 0);
 
     tmp = kmath::quat_multiply(brf_rotation, attitude);
     DM world_att = kmath::quat_multiply(tmp, kmath::quat_inverse(brf_rotation));
 
     /** @todo : remove this hack */
     world_pos(2) = world_pos(2) + 2.77;
 
     return DM::vertcat({world_pos, world_att});
 }
 
 void KiteEKF_Node::estimate()
 {
     //get observation
     DM observation = optitrack2world(convertToDM(measurements.back()));
     double tstamp = measurements.back().header.stamp.toSec();
     filter->estimate(observation, tstamp);
 
     /** update filter time */
     filter->setTime(tstamp);
 }
 
 void KiteEKF_Node::publish()
 {
     /** pack estimation to ROS message */
     DM correction = DM({0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
-                        -0.09, -0.1247, -0.0418, 0.0, 0.0, 0.0, 0.0});
+                        -0.09, -0.1247, -0.0418, 0.0, 0.0, 0.0, 0.0}) +
+            DM({0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
+                                    -0.02, 0.01, -0.0418, 0.0, 0.0, 0.0, 0.0});
     DM corrected_estim = filter->getEstimation() - correction;
     //std::cout << "Estimated distance: " << DM::norm_2(corrected_estim(Slice(6,9))) << "\n";
     std::vector<double> state_vec = corrected_estim.nonzeros();
 
     kite_state.header.stamp = ros::Time::now();
 
     kite_state.twist[0].linear.x = state_vec[0];
     kite_state.twist[0].linear.y = state_vec[1];
     kite_state.twist[0].linear.z = state_vec[2];
 
     kite_state.twist[0].angular.x = state_vec[3];
     kite_state.twist[0].angular.y = state_vec[4];
     kite_state.twist[0].angular.z = state_vec[5];
 
     kite_state.transforms[0].translation.x = state_vec[6];
     kite_state.transforms[0].translation.y = state_vec[7];
     kite_state.transforms[0].translation.z = state_vec[8];
 
     kite_state.transforms[0].rotation.w = state_vec[9];
     kite_state.transforms[0].rotation.x = state_vec[10];
     kite_state.transforms[0].rotation.y = state_vec[11];
     kite_state.transforms[0].rotation.z = state_vec[12];
 
     /** publish current state estimation */
     state_pub.publish(kite_state);
 }
 
 int main(int argc, char **argv)
 {
     ros::init(argc, argv, "ekf_node");
     ros::NodeHandle n("~");
 
     unsigned tries = 0;
     unsigned locks = 0;
 
     /** create a kite object */
     std::string kite_params_file;
     n.param<std::string>("kite_params", kite_params_file, "./umx_radian.yaml");
     std::cout << kite_params_file << "\n";
     KiteProperties kite_props = kite_utils::LoadProperties(kite_params_file);
     AlgorithmProperties algo_props;
     algo_props.Integrator = RK4;
     algo_props.sampling_time = 0.02;
     KiteDynamics kite = KiteDynamics(kite_props, algo_props);
 
     /** create a rigid body topic */
     RigidBodyKinematics rigid_body = RigidBodyKinematics(algo_props);
 
     Function fIntegrator = rigid_body.getNumericIntegrator();
     Function fJacobian = rigid_body.getNumericJacobian();
 
     /** create an EKF instance */
     KiteEKF_Node filter(n, fIntegrator, fJacobian);
     ros::Rate loop_rate(50); /** 50 Hz */
 
     while (ros::ok())
     {
         //std::cout << "TRIES: " << tries << " LOCKS: " << locks << "\n";
 
         /** Some complicated logic here please */
         if (!filter.initialized())
         {   std::cout << "CANNOT INITIALIZE \n";
             //boost::unique_lock<boost::mutex> scoped_lock(filter.m_mutex);
             filter.initialize();
         }
         else
         {
             /** perform estimation */
             //tries++;
             //boost::unique_lock<boost::mutex> scoped_lock(filter.m_mutex);
             ///locks++;
             filter.estimate();
             filter.publish();
         }
 
         ros::spinOnce();
         loop_rate.sleep();
     }
 
     return 0;
 }