diff --git a/src/nodes/kite_visualization_node.cpp b/src/nodes/kite_visualization_node.cpp
index 65c7d20..6b7b33f 100644
--- a/src/nodes/kite_visualization_node.cpp
+++ b/src/nodes/kite_visualization_node.cpp
@@ -1,329 +1,404 @@
 #include <ros/ros.h>
 #include <visualization_msgs/Marker.h>
 #include <visualization_msgs/MarkerArray.h>
 #include "sensor_msgs/MultiDOFJointState.h"
 #include "geometry_msgs/Vector3.h"
 #include "geometry_msgs/Quaternion.h"
 #include "geometry_msgs/Point.h"
 #include "geometry_msgs/Transform.h"
 
 #include "kite.h"
 
 using namespace casadi;
 using namespace kmath;
 
 struct Scale
 {
     float x;
     float y;
     float z;
 
     Scale(const float &_x=1, const float &_y=1, const float &_z=1) : x(_x), y(_y), z(_z) {}
     virtual ~Scale(){}
 };
 
 struct Color
 {
     float r;
     float g;
     float b;
     float transparency;
 
     Color(const float &_r=0, const float &_g=0, const float &_b=1, const float &_t=0) : r(_r), g(_g), b(_b), transparency(_t){}
     virtual ~Color(){}
 };
 
 struct MarkerProperties
 {
     int         type;
     int         id;
     int         action;
     std::string frame_id;
     std::string ns;
     std::string mesh_resource;
     Scale       scale;
     Color       color;
 
     geometry_msgs::Point      position;
     geometry_msgs::Quaternion orientation;
 
     MarkerProperties() : type(visualization_msgs::Marker::SPHERE),
                          id(0),
                          action(visualization_msgs::Marker::ADD),
                          frame_id("/kite"),
                          ns("awe"),
                          scale(Scale()),
                          color(Color()),
                          mesh_resource("")
     {
         position.x = position.y = position.z = 0;
         orientation.x = orientation.y = orientation.z = 0;
         orientation.w = 1;
     }
 
     void configureMarker(visualization_msgs::Marker &marker);
 };
 
 void MarkerProperties::configureMarker(visualization_msgs::Marker &marker)
 {
     marker.type = type;
     marker.id   = id;
     marker.header.frame_id = frame_id;
     marker.header.stamp    = ros::Time::now();
     marker.action = action;
     marker.color.r = color.r; marker.color.g = color.g; marker.color.b = color.b;
     marker.color.a = color.transparency;
     marker.scale.x = scale.x; marker.scale.y = scale.y; marker.scale.z = scale.z;
     marker.pose.position = position;
     marker.pose.orientation = orientation;
     if(type == visualization_msgs::Marker::MESH_RESOURCE)
         marker.mesh_resource    = mesh_resource;
 }
 
 class KiteVisualizer
 {
 public:
     KiteVisualizer(const ros::NodeHandle &_nh);
     virtual ~KiteVisualizer(){}
 
-    void filterCallback(const sensor_msgs::MultiDOFJointState::ConstPtr &msg);
-    void controlCallback(const sensor_msgs::MultiDOFJointState::ConstPtr &msg);
-
     geometry_msgs::Point getTranslation(){geometry_msgs::Vector3 point = kite_state.transforms[0].translation;
                                           geometry_msgs::Point p; p.x = point.x; p.y = point.y; p.z = point.z;
                                           return p;}
 
     geometry_msgs::Quaternion getRotation(){return kite_state.transforms[0].rotation;}
     bool is_initialized(){return initialized;}
     uint32_t getNumPublishers(){return state_sub.getNumPublishers();}
 
     DM world2rviz(const casadi::DM &pose);
     visualization_msgs::Marker state2marker(const casadi::DM &kite_pose);
     visualization_msgs::Marker getPose(){return m_kite_marker;}
 
     visualization_msgs::MarkerArray getOptimalTrajectory();
     visualization_msgs::Marker      getVirtualTrajectory();
 
+    void setPath(const Function &path){PathFunction = path;}
+
 private:
     std::shared_ptr<ros::NodeHandle> nh;
     ros::Subscriber state_sub;
     ros::Subscriber opt_traj_sub;
 
+    void filterCallback(const sensor_msgs::MultiDOFJointState::ConstPtr &msg);
+    void controlCallback(const sensor_msgs::MultiDOFJointState::ConstPtr &msg);
+
     sensor_msgs::MultiDOFJointState    kite_state;
     visualization_msgs::Marker         m_kite_marker;
 
     /** optimal trajectory visualisation */
     visualization_msgs::MarkerArray    kite_traj_markers;
     visualization_msgs::Marker         virtual_state_markers;
 
-    sensor_msgs::MultiDOFJointState    kite_trajectory;
+    DM   optimal_trajectory;
+    Function PathFunction;
     bool initialized;
 
     DM convertToDM(const sensor_msgs::MultiDOFJointState &_value, const bool &with_virtual = 0);
 };
 
 KiteVisualizer::KiteVisualizer(const ros::NodeHandle &_nh)
 {
     nh = std::make_shared<ros::NodeHandle>(_nh);
 
     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";
 
     std::string state_topic = "/kite_state";
     state_sub = nh->subscribe(state_topic, 100, &KiteVisualizer::filterCallback, this);
     opt_traj_sub = nh->subscribe("/opt_traj", 100, &KiteVisualizer::controlCallback, this);
 
     /** configure kite_marker */
     MarkerProperties m_props;
     m_props.id = 101;
     m_props.type = visualization_msgs::Marker::MESH_RESOURCE;
     m_props.mesh_resource = "package://test_package/meshes/kite_rviz.dae";
     m_props.scale = Scale(0.1, 0.1, 0.1);
     m_props.color = Color(0.0, 1.0, 0.0, 0.5);
     m_props.configureMarker(m_kite_marker);
     m_kite_marker.lifetime = ros::Duration();
 
     /** configure virtual state trajectory */
     m_props.id = 201;
     m_props.type  = visualization_msgs::Marker::SPHERE_LIST;
     m_props.color = Color(1.0, 0.0, 0.0, 0.5);
     m_props.configureMarker(virtual_state_markers);
     virtual_state_markers.lifetime = ros::Duration();
 
     initialized = false;
 }
 
 void KiteVisualizer::filterCallback(const sensor_msgs::MultiDOFJointState::ConstPtr &msg)
 {
     /** transform kite pose to Rviz reference frame */
     /** @badcode: */
     DM pose = convertToDM(*msg);
     DM kite_state_dm = world2rviz(pose);
     m_kite_marker = state2marker(kite_state_dm);
     initialized = true;
 }
 
 void KiteVisualizer::controlCallback(const sensor_msgs::MultiDOFJointState::ConstPtr &msg)
 {
     DM pose = convertToDM(*msg);
-    DM kite_state_dm = world2rviz(pose);
-
-    /** to finish */
+    optimal_trajectory = world2rviz(pose);
 }
 
 DM KiteVisualizer::convertToDM(const sensor_msgs::MultiDOFJointState &_value, const bool &with_virtual)
 {
     uint num_poses = _value.transforms.size();
     int  size      = with_virtual ? 10 : 7;
     DM poses = DM::zeros(size, num_poses);
 
     for(uint i = 0; i < num_poses; ++i)
     {
         poses(0, i) = _value.transforms[i].translation.x;
         poses(1, i) = _value.transforms[i].translation.y;
         poses(2, i) = _value.transforms[i].translation.z;
         poses(3, i) = _value.transforms[i].rotation.w;
         poses(4, i) = _value.transforms[i].rotation.x;
         poses(5, i) = _value.transforms[i].rotation.y;
         poses(6, i) = _value.transforms[i].rotation.z;
 
         if(with_virtual)
         {
             poses(7, i) = _value.wrench[i].force.x;
             poses(8, i) = _value.wrench[i].force.y;
             poses(9, i) = _value.wrench[i].force.z;
         }
     }
     return poses;
 }
 
 DM KiteVisualizer::world2rviz(const DM &world_pose)
 {
     DM pose = DM::zeros(world_pose.size());
     DM transform = DM::vertcat({0, 1, 0, 0});
+    /** do only position transform if receive a point*/
+    if(pose.size1() == 3)
+    {
+        DM q_pose = quat_multiply(transform, DM::vertcat({0, world_pose}) );
+        DM tmp = quat_multiply(q_pose, quat_inverse(transform) );
+        pose = tmp(Slice(1,4), 0);
+
+        return pose;
+    }
+
     /** position transform */
     DM q_pose = quat_multiply(transform, DM::vertcat({0, world_pose(Slice(0,3), 0) }) );
     DM tmp = quat_multiply(q_pose, quat_inverse(transform) );
     pose(Slice(0,3), 0) = tmp(Slice(1,4), 0);
     /** attitude transform */
     pose(Slice(3,7),0) = quat_multiply(quat_multiply(transform, world_pose(Slice(3,7), 0)), quat_inverse(transform));
 
     if(pose.size1() == 10)
     {
         q_pose = quat_multiply(transform, DM::vertcat({0, world_pose(Slice(7,10), 0) }) );
         tmp = quat_multiply(q_pose, quat_inverse(transform) );
         pose(Slice(7,10), 0) = tmp(Slice(1,4), 0);
     }
 
     return pose;
 }
 
