cob_trajectory_controller.cpp
Go to the documentation of this file.
00001 
00062 #include "ros/ros.h"
00063 #include <sensor_msgs/JointState.h>
00064 #include <control_msgs/JointTrajectoryControllerState.h>
00065 #include <actionlib/server/simple_action_server.h>
00066 #include <control_msgs/FollowJointTrajectoryAction.h>
00067 
00068 #include <brics_actuator/JointVelocities.h>
00069 #include <cob_trajectory_controller/genericArmCtrl.h>
00070 // ROS service includes
00071 #include <cob_srvs/Trigger.h>
00072 #include <cob_srvs/SetOperationMode.h>
00073 #include <cob_trajectory_controller/SetFloat.h>
00074 
00075 
00076 #define HZ 100
00077 
00078 class cob_trajectory_controller_node
00079 {
00080 private:
00081     ros::NodeHandle n_;
00082 
00083     ros::Publisher joint_vel_pub_;
00084     ros::Subscriber controller_state_;
00085         ros::Subscriber operation_mode_;
00086         ros::ServiceServer srvServer_Stop_;
00087     ros::ServiceServer srvServer_SetVel_;
00088     ros::ServiceServer srvServer_SetAcc_;
00089         ros::ServiceClient srvClient_SetOperationMode;
00090 
00091     actionlib::SimpleActionServer<control_msgs::FollowJointTrajectoryAction> as_follow_;
00092  
00093   
00094     //std::string action_name_;
00095     std::string action_name_follow_;    
00096     std::string current_operation_mode_;
00097     XmlRpc::XmlRpcValue JointNames_param_;
00098     std::vector<std::string> JointNames_;
00099     bool executing_;
00100     bool failure_;
00101     bool rejected_;
00102   bool preemted_;
00103     int DOF;
00104     double velocity_timeout_;
00105 
00106         int watchdog_counter;
00107     genericArmCtrl* traj_generator_;
00108     trajectory_msgs::JointTrajectory traj_;
00109     trajectory_msgs::JointTrajectory traj_2_;
00110     std::vector<double> q_current, startposition_, joint_distance_;
00111 
00112 public:
00113 
00114 
00115     cob_trajectory_controller_node():
00116     //as_(n_, "joint_trajectory_action", boost::bind(&cob_trajectory_controller_node::executeTrajectory, this, _1), true),
00117     as_follow_(n_, "follow_joint_trajectory", boost::bind(&cob_trajectory_controller_node::executeFollowTrajectory, this, _1), true),
00118     //action_name_("joint_trajectory_action"),
00119     action_name_follow_("follow_joint_trajectory")
00120  
00121     {
00122                 joint_vel_pub_ = n_.advertise<brics_actuator::JointVelocities>("command_vel", 1);
00123         controller_state_ = n_.subscribe("state", 1, &cob_trajectory_controller_node::state_callback, this);
00124                 operation_mode_ = n_.subscribe("current_operationmode", 1, &cob_trajectory_controller_node::operationmode_callback, this);
00125                 srvServer_Stop_ = n_.advertiseService("stop", &cob_trajectory_controller_node::srvCallback_Stop, this);
00126         srvServer_SetVel_ = n_.advertiseService("set_joint_velocity", &cob_trajectory_controller_node::srvCallback_setVel, this);
00127         srvServer_SetAcc_ = n_.advertiseService("set_joint_acceleration", &cob_trajectory_controller_node::srvCallback_setAcc, this);
00128                 srvClient_SetOperationMode = n_.serviceClient<cob_srvs::SetOperationMode>("set_operation_mode");
00129                 while(!srvClient_SetOperationMode.exists())
00130                   {
00131                     ROS_INFO("Waiting for operationmode service to become available");
00132                       sleep(1);
00133                   }
00134         executing_ = false;
00135         failure_ = false;
00136         rejected_ = false;
00137         preemted_ = false;
00138                 watchdog_counter = 0;
00139                 current_operation_mode_ = "undefined";
00140                 double PTPvel = 0.7;
00141                 double PTPacc = 0.2;
00142                 double maxError = 0.7;
00143                 double overlap_time = 0.4;
00144         velocity_timeout_ = 2.0;
00145                 DOF = 7;
00146                 // get JointNames from parameter server
00147                 ROS_INFO("getting JointNames from parameter server");
00148                 if (n_.hasParam("joint_names"))
00149                 {
00150                         n_.getParam("joint_names", JointNames_param_);
00151                 }
00152                 else
00153                 {
00154                         ROS_ERROR("Parameter joint_names not set");
00155                 }
00156                 JointNames_.resize(JointNames_param_.size());
00157                 for (int i = 0; i<JointNames_param_.size(); i++ )
00158                 {
00159                         JointNames_[i] = (std::string)JointNames_param_[i];
00160                 }
00161                 DOF = JointNames_param_.size();
00162                 if (n_.hasParam("ptp_vel"))
00163                 {
00164                         n_.getParam("ptp_vel", PTPvel);
00165                 }
00166                 if (n_.hasParam("ptp_acc"))
00167                 {
00168                         n_.getParam("ptp_acc", PTPacc);
00169                 }
00170                 if (n_.hasParam("max_error"))
00171                 {
00172                         n_.getParam("max_error", maxError);
00173                 }
00174                 if (n_.hasParam("overlap_time"))
00175                   {
00176                     n_.getParam("overlap_time", overlap_time);
00177                   }
00178                 q_current.resize(DOF);
00179                 ROS_INFO("starting controller with DOF: %d PTPvel: %f PTPAcc: %f maxError %f", DOF, PTPvel, PTPacc, maxError);
00180                 traj_generator_ = new genericArmCtrl(DOF, PTPvel, PTPacc, maxError);
00181                 traj_generator_->overlap_time = overlap_time;
00182         }
00183 
00184   double getFrequency()
00185   {
00186     double frequency;
00187       if (n_.hasParam("frequency"))                                                                   
00188       {                                                                                                     
00189         n_.getParam("frequency", frequency);                                                              
00190         ROS_INFO("Setting controller frequency to %f HZ", frequency);                                       
00191       }                                                                                                     
00192     else                                                                                                    
00193       {                                                                                                     
00194         frequency = 100; //Hz                                                                               
00195         ROS_WARN("Parameter frequency not available, setting to default value: %f Hz", frequency);          
00196         }
00197       return frequency;
00198   }
00199 
00200         bool srvCallback_Stop(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00201         {
00202                 ROS_INFO("Stopping trajectory controller.");
00203 
00204                 // stop trajectory controller
00205                 executing_ = false;
00206                 res.success.data = true;
00207                 traj_generator_->isMoving = false;
00208                 //as_.setPreemted();
00209                 failure_ = true;
00210                 return true;
00211         }
00212     bool srvCallback_setVel(cob_trajectory_controller::SetFloat::Request &req, cob_trajectory_controller::SetFloat::Response &res)
00213     {
00214         ROS_INFO("Setting velocity to %f", req.value.data);
00215         traj_generator_->SetPTPvel(req.value.data);
00216         res.success.data = true;
00217         return true;
00218     }
00219     bool srvCallback_setAcc(cob_trajectory_controller::SetFloat::Request &req, cob_trajectory_controller::SetFloat::Response &res)
00220     {
00221         ROS_INFO("Setting acceleration to %f", req.value.data);
00222         traj_generator_->SetPTPacc(req.value.data);
00223         res.success.data = true;
00224         return true;
00225     }
00226 
00227   void operationmode_callback(const std_msgs::StringPtr& message)
00228   {
00229     current_operation_mode_ = message->data;
00230   }
00231   void state_callback(const control_msgs::JointTrajectoryControllerStatePtr& message)
00232   {
00233     std::vector<double> positions = message->actual.positions;
00234     for(unsigned int i = 0; i < positions.size(); i++)
00235     {
00236       q_current[i] = positions[i];
00237     }
00238   }
00239 
00240   void spawnTrajector(trajectory_msgs::JointTrajectory trajectory)
00241   {
00242     if(!executing_ || preemted_)
00243         {
00244            //set component to velocity mode
00245           cob_srvs::SetOperationMode opmode;
00246           opmode.request.operation_mode.data = "velocity";
00247           srvClient_SetOperationMode.call(opmode);
00248           ros::Time begin = ros::Time::now();
00249           while(current_operation_mode_ != "velocity")
00250           {
00251              ROS_INFO("waiting for component to go to velocity mode");
00252              usleep(100000);
00253              //add timeout and set action to rejected
00254              if((ros::Time::now() - begin).toSec() > velocity_timeout_)
00255                                 {
00256                rejected_ = true;
00257                return;
00258                                 }  
00259             }
00260 
00261           std::vector<double> traj_start;
00262           if(preemted_ == true) //Calculate trajectory for runtime modification of trajectories
00263             {
00264               ROS_INFO("There is a old trajectory currently running");
00265               traj_start = traj_generator_->last_q;
00266               trajectory_msgs::JointTrajectory temp_traj;
00267                   temp_traj = trajectory;
00268                   //Insert the saved point as first point of trajectory, then generate SPLINE trajectory
00269                   trajectory_msgs::JointTrajectoryPoint p;
00270                   p.positions.resize(DOF);
00271                   p.velocities.resize(DOF);
00272                   p.accelerations.resize(DOF);
00273                   for(int i = 0; i<DOF; i++)
00274                   {
00275                           p.positions.at(i) = traj_start.at(i);
00276                           p.velocities.at(i) = 0.0;
00277                           p.accelerations.at(i) = 0.0;
00278                   }
00279                   std::vector<trajectory_msgs::JointTrajectoryPoint>::iterator it;
00280                   it = temp_traj.points.begin();
00281                   temp_traj.points.insert(it,p);
00282                   //Now insert the current as first point of trajectory, then generate SPLINE trajectory
00283                   for(int i = 0; i<DOF; i++)
00284                   {
00285                           p.positions.at(i) = traj_generator_->last_q1.at(i);
00286                           p.velocities.at(i) = 0.0;
00287                           p.accelerations.at(i) = 0.0;
00288                   }
00289                   it = temp_traj.points.begin();
00290                   temp_traj.points.insert(it,p);
00291                   for(int i = 0; i<DOF; i++)
00292                   {
00293                           p.positions.at(i) = traj_generator_->last_q2.at(i);
00294                           p.velocities.at(i) = 0.0;
00295                           p.accelerations.at(i) = 0.0;
00296                   }
00297                   it = temp_traj.points.begin();
00298                   temp_traj.points.insert(it,p);
00299                   for(int i = 0; i<DOF; i++)
00300                   {
00301                           p.positions.at(i) = traj_generator_->last_q3.at(i);
00302                           p.velocities.at(i) = 0.0;
00303                           p.accelerations.at(i) = 0.0;
00304                   }
00305                   it = temp_traj.points.begin();
00306                   temp_traj.points.insert(it,p);
00307                   for(int i = 0; i<DOF; i++)
00308                   {
00309                           p.positions.at(i) = q_current.at(i);
00310                           p.velocities.at(i) = 0.0;
00311                           p.accelerations.at(i) = 0.0;
00312                   }
00313                   it = temp_traj.points.begin();
00314                   temp_traj.points.insert(it,p);
00315                   traj_generator_->isMoving = false ;
00316                   traj_generator_->moveTrajectory(temp_traj, traj_start);
00317             }
00318           else //Normal calculation of trajectories
00319             {
00320               traj_start = q_current;
00321               trajectory_msgs::JointTrajectory temp_traj;
00322                   temp_traj = trajectory;
00323                   if(temp_traj.points.size() == 1)
00324                   {
00325                           traj_generator_->isMoving = false ;
00326                           traj_generator_->moveThetas(temp_traj.points[0].positions, traj_start);
00327                   }
00328                   else
00329                   {
00330                           //Insert the current point as first point of trajectory, then generate SPLINE trajectory
00331                           trajectory_msgs::JointTrajectoryPoint p;
00332                           p.positions.resize(DOF);
00333                           p.velocities.resize(DOF);
00334                           p.accelerations.resize(DOF);
00335                           for(int i = 0; i<DOF; i++)
00336                           {
00337                                   p.positions.at(i) = traj_start.at(i);
00338                                   p.velocities.at(i) = 0.0;
00339                                   p.accelerations.at(i) = 0.0;
00340                           }
00341                           std::vector<trajectory_msgs::JointTrajectoryPoint>::iterator it;
00342                           it = temp_traj.points.begin();
00343                           temp_traj.points.insert(it,p);
00344                           traj_generator_->isMoving = false ;
00345                           traj_generator_->moveTrajectory(temp_traj, traj_start);
00346                   }
00347             }
00348 
00349             executing_ = true;
00350             startposition_ = q_current;
00351             preemted_ = false;
00352 
00353             }
00354         else //suspend current movement and start new one
00355         {
00356         }
00357         while(executing_)
00358         {
00359           if(!preemted_)
00360             {
00361             usleep(1000);
00362             }
00363           else{
00364                   return;
00365           }
00366         }
00367 
00368         
00369   }
00370 
00371 
00372      void executeFollowTrajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal) 
00373   {
00374         ROS_INFO("Received new goal trajectory with %lu points",goal->trajectory.points.size());
00375         spawnTrajector(goal->trajectory);
00376         // only set to succeeded if component could reach position. this is currently not the care for e.g. by emergency stop, hardware error or exceeds limit.
00377         if(rejected_)
00378             as_follow_.setAborted(); //setRejected not implemented in simpleactionserver ?
00379         else
00380         {
00381             if(failure_)
00382                 as_follow_.setAborted();
00383             else
00384                 as_follow_.setSucceeded();
00385         }
00386         rejected_ = false;
00387         failure_ = false;
00388     }
00389     
00390     void run()
00391     {
00392         if(executing_)
00393         {
00394             failure_ = false;
00395                 watchdog_counter = 0;
00396                 //if (as_follow_.isPreemptRequested() || !ros::ok() || current_operation_mode_ != "velocity")
00397                         if (!ros::ok() || current_operation_mode_ != "velocity")
00398                         {
00399                                 
00400                                 // set the action state to preempted
00401                                 executing_ = false;
00402                                 traj_generator_->isMoving = false;
00403                                 //as_.setPreempted();
00404                 failure_ = true;
00405                 return;
00406                         }
00407                         if (as_follow_.isPreemptRequested())
00408                           {
00409                             
00410                             //as_follow_.setAborted()
00411                             failure_ = true;
00412                             preemted_ = true;
00413                             ROS_INFO("Preempted trajectory action");
00414                             return;
00415                           }
00416                 std::vector<double> des_vel;
00417                 if(traj_generator_->step(q_current, des_vel))
00418                 {
00419                         if(!traj_generator_->isMoving) //Finished trajectory
00420                         {
00421                                 executing_ = false;
00422                                 preemted_ = false;
00423                         }
00424                                 brics_actuator::JointVelocities target_joint_vel;
00425                                 target_joint_vel.velocities.resize(DOF);
00426                                 for(int i=0; i<DOF; i++)
00427                                 {
00428                                         target_joint_vel.velocities[i].joint_uri = JointNames_[i].c_str();
00429                                         target_joint_vel.velocities[i].unit = "rad";
00430                                         target_joint_vel.velocities[i].value = des_vel.at(i);
00431 
00432                                 }
00433 
00434                                 //send everything
00435                                 joint_vel_pub_.publish(target_joint_vel);
00436                 }
00437                 else
00438                 {
00439                         ROS_INFO("An controller error occured!");
00440                 failure_ = true;
00441                         executing_ = false;
00442                 }
00443         }
00444                 else
00445                 {       //WATCHDOG TODO: don't always send
00446                   if(watchdog_counter < 10)
00447                     {
00448                         brics_actuator::JointVelocities target_joint_vel;
00449                         target_joint_vel.velocities.resize(DOF);
00450                         for (int i = 0; i < DOF; i += 1)
00451                         {
00452                                 target_joint_vel.velocities[i].joint_uri = JointNames_[i].c_str();
00453                                 target_joint_vel.velocities[i].unit = "rad";
00454                                 target_joint_vel.velocities[i].value = 0;
00455                         }
00456                                 joint_vel_pub_.publish(target_joint_vel);
00457                         }
00458                   watchdog_counter++;
00459                 }
00460     }
00461     
00462 };
00463 
00464 
00465 
00466 int main(int argc, char ** argv)
00467 {
00468     ros::init(argc, argv, "cob_trajectory_controller");
00469 
00470     cob_trajectory_controller_node tm;
00471 
00473     double frequency = tm.getFrequency();
00474 
00475     ros::Rate loop_rate(frequency);
00476     while (ros::ok())
00477     {
00478         tm.run();
00479         ros::spinOnce();
00480         loop_rate.sleep();
00481     }  
00482         
00483 }
00484 
00485 
00486 
00487 
00488 
00489 


cob_trajectory_controller
Author(s): Alexander Bubeck
autogenerated on Tue Mar 3 2015 15:12:41