cob_trajectory_controller_sim.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 joint_state_sub_;
00085     ros::Subscriber controller_state_;
00086     ros::Subscriber operation_mode_;
00087     ros::ServiceServer srvServer_Stop_;
00088     ros::ServiceServer srvServer_SetVel_;
00089     ros::ServiceServer srvServer_SetAcc_;
00090     ros::ServiceClient srvClient_SetOperationMode;
00091 
00092     actionlib::SimpleActionServer<control_msgs::FollowJointTrajectoryAction> as_follow_;
00093  
00094   
00095     //std::string action_name_;
00096     std::string action_name_follow_;  
00097     std::string current_operation_mode_;
00098     XmlRpc::XmlRpcValue JointNames_param_;
00099     std::vector<std::string> JointNames_;
00100     bool executing_;
00101     bool failure_;
00102     bool rejected_;
00103     bool preemted_;
00104     int DOF;
00105     double velocity_timeout_;
00106 
00107     int watchdog_counter;
00108     genericArmCtrl* traj_generator_;
00109     trajectory_msgs::JointTrajectory traj_;
00110     trajectory_msgs::JointTrajectory traj_2_;
00111     std::vector<double> q_current, startposition_, joint_distance_;
00112 
00113 public:
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         joint_vel_pub_ = n_.advertise<brics_actuator::JointVelocities>("command_vel", 1);
00122         joint_state_sub_ = n_.subscribe("/joint_states", 1, &cob_trajectory_controller_node::joint_state_callback, this);
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     
00213     bool srvCallback_setVel(cob_trajectory_controller::SetFloat::Request &req, cob_trajectory_controller::SetFloat::Response &res)
00214     {
00215         ROS_INFO("Setting velocity to %f", req.value.data);
00216         traj_generator_->SetPTPvel(req.value.data);
00217         res.success.data = true;
00218         return true;
00219     }
00220     
00221     bool srvCallback_setAcc(cob_trajectory_controller::SetFloat::Request &req, cob_trajectory_controller::SetFloat::Response &res)
00222     {
00223         ROS_INFO("Setting acceleration to %f", req.value.data);
00224         traj_generator_->SetPTPacc(req.value.data);
00225         res.success.data = true;
00226         return true;
00227     }
00228 
00229     void operationmode_callback(const std_msgs::StringPtr& message)
00230     {
00231         ROS_INFO("Setting operation_mode: %s", (message->data).c_str());
00232         current_operation_mode_ = message->data;
00233     }
00234     
00235     void state_callback(const control_msgs::JointTrajectoryControllerStatePtr& message)
00236     {
00237         std::vector<double> positions = message->actual.positions;
00238         for(unsigned int i = 0; i < positions.size(); i++)
00239         {
00240             q_current[i] = positions[i];
00241         }
00242     }
00243     
00244     void joint_state_callback(const sensor_msgs::JointStatePtr& message)
00245     {
00246         for(unsigned int i = 0; i < message->name.size(); i++)
00247         {
00248             for(unsigned int j = 0; j < DOF; j++)
00249             {
00250                 if(message->name[i]==JointNames_[j])
00251                     q_current[j] = message->position[i];
00252             }
00253         }
00254     }
00255 
00256     void spawnTrajector(trajectory_msgs::JointTrajectory trajectory)
00257     {
00258         if(!executing_ || preemted_)
00259         {
00260             //set component to velocity mode
00261             cob_srvs::SetOperationMode opmode;
00262             opmode.request.operation_mode.data = "velocity";
00263             srvClient_SetOperationMode.call(opmode);
00264             ros::Time begin = ros::Time::now();
00265             while(current_operation_mode_ != "velocity")
00266             {
00267                 ROS_INFO("waiting for component to go to velocity mode");
00268                 usleep(100000);
00269                 //add timeout and set action to rejected
00270                 if((ros::Time::now() - begin).toSec() > velocity_timeout_)
00271                 {
00272                     rejected_ = true;
00273                     return;
00274                 }  
00275             }
00276             
00277             std::vector<double> traj_start;
00278             if(preemted_ == true) //Calculate trajectory for runtime modification of trajectories
00279             {
00280                 ROS_INFO("There is a old trajectory currently running");
00281                 traj_start = traj_generator_->last_q;
00282                 trajectory_msgs::JointTrajectory temp_traj;
00283                 temp_traj = trajectory;
00284                 //Insert the saved point as first point of trajectory, then generate SPLINE trajectory
00285                 trajectory_msgs::JointTrajectoryPoint p;
00286                 p.positions.resize(DOF);
00287                 p.velocities.resize(DOF);
00288                 p.accelerations.resize(DOF);
00289                 for(int i = 0; i<DOF; i++)
00290                 {
00291                     p.positions.at(i) = traj_start.at(i);
00292                     p.velocities.at(i) = 0.0;
00293                     p.accelerations.at(i) = 0.0;
00294                 }
00295                 std::vector<trajectory_msgs::JointTrajectoryPoint>::iterator it;
00296                 it = temp_traj.points.begin();
00297                 temp_traj.points.insert(it,p);
00298                 //Now insert the current as first point of trajectory, then generate SPLINE trajectory
00299                 for(int i = 0; i<DOF; i++)
00300                 {
00301                     p.positions.at(i) = traj_generator_->last_q1.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) = traj_generator_->last_q2.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                 for(int i = 0; i<DOF; i++)
00316                 {
00317                     p.positions.at(i) = traj_generator_->last_q3.at(i);
00318                     p.velocities.at(i) = 0.0;
00319                     p.accelerations.at(i) = 0.0;
00320                 }
00321                 it = temp_traj.points.begin();
00322                 temp_traj.points.insert(it,p);
00323                 for(int i = 0; i<DOF; i++)
00324                 {
00325                     p.positions.at(i) = q_current.at(i);
00326                     p.velocities.at(i) = 0.0;
00327                     p.accelerations.at(i) = 0.0;
00328                 }
00329                 it = temp_traj.points.begin();
00330                 temp_traj.points.insert(it,p);
00331                 traj_generator_->isMoving = false ;
00332                 traj_generator_->moveTrajectory(temp_traj, traj_start);
00333             }
00334             else //Normal calculation of trajectories
00335             {
00336                 traj_start = q_current;
00337                 trajectory_msgs::JointTrajectory temp_traj;
00338                 temp_traj = trajectory;
00339                 if(temp_traj.points.size() == 1)
00340                 {
00341                     traj_generator_->isMoving = false ;
00342                     traj_generator_->moveThetas(temp_traj.points[0].positions, traj_start);
00343                 }
00344                 else
00345                 {
00346                     //Insert the current point as first point of trajectory, then generate SPLINE trajectory
00347                     trajectory_msgs::JointTrajectoryPoint p;
00348                     p.positions.resize(DOF);
00349                     p.velocities.resize(DOF);
00350                     p.accelerations.resize(DOF);
00351                     for(int i = 0; i<DOF; i++)
00352                     {
00353                         p.positions.at(i) = traj_start.at(i);
00354                         p.velocities.at(i) = 0.0;
00355                         p.accelerations.at(i) = 0.0;
00356                     }
00357                     std::vector<trajectory_msgs::JointTrajectoryPoint>::iterator it;
00358                     it = temp_traj.points.begin();
00359                     temp_traj.points.insert(it,p);
00360                     traj_generator_->isMoving = false ;
00361                     traj_generator_->moveTrajectory(temp_traj, traj_start);
00362                 }
00363             }
00364             
00365             executing_ = true;
00366             startposition_ = q_current;
00367             preemted_ = false;
00368             
00369         }
00370         else //suspend current movement and start new one
00371         {
00372         }
00373         while(executing_)
00374         {
00375             if(!preemted_)
00376             {
00377                 usleep(1000);
00378             }
00379             else
00380             {
00381                 return;
00382             }
00383         }
00384     }
00385 
00386 
00387     void executeFollowTrajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal) 
00388     {
00389         ROS_INFO("Received new goal trajectory with %lu points",goal->trajectory.points.size());
00390         spawnTrajector(goal->trajectory);
00391         // 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.
00392         if(rejected_)
00393             as_follow_.setAborted(); //setRejected not implemented in simpleactionserver ?
00394         else
00395         {
00396             if(failure_)
00397                 as_follow_.setAborted();
00398             else
00399                 as_follow_.setSucceeded();
00400         }
00401         rejected_ = false;
00402         failure_ = false;
00403     }
00404     
00405     void run()
00406     {
00407         if(executing_)
00408         {
00409             failure_ = false;
00410             watchdog_counter = 0;
00411             //if (as_follow_.isPreemptRequested() || !ros::ok() || current_operation_mode_ != "velocity")
00412             if (!ros::ok() || current_operation_mode_ != "velocity")
00413             {
00414                 // set the action state to preempted
00415                 executing_ = false;
00416                 traj_generator_->isMoving = false;
00417                 //as_.setPreempted();
00418                 failure_ = true;
00419                 return;
00420             }
00421             if (as_follow_.isPreemptRequested())
00422             {
00423                 //as_follow_.setAborted()
00424                 failure_ = true;
00425                 preemted_ = true;
00426                 ROS_INFO("Preempted trajectory action");
00427                 return;
00428             }
00429             std::vector<double> des_vel;
00430             if(traj_generator_->step(q_current, des_vel))
00431             {
00432                 if(!traj_generator_->isMoving) //Finished trajectory
00433                 {
00434                     executing_ = false;
00435                     preemted_ = false;
00436                 }
00437                 brics_actuator::JointVelocities target_joint_vel;
00438                 target_joint_vel.velocities.resize(DOF);
00439                 for(int i=0; i<DOF; i++)
00440                 {
00441                     target_joint_vel.velocities[i].joint_uri = JointNames_[i].c_str();
00442                     target_joint_vel.velocities[i].unit = "rad";
00443                     target_joint_vel.velocities[i].value = des_vel.at(i);
00444                 }
00445                 
00446                 //send everything
00447                 joint_vel_pub_.publish(target_joint_vel);
00448             }
00449             else
00450             {
00451                 ROS_INFO("An controller error occured!");
00452                 failure_ = true;
00453                 executing_ = false;
00454             }
00455         }
00456         else
00457         {  //WATCHDOG TODO: don't always send
00458             if(watchdog_counter < 10)
00459             {
00460                 brics_actuator::JointVelocities target_joint_vel;
00461                 target_joint_vel.velocities.resize(DOF);
00462                 for (int i = 0; i < DOF; i += 1)
00463                 {
00464                     target_joint_vel.velocities[i].joint_uri = JointNames_[i].c_str();
00465                     target_joint_vel.velocities[i].unit = "rad";
00466                     target_joint_vel.velocities[i].value = 0;
00467                 }
00468                 joint_vel_pub_.publish(target_joint_vel);
00469                 ROS_INFO("Publishing 0-vel (%d)", DOF);
00470             }
00471             watchdog_counter++;
00472         }
00473     }
00474     
00475 };
00476 
00477 
00478 
00479 int main(int argc, char ** argv)
00480 {
00481     ros::init(argc, argv, "cob_trajectory_controller");
00482 
00483     cob_trajectory_controller_node tm;
00484 
00486     double frequency = tm.getFrequency();
00487 
00488     ros::Rate loop_rate(frequency);
00489     while (ros::ok())
00490     {
00491         tm.run();
00492         ros::spinOnce();
00493         loop_rate.sleep();
00494     }
00495 }
00496 
00497 
00498 
00499 


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