kinton_vs_control_alg_node.cpp
Go to the documentation of this file.
00001 #include "kinton_vs_control_alg_node.h"
00002 
00003 KintonVsControlAlgNode::KintonVsControlAlgNode(void) :
00004   algorithm_base::IriBaseAlgorithm<KintonVsControlAlgorithm>(),
00005   estop_(false),
00006   serial_(false),
00007   height_fix_(0.0),
00008   time_(0),
00009   time_last_(0)
00010 {
00011   //init class attributes if necessary
00012   this->loop_rate_ = 100;//in [Hz]
00013 
00014   //Init Thrust PIDs
00015   this->nm_pid_thrust_.initPid(this->nm_thrust_kp_, 0, this->nm_thrust_kd_, 0, 0);
00016   
00017   //Init Roll PIDs
00018   this->nm_pid_roll_.initPid(this->nm_roll_kp_, 0, this->nm_roll_kd_, 0, 0);
00019   
00020   //Init Pitch PIDs
00021   this->nm_pid_pitch_.initPid(this->nm_pitch_kp_, 0, this->nm_pitch_kd_, 0, 0);
00022   
00023   //Init Yaw PIDs
00024   this->nm_pid_yaw_.initPid(this->nm_yaw_kp_, 0, this->nm_yaw_kd_, 0, 0);
00025 
00026   this->cam_twist_ = Eigen::MatrixXd::Zero(6,1);
00027 
00028   //Get fixed transforms between the IMU data and the robot frame
00029   tf::TransformListener listener;
00030   tf::StampedTransform tf_quad_to_cam;
00031 
00032   //wait 1.0 secs waiting for the other nodes to start
00033   sleep(1.0);
00034 
00035   try {
00036     listener.waitForTransform("/base_link","/front_cam_optical_frame", ros::Time::now(), ros::Duration(1.0));
00037     listener.lookupTransform("/base_link","/front_cam_optical_frame", ros::Time::now(), tf_quad_to_cam);
00038   } 
00039   catch (tf::TransformException ex) {
00040     ROS_ERROR("Quad_to_cam Transform error: %s",ex.what());
00041   }
00042 
00043   //Homogenous transform between camera and quadrotor base_link frames
00044   this->T_quad_to_cam_ = getTransform(tf_quad_to_cam);
00045 
00046   // [init publishers]
00047   this->cmd_yaw_publisher_ = this->public_node_handle_.advertise<std_msgs::Float64>("cmd_yaw", 10);
00048   this->cmd_pitch_publisher_ = this->public_node_handle_.advertise<std_msgs::Float64>("cmd_pitch", 10);
00049   this->cmd_roll_publisher_ = this->public_node_handle_.advertise<std_msgs::Float64>("cmd_roll", 10);
00050   this->cmd_thrust_publisher_ = this->public_node_handle_.advertise<std_msgs::Float64>("cmd_thrust", 10);
00051   this->ESTOP_publisher_ = this->public_node_handle_.advertise<std_msgs::Bool>("ESTOP", 1);
00052 
00053   // [init subscribers]
00054   this->cam_vel_subscriber_ = this->public_node_handle_.subscribe("cam_vel", 100, &KintonVsControlAlgNode::cam_vel_callback, this);
00055   this->odom_subscriber_ = this->public_node_handle_.subscribe("odom", 100, &KintonVsControlAlgNode::odom_callback, this);
00056   this->ll_status_subscriber_ = this->public_node_handle_.subscribe("ll_status", 100, &KintonVsControlAlgNode::ll_status_callback, this);
00057 
00058   
00059   // [init services]
00060   
00061   // [init clients]
00062   
00063   // [init action servers]
00064   
00065   // [init action clients]
00066 }
00067 
00068 KintonVsControlAlgNode::~KintonVsControlAlgNode(void)
00069 {
00070   // [free dynamic memory]
00071 }
00072 
00073 void KintonVsControlAlgNode::mainNodeThread(void)
00074 {
00075   // [fill msg structures]
00076   
00077   // [fill srv structure and make request to the server]
00078   
00079   // [fill action structure and make request to the action server]
00080 
00081   this->time_ = ros::Time::now();
00082 
00083   this->cam_vel_mutex_.enter();
00084     bool marker_ctrl = this->marker_ctrl_;
00085   this->cam_vel_mutex_.exit();
00086 
00087   // Marker or Height control
00088   Eigen::MatrixXd cmd_raw = Eigen::MatrixXd::Zero(4,1);
00089   Eigen::MatrixXd quad_cmd = Eigen::MatrixXd::Zero(4,1);
00090   if (marker_ctrl){
00091 
00092     //Transform velocities from camera to base_link frames
00093     Eigen::MatrixXd quad_vel;
00094     quad_vel = cam_to_quad_vel();
00095 
00096     cmd_raw(0,0) = quad_vel(0,0);
00097     cmd_raw(1,0) = quad_vel(1,0);
00098     cmd_raw(2,0) = quad_vel(5,0);
00099     cmd_raw(3,0) = quad_vel(2,0);
00100   }  
00101   else{
00102     this->odom_mutex_.enter(); 
00103       double height = this->height_;
00104       double height_fix = this->height_fix_;
00105     this->odom_mutex_.exit(); 
00106     
00107     // Height control
00108     Eigen::MatrixXd error_no_marker = Eigen::MatrixXd::Zero(4,1);
00109     error_no_marker(2,0) = height - height_fix;
00110 
00111     //TODO: translate error vector from inertial to body
00112 
00113     cmd_raw(0,0) = this->nm_pid_roll_.updatePid(error_no_marker(0,0), this->time_ - this->time_last_);
00114     cmd_raw(1,0) = this->nm_pid_pitch_.updatePid(error_no_marker(1,0), this->time_ - this->time_last_);
00115     cmd_raw(2,0) = this->nm_pid_yaw_.updatePid(error_no_marker(2,0), this->time_ - this->time_last_);
00116     cmd_raw(3,0) = this->nm_pid_thrust_.updatePid(error_no_marker(3,0), this->time_ - this->time_last_);
00117   }
00118 
00119 
00120   //Signal adaptation (trimmers and saturations)
00121   quad_cmd = signal_adapt(cmd_raw);
00122 
00123   // [publish messages]
00124   this->cmd_roll_msg_.data = quad_cmd(0,0);
00125   this->cmd_pitch_msg_.data = quad_cmd(1,0);
00126   this->cmd_yaw_msg_.data = quad_cmd(2,0);
00127   this->cmd_thrust_msg_.data = quad_cmd(3,0);
00128 
00129   this->cmd_roll_publisher_.publish(this->cmd_roll_msg_);
00130   this->cmd_pitch_publisher_.publish(this->cmd_pitch_msg_);
00131   this->cmd_yaw_publisher_.publish(this->cmd_yaw_msg_);
00132   this->cmd_thrust_publisher_.publish(this->cmd_thrust_msg_);
00133 
00134   //Emergency STOP enable
00135   this->Bool_msg_.data=this->estop_;
00136   if (this->estop_) {
00137     ROS_ERROR_STREAM("EMERGENCY_STOP ENABLED");
00138     this->ESTOP_publisher_.publish(this->Bool_msg_);
00139   }
00140 
00141   this->time_last_ = this->time_;
00142 }
00143 
00144 /*  [subscriber callbacks] */
00145 void KintonVsControlAlgNode::cam_vel_callback(const geometry_msgs::TwistWithCovariance::ConstPtr& msg) 
00146 { 
00147   //ROS_INFO("KintonVsControlAlgNode::twist_cov_callback: New Message Received"); 
00148 
00149   //use appropiate mutex to shared variables if necessary 
00150   //this->alg_.lock(); 
00151   this->cam_vel_mutex_.enter(); 
00152 
00153   if (msg->covariance[0]<1000)
00154   {
00155     this->height_fix_ = this->height_;
00156     this->marker_ctrl_ = true;
00157   }
00158   else{
00159     this->marker_ctrl_ = false;
00160   }
00161 
00162   //Rotate camera velocities such as base_link
00163   this->cam_twist_(0,0) = msg->twist.linear.x;
00164   this->cam_twist_(1,0) = msg->twist.linear.y;
00165   this->cam_twist_(2,0) = msg->twist.linear.z;
00166   this->cam_twist_(3,0) = msg->twist.angular.x;
00167   this->cam_twist_(4,0) = msg->twist.angular.y;
00168   this->cam_twist_(5,0) = msg->twist.angular.z;
00169 
00170   //std::cout << msg->data << std::endl; 
00171 
00172   //unlock previously blocked shared variables 
00173   //this->alg_.unlock(); 
00174   this->cam_vel_mutex_.exit(); 
00175 }
00176 void KintonVsControlAlgNode::odom_callback(const nav_msgs::Odometry::ConstPtr& msg) 
00177 { 
00178   //ROS_INFO("KintonVsControlAlgNode::odom_callback: New Message Received"); 
00179 
00180   //use appropiate mutex to shared variables if necessary 
00181   //this->alg_.lock(); 
00182   this->odom_mutex_.enter(); 
00183 
00184   //Check if the twist covariance is correct 
00185 
00186   this->height_ = msg->pose.pose.position.z;
00187 
00188   //unlock previously blocked shared variables 
00189   //this->alg_.unlock(); 
00190   this->odom_mutex_.exit(); 
00191 }
00192 void KintonVsControlAlgNode::ll_status_callback(const asctec_msgs::LLStatus::ConstPtr& msg) 
00193 { 
00194   //ROS_INFO("UncalibvsAlgNode::ll_status_callback: New Message Received"); 
00195 
00196   //use appropiate mutex to shared variables if necessary 
00197   //this->alg_.lock(); 
00198   this->ll_status_mutex_.enter(); 
00199 
00200   //std::cout << msg->data << std::endl; 
00201   int ll_status;
00202   ll_status=(int)msg->flightMode;
00203   
00204   std::bitset<32> flight_mode;
00205   flight_mode.reset();
00206   
00207   
00208   int *y,x;
00209   y = reinterpret_cast<int*>(&ll_status);
00210   x=*y;
00211   for(short i=0;i<32;++i) {
00212     flight_mode[i] = x%2;
00213     x /= 2;
00214   }
00215 
00216   
00217   if ((ll_status|0b1111111101111111)!=0b1111111111111111)   ROS_DEBUG("NO Emergency");
00218   if ((ll_status|0b1111111111111101)!=0b1111111111111111)   ROS_DEBUG("NO Height Control");
00219   if ((ll_status|0b1111111111111011)!=0b1111111111111111)   ROS_DEBUG("NO GPS Mode");
00220   if ((ll_status|0b1111111111011111)!=0b1111111111111111) {
00221     ROS_DEBUG("NO Serial Enable");
00222     this->serial_=false;
00223     this->height_fix_=0;
00224   }
00225   else {
00226     this->serial_=true;
00227   }
00228   
00229   if ((ll_status|0b1111111110111111)!=0b1111111111111111)   ROS_DEBUG("NO Serial Active");
00230 
00231   //unlock previously blocked shared variables 
00232   //this->alg_.unlock(); 
00233   this->ll_status_mutex_.exit(); 
00234 }
00235 
00236 /*  [service callbacks] */
00237 
00238 /*  [action callbacks] */
00239 
00240 /*  [action requests] */
00241 
00242 Eigen::MatrixXd KintonVsControlAlgNode::cam_to_quad_vel() 
00243 {
00244 
00245   Eigen::MatrixXd cam_lin = Eigen::MatrixXd::Zero(3,1);
00246   Eigen::MatrixXd cam_ang = Eigen::MatrixXd::Zero(3,1);
00247 
00248   //Camera desired velocities
00249   this->cam_vel_mutex_.enter();
00250     cam_lin = this->cam_twist_.block(0,0,3,1);
00251     cam_ang = this->cam_twist_.block(3,0,3,1);
00252   this->cam_vel_mutex_.exit();
00253 
00254   //Transform angular velocities from cam_optical_frame to base_link
00255   //In a rigid body the values does not change, only frame changes
00256   Eigen::MatrixXd quad_ang = Eigen::MatrixXd::Zero(3,1);
00257   quad_ang = this->T_quad_to_cam_.block(0,0,3,3) * cam_ang;
00258 
00259   //In a rigid body, the angular velocities add linear velocities
00260   //Without considering it negligible:
00261   //Skew symmetric to perform cross product
00262   // Eigen::Matrix3d skew;
00263   // skew(0,0) = 0.0;
00264   // skew(0,1) = -quad_ang(2,0);
00265   // skew(0,2) = quad_ang(1,0);
00266   // skew(1,0) = quad_ang(2,0);
00267   // skew(1,1) = 0.0;
00268   // skew(1,2) = -quad_ang(0,0);
00269   // skew(2,0) = -quad_ang(1,0);
00270   // skew(2,1) = quad_ang(0,0);
00271   // skew(2,2) = 0.0;
00272 
00273   // Eigen::MatrixXd quad_lin = Eigen::MatrixXd::Zero(3,1);
00274   // quad_lin = (this->T_quad_to_cam_.block(0,0,3,3) * cam_lin) + (skew * T_quad_to_cam_.block(0,3,3,1));
00275 
00276   //Considering cam and quad frames witht he same origin point
00277   Eigen::MatrixXd quad_lin = Eigen::MatrixXd::Zero(3,1);
00278   quad_lin = this->T_quad_to_cam_.block(0,0,3,3) * cam_lin;
00279 
00280 
00281   Eigen::MatrixXd quad_vel = Eigen::MatrixXd::Zero(6,1);
00282   quad_vel.block(0,0,3,1) = quad_lin;
00283   quad_vel.block(3,0,3,1) = quad_ang;
00284 
00285   return quad_vel;
00286 }
00287 
00288 Eigen::Matrix4d KintonVsControlAlgNode::getTransform(const tf::StampedTransform& transform)
00289 {
00290 
00291   double roll,pitch,yaw;
00292   tf::Quaternion q =  transform.getRotation();
00293   tf::Matrix3x3(q).getRPY(roll,pitch,yaw); 
00294 
00295   Eigen::Matrix3d Rot;
00296   Rot = Eigen::AngleAxisd(yaw, Eigen::Vector3d::UnitZ()) \
00297       * Eigen::AngleAxisd(pitch, Eigen::Vector3d::UnitY()) \
00298       * Eigen::AngleAxisd(roll, Eigen::Vector3d::UnitX());
00299   Eigen::Matrix4d T = Eigen::Matrix4d::Zero();
00300 
00301   T.block(0,0,3,3) = Rot;
00302   T(0,3) = transform.getOrigin().x();
00303   T(1,3) = transform.getOrigin().y();
00304   T(2,3) = transform.getOrigin().z();
00305   T(3,3) = 1.0;  
00306 
00307   //ROS_INFO("x: %f y: %f z: %f roll: %f, pitch: %f, yaw: %f",transform.getOrigin().x(),transform.getOrigin().y(),transform.getOrigin().z(),roll,pitch,yaw);
00308 
00309   return T;
00310 }
00311 
00312 Eigen::MatrixXd KintonVsControlAlgNode::signal_adapt(const Eigen::MatrixXd& cmd_raw)
00313 {
00314 
00315   Eigen::MatrixXd cmd = Eigen::MatrixXd::Zero(4,1);
00316 
00317   //ROLL (trimmer and saturations)
00318   cmd(0,0) = cmd_raw(0,0)-this->trimm_y_;
00319   if (cmd(0,0) > this->rollpitch_sat_max_) cmd(0,0) = this->rollpitch_sat_max_;
00320   if (cmd(0,0) < this->rollpitch_sat_min_) cmd(0,0) = this->rollpitch_sat_min_;
00321 
00322   //PITCH (trimmer and saturations)
00323   cmd(1,0) = cmd_raw(1,0)-this->trimm_x_;
00324   if (cmd(1,0) > this->rollpitch_sat_max_) cmd(1,0) = this->rollpitch_sat_max_;
00325   if (cmd(1,0) < this->rollpitch_sat_min_) cmd(1,0) = this->rollpitch_sat_min_;
00326 
00327   //YAW (saturations)
00328   cmd(2,0) = cmd_raw(2,0);
00329   if (cmd(2,0) > yaw_sat_max_) cmd(2,0) = this->yaw_sat_max_;
00330   if (cmd(2,0) < yaw_sat_min_) cmd(2,0) = this->yaw_sat_min_;
00331 
00332   //THRUST (offset and saturations)
00333   cmd(3,0) = cmd_raw(3,0) + this->ctrl_ref_;
00334   if (cmd(3,0) > this->sat_max_) cmd(3,0) = this->sat_max_;
00335   if (cmd(3,0) < this->sat_min_) cmd(3,0) = this->sat_min_; 
00336 
00337   return cmd;
00338 }
00339 
00340 void KintonVsControlAlgNode::node_config_update(Config &config, uint32_t level)
00341 {
00342   this->alg_.lock();
00343 
00344   //signal adaptation parameters
00345   this->trimm_x_ = config.trimm_x;
00346   this->trimm_y_ = config.trimm_y;
00347   this->rollpitch_sat_min_ = config.rollpitch_sat_min;
00348   this->rollpitch_sat_max_ = config.rollpitch_sat_max;
00349   this->yaw_sat_min_ = config.yaw_sat_min;
00350   this->yaw_sat_max_ =config.yaw_sat_max;
00351   this->ctrl_ref_ = config.thrust_ctrl_ref;
00352   this->sat_min_ = config.thrust_sat_min;
00353   this->sat_max_ = config.thrust_sat_max;
00354 
00355   //Height control parameters
00356   this->nm_roll_kp_ = config.nm_roll_kp;
00357   this->nm_roll_kd_ = config.nm_roll_kd;
00358   this->nm_pitch_kp_ = config.nm_pitch_kp;
00359   this->nm_pitch_kd_ = config.nm_pitch_kd;
00360   this->nm_yaw_kp_ = config.nm_yaw_kp;
00361   this->nm_yaw_kd_ = config.nm_yaw_kd;
00362   this->nm_thrust_kp_ = config.nm_thrust_kp;
00363   this->nm_thrust_kd_ = config.nm_thrust_kd;
00364 
00365   //Emergency stop external signal
00366   this->estop_=config.EMERGENCY_STOP;
00367   this->alg_.unlock();
00368 }
00369 
00370 void KintonVsControlAlgNode::addNodeDiagnostics(void)
00371 {
00372 }
00373 
00374 /* main function */
00375 int main(int argc,char *argv[])
00376 {
00377   return algorithm_base::main<KintonVsControlAlgNode>(argc, argv, "kinton_vs_control_alg_node");
00378 }


kinton_vs_control
Author(s): asantamaria
autogenerated on Fri Dec 6 2013 23:24:19