+visualization_msgs::MarkerArray KiteVisualizer::getOptimalTrajectory()
+{
+    visualization_msgs::MarkerArray m_array;
+    int array_size = optimal_trajectory.size2();
+    if(array_size == 0)
+        return m_array;
+
+    DMVector split_traj = DM::horzsplit(optimal_trajectory, 1);
+
+    for(DMVector::const_iterator it = split_traj.begin(); it != split_traj.end() - 1; std::advance(it, 2))
+    {
+        /** transform to rviz ref frame */
+        DM state = world2rviz(*it);
+
+        std::vector<double> row = state.nonzeros();
+        m_kite_marker.pose.position.x = row[6];
+        m_kite_marker.pose.position.y = row[7];
+        m_kite_marker.pose.position.z = row[8];
+
+        m_kite_marker.pose.orientation.w = row[9];
+        m_kite_marker.pose.orientation.x = row[10];
+        m_kite_marker.pose.orientation.y = row[11];
+        m_kite_marker.pose.orientation.z = row[12];
+
+        m_array.markers.push_back(m_kite_marker);
+    }
+    return m_array;
+}
+
+visualization_msgs::Marker KiteVisualizer::getVirtualTrajectory()
+{
+    visualization_msgs::Marker m_array;
+    int array_size = optimal_trajectory.size2();
+    if(array_size == 0 || PathFunction.is_null())
+        return m_array;
+
+    DMVector split_traj = DM::horzsplit(optimal_trajectory, 1);
+    virtual_state_markers.points.clear();
+
+    for(DMVector::const_iterator it = split_traj.begin(); it != split_traj.end(); std::advance(it, 1))
+    {
+        DM theta = (*it)(13);
+        DMVector res = PathFunction(DMVector{theta});
+        DM point = world2rviz(res[0]);
+        geometry_msgs::Point p;
+        std::vector<double> coords = point.nonzeros();
+        p.x = coords[0];
+        p.y = coords[1];
+        p.z = coords[2];
+
+        virtual_state_markers.points.push_back(p);
+    }
+    return m_array;
+}
+
 visualization_msgs::Marker KiteVisualizer::state2marker(const DM &kite_pose)
 {
     visualization_msgs::Marker marker;
     std::vector<double> pose = kite_pose.nonzeros();
     marker.pose.position.x = pose[0];
     marker.pose.position.y = pose[1];
     marker.pose.position.z = pose[2];
 
     marker.pose.orientation.w = pose[3];
     marker.pose.orientation.x = pose[4];
     marker.pose.orientation.y = pose[5];
     marker.pose.orientation.z = pose[6];
 
     return marker;
 }
 
 
 int main( int argc, char** argv )
 {
     ros::init(argc, argv, "kite_visualization_node");
     ros::NodeHandle n;
     ros::Rate r(10);
     ros::Publisher marker_pub = n.advertise<visualization_msgs::Marker>("visualization_marker", 10);
     ros::Publisher trajec_pub = n.advertise<visualization_msgs::MarkerArray>("trajectory_marker", 10);
 
     KiteVisualizer kite(n);
     visualization_msgs::Marker gs_marker;
     visualization_msgs::Marker kite_marker;
     visualization_msgs::Marker path_marker;
 
     MarkerProperties marker_props;
     marker_props.type  = visualization_msgs::Marker::CYLINDER;
     marker_props.scale = Scale(0.1, 0.1, 2.0);
     marker_props.color = Color(0.0, 1.0, 0.0, 1.0);
     marker_props.configureMarker(gs_marker);
     gs_marker.lifetime = ros::Duration();
 
     /** kite marker set up */
     marker_props.id = 1;
     marker_props.type = visualization_msgs::Marker::MESH_RESOURCE;
     marker_props.mesh_resource = "package://test_package/meshes/kite_rviz.dae";
     marker_props.scale = Scale(0.1, 0.1, 0.1);
     marker_props.configureMarker(kite_marker);
     kite_marker.lifetime = ros::Duration();
 
     /** path markers set up */
     marker_props.id = 3;
     marker_props.type = visualization_msgs::Marker::LINE_STRIP;
     marker_props.scale.x = 0.025;
     marker_props.configureMarker(path_marker);
     path_marker.lifetime = ros::Duration();
 
     /** create a path */
     SX x = SX::sym("x");
     double radius   = 2.31;
     double altitude = 3.0;
     SX Path = SX::vertcat(SXVector{radius * cos(x), radius * sin(x), altitude});
     Function path_fun = Function("path", {x}, {Path});
     for(double alpha = 0; alpha < 2 * M_PI; alpha += 0.2)
     {
         DMVector res = path_fun( DMVector{DM(alpha)} );
         geometry_msgs::Point p;
         DM point = res[0];
         p.x = point.nonzeros()[0];
         p.y = point.nonzeros()[1];
         p.z = point.nonzeros()[2];
         path_marker.points.push_back(p);
     }
 
     bool published_once = false;
 
     while (ros::ok())
     {
         gs_marker.lifetime = ros::Duration();
         kite_marker.lifetime = ros::Duration();
 
         if(kite.is_initialized())
         {
             kite_marker = kite.getPose();
         }
 
         // Publish the marker
         while (marker_pub.getNumSubscribers() < 1)
         {
             if (!ros::ok())
             {
                 return 0;
             }
             ROS_WARN_ONCE("Please create a subscriber to the marker");
             sleep(1);
         }
 
         marker_pub.publish(gs_marker);
         marker_pub.publish(kite_marker);
 
+        /** draw optimal trajectories */
+        visualization_msgs::Marker virt_markers     = kite.getVirtualTrajectory();
+        visualization_msgs::MarkerArray opt_markers = kite.getOptimalTrajectory();
+        if(!opt_markers.markers.empty())
+            trajec_pub.publish(opt_markers);
+
+        if(!virt_markers.points.empty())
+            marker_pub.publish(virt_markers);
+
         if(!published_once)
         {
             marker_pub.publish(path_marker);
             published_once = true;
         }
 
 
         ros::spinOnce();
         r.sleep();
     }
 }