cob_trajectory_controller.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright 2017 Fraunhofer Institute for Manufacturing Engineering and Automation (IPA)
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *   http://www.apache.org/licenses/LICENSE-2.0
00009 
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 
00018 #include "ros/ros.h"
00019 #include <std_msgs/String.h>
00020 #include <std_msgs/Float64MultiArray.h>
00021 #include <sensor_msgs/JointState.h>
00022 #include <control_msgs/JointTrajectoryControllerState.h>
00023 #include <actionlib/server/simple_action_server.h>
00024 #include <control_msgs/FollowJointTrajectoryAction.h>
00025 
00026 #include <cob_trajectory_controller/genericArmCtrl.h>
00027 // ROS service includes
00028 #include <std_srvs/Trigger.h>
00029 #include <cob_srvs/SetString.h>
00030 #include <cob_srvs/SetFloat.h>
00031 
00032 
00033 #define HZ 100
00034 
00035 class cob_trajectory_controller_node
00036 {
00037 private:
00038     ros::NodeHandle n_;
00039     ros::NodeHandle n_private_;
00040 
00041     ros::Publisher joint_vel_pub_;
00042     ros::Subscriber controller_state_;
00043     ros::Subscriber operation_mode_;
00044     ros::ServiceServer srvServer_Stop_;
00045     ros::ServiceServer srvServer_SetVel_;
00046     ros::ServiceServer srvServer_SetAcc_;
00047     ros::ServiceClient srvClient_SetOperationMode;
00048 
00049     actionlib::SimpleActionServer<control_msgs::FollowJointTrajectoryAction> as_;
00050 
00051     std::string action_name_;
00052     std::string current_operation_mode_;
00053     std::vector<std::string> JointNames_;
00054     bool executing_;
00055     bool failure_;
00056     bool rejected_;
00057     bool preemted_;
00058     int DOF;
00059     double velocity_timeout_;
00060 
00061     int watchdog_counter;
00062     genericArmCtrl* traj_generator_;
00063     trajectory_msgs::JointTrajectory traj_;
00064     trajectory_msgs::JointTrajectory traj_2_;
00065     std::vector<double> q_current, startposition_, joint_distance_;
00066 
00067 public:
00068 
00069     cob_trajectory_controller_node():
00070     as_(n_, "joint_trajectory_controller/follow_joint_trajectory", boost::bind(&cob_trajectory_controller_node::executeFollowTrajectory, this, _1), false),
00071     action_name_("follow_joint_trajectory")
00072     {
00073         joint_vel_pub_ = n_.advertise<std_msgs::Float64MultiArray>("joint_group_velocity_controller/command", 1);
00074         controller_state_ = n_.subscribe("joint_trajectory_controller/state", 1, &cob_trajectory_controller_node::state_callback, this);
00075         operation_mode_ = n_.subscribe("driver/current_operationmode", 1, &cob_trajectory_controller_node::operationmode_callback, this);
00076         srvServer_Stop_ = n_.advertiseService("driver/stop", &cob_trajectory_controller_node::srvCallback_Stop, this);
00077         srvServer_SetVel_ = n_.advertiseService("driver/set_joint_velocity", &cob_trajectory_controller_node::srvCallback_setVel, this);
00078         srvServer_SetAcc_ = n_.advertiseService("driver/set_joint_acceleration", &cob_trajectory_controller_node::srvCallback_setAcc, this);
00079         srvClient_SetOperationMode = n_.serviceClient<cob_srvs::SetString>("driver/set_operation_mode");
00080         while(!srvClient_SetOperationMode.exists())
00081         {
00082             ROS_INFO("Waiting for operationmode service to become available");
00083             sleep(1);
00084         }
00085         executing_ = false;
00086         failure_ = false;
00087         rejected_ = false;
00088         preemted_ = false;
00089         watchdog_counter = 0;
00090         current_operation_mode_ = "undefined";
00091         double PTPvel = 0.7;
00092         double PTPacc = 0.2;
00093         double maxError = 0.7;
00094         double overlap_time = 0.4;
00095         velocity_timeout_ = 2.0;
00096         DOF = 7;
00097         // get JointNames from parameter server
00098         ROS_INFO("getting JointNames from parameter server: %s", n_private_.getNamespace().c_str());
00099         if (n_private_.hasParam("joint_names"))
00100         {
00101             n_private_.getParam("joint_names", JointNames_);
00102         }
00103         else
00104         {
00105             ROS_ERROR("Parameter 'joint_names' not set");
00106         }
00107         DOF = JointNames_.size();
00108 
00109         if (n_private_.hasParam("ptp_vel"))
00110         {
00111             n_private_.getParam("ptp_vel", PTPvel);
00112         }
00113         if (n_private_.hasParam("ptp_acc"))
00114         {
00115             n_private_.getParam("ptp_acc", PTPacc);
00116         }
00117         if (n_private_.hasParam("max_error"))
00118         {
00119             n_private_.getParam("max_error", maxError);
00120         }
00121         if (n_private_.hasParam("overlap_time"))
00122         {
00123             n_private_.getParam("overlap_time", overlap_time);
00124         }
00125         if (n_private_.hasParam("operation_mode"))
00126         {
00127             n_private_.getParam("operation_mode", current_operation_mode_);
00128         }
00129         q_current.resize(DOF);
00130         ROS_INFO("starting controller with DOF: %d PTPvel: %f PTPAcc: %f maxError %f", DOF, PTPvel, PTPacc, maxError);
00131         traj_generator_ = new genericArmCtrl(DOF, PTPvel, PTPacc, maxError);
00132         traj_generator_->overlap_time = overlap_time;
00133 
00134         as_.start();
00135     }
00136 
00137     double getFrequency()
00138     {
00139         double frequency;
00140         if (n_private_.hasParam("frequency"))
00141         {
00142             n_private_.getParam("frequency", frequency);
00143             ROS_INFO("Setting controller frequency to %f HZ", frequency);
00144         }
00145         else
00146         {
00147             frequency = 100; //Hz
00148             ROS_WARN("Parameter 'frequency' not available, setting to default value: %f Hz", frequency);
00149         }
00150         return frequency;
00151     }
00152 
00153     bool srvCallback_Stop(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
00154     {
00155         ROS_INFO("Stopping trajectory controller.");
00156 
00157         // stop trajectory controller
00158         executing_ = false;
00159         res.success = true;
00160         traj_generator_->isMoving = false;
00161         failure_ = true;
00162         return true;
00163     }
00164 
00165     bool srvCallback_setVel(cob_srvs::SetFloat::Request &req, cob_srvs::SetFloat::Response &res)
00166     {
00167         ROS_INFO("Setting velocity to %f", req.data);
00168         traj_generator_->SetPTPvel(req.data);
00169         res.success = true;
00170         return true;
00171     }
00172 
00173     bool srvCallback_setAcc(cob_srvs::SetFloat::Request &req, cob_srvs::SetFloat::Response &res)
00174     {
00175         ROS_INFO("Setting acceleration to %f", req.data);
00176         traj_generator_->SetPTPacc(req.data);
00177         res.success = true;
00178         return true;
00179     }
00180 
00181     void operationmode_callback(const std_msgs::StringPtr& message)
00182     {
00183         current_operation_mode_ = message->data;
00184     }
00185 
00186     void state_callback(const control_msgs::JointTrajectoryControllerStatePtr& message)
00187     {
00188         std::vector<double> positions = message->actual.positions;
00189         for(unsigned int i = 0; i < positions.size(); i++)
00190         {
00191             q_current[i] = positions[i];
00192         }
00193     }
00194 
00195     void spawnTrajector(trajectory_msgs::JointTrajectory trajectory)
00196     {
00197         if(!executing_ || preemted_)
00198         {
00199             //set component to velocity mode
00200             cob_srvs::SetString opmode;
00201             opmode.request.data = "velocity";
00202             srvClient_SetOperationMode.call(opmode);
00203             ros::Time begin = ros::Time::now();
00204             while(current_operation_mode_ != "velocity")
00205             {
00206                 ROS_INFO("waiting for component to go to velocity mode");
00207                 usleep(100000);
00208                 //add timeout and set action to rejected
00209                 if((ros::Time::now() - begin).toSec() > velocity_timeout_)
00210                 {
00211                     rejected_ = true;
00212                     return;
00213                 }
00214             }
00215 
00216             std::vector<double> traj_start;
00217             if(preemted_ == true) //Calculate trajectory for runtime modification of trajectories
00218             {
00219                 ROS_INFO("There is a old trajectory currently running");
00220                 traj_start = traj_generator_->last_q;
00221                 trajectory_msgs::JointTrajectory temp_traj;
00222                 temp_traj = trajectory;
00223                 //Insert the saved point as first point of trajectory, then generate SPLINE trajectory
00224                 trajectory_msgs::JointTrajectoryPoint p;
00225                 p.positions.resize(DOF);
00226                 p.velocities.resize(DOF);
00227                 p.accelerations.resize(DOF);
00228                 for(int i = 0; i<DOF; i++)
00229                 {
00230                     p.positions.at(i) = traj_start.at(i);
00231                     p.velocities.at(i) = 0.0;
00232                     p.accelerations.at(i) = 0.0;
00233                 }
00234                 std::vector<trajectory_msgs::JointTrajectoryPoint>::iterator it;
00235                 it = temp_traj.points.begin();
00236                 temp_traj.points.insert(it,p);
00237                 //Now insert the current as first point of trajectory, then generate SPLINE trajectory
00238                 for(int i = 0; i<DOF; i++)
00239                 {
00240                     p.positions.at(i) = traj_generator_->last_q1.at(i);
00241                     p.velocities.at(i) = 0.0;
00242                     p.accelerations.at(i) = 0.0;
00243                 }
00244                 it = temp_traj.points.begin();
00245                 temp_traj.points.insert(it,p);
00246                 for(int i = 0; i<DOF; i++)
00247                 {
00248                     p.positions.at(i) = traj_generator_->last_q2.at(i);
00249                     p.velocities.at(i) = 0.0;
00250                     p.accelerations.at(i) = 0.0;
00251                 }
00252                 it = temp_traj.points.begin();
00253                 temp_traj.points.insert(it,p);
00254                 for(int i = 0; i<DOF; i++)
00255                 {
00256                     p.positions.at(i) = traj_generator_->last_q3.at(i);
00257                     p.velocities.at(i) = 0.0;
00258                     p.accelerations.at(i) = 0.0;
00259                 }
00260                 it = temp_traj.points.begin();
00261                 temp_traj.points.insert(it,p);
00262                 for(int i = 0; i<DOF; i++)
00263                 {
00264                     p.positions.at(i) = q_current.at(i);
00265                     p.velocities.at(i) = 0.0;
00266                     p.accelerations.at(i) = 0.0;
00267                 }
00268                 it = temp_traj.points.begin();
00269                 temp_traj.points.insert(it,p);
00270                 traj_generator_->isMoving = false ;
00271                 traj_generator_->moveTrajectory(temp_traj, traj_start);
00272             }
00273             else //Normal calculation of trajectories
00274             {
00275                 traj_start = q_current;
00276                 trajectory_msgs::JointTrajectory temp_traj;
00277                 temp_traj = trajectory;
00278                 if(temp_traj.points.size() == 1)
00279                 {
00280                     traj_generator_->isMoving = false ;
00281                     traj_generator_->moveThetas(temp_traj.points[0].positions, traj_start);
00282                 }
00283                 else
00284                 {
00285                     //Insert the current point as first point of trajectory, then generate SPLINE trajectory
00286                     trajectory_msgs::JointTrajectoryPoint p;
00287                     p.positions.resize(DOF);
00288                     p.velocities.resize(DOF);
00289                     p.accelerations.resize(DOF);
00290                     for(int i = 0; i<DOF; i++)
00291                     {
00292                         p.positions.at(i) = traj_start.at(i);
00293                         p.velocities.at(i) = 0.0;
00294                         p.accelerations.at(i) = 0.0;
00295                     }
00296                     std::vector<trajectory_msgs::JointTrajectoryPoint>::iterator it;
00297                     it = temp_traj.points.begin();
00298                     temp_traj.points.insert(it,p);
00299                     traj_generator_->isMoving = false ;
00300                     traj_generator_->moveTrajectory(temp_traj, traj_start);
00301                 }
00302             }
00303 
00304             executing_ = true;
00305             startposition_ = q_current;
00306             preemted_ = false;
00307 
00308         }
00309         else //suspend current movement and start new one
00310         {
00311         }
00312         while(executing_)
00313         {
00314             if(!preemted_)
00315             {
00316                 usleep(1000);
00317             }
00318             else
00319             {
00320                 return;
00321             }
00322         }
00323     }
00324 
00325 
00326     void executeFollowTrajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
00327     {
00328         ROS_INFO("Received new goal trajectory with %lu points",goal->trajectory.points.size());
00329         spawnTrajector(goal->trajectory);
00330         // 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.
00331         if(rejected_)
00332             as_.setAborted(); //setRejected not implemented in simpleactionserver ?
00333         else
00334         {
00335             if(failure_)
00336                 as_.setAborted();
00337             else
00338                 as_.setSucceeded();
00339         }
00340         rejected_ = false;
00341         failure_ = false;
00342     }
00343 
00344     void run()
00345     {
00346         if(executing_)
00347         {
00348             failure_ = false;
00349             watchdog_counter = 0;
00350             if (!ros::ok() || current_operation_mode_ != "velocity")
00351             {
00352                 // set the action state to preempted
00353                 executing_ = false;
00354                 traj_generator_->isMoving = false;
00355                 failure_ = true;
00356                 return;
00357             }
00358             if (as_.isPreemptRequested())
00359             {
00360                 failure_ = true;
00361                 preemted_ = true;
00362                 executing_ = false;
00363                 traj_generator_->isMoving = false;
00364                 ROS_INFO("Preempted trajectory action");
00365                 return;
00366             }
00367             std::vector<double> des_vel;
00368             if(traj_generator_->step(q_current, des_vel))
00369             {
00370                 if(!traj_generator_->isMoving) //Finished trajectory
00371                 {
00372                     executing_ = false;
00373                     preemted_ = false;
00374                 }
00375                 std_msgs::Float64MultiArray target_joint_vel;
00376                 for(int i=0; i<DOF; i++)
00377                 {
00378                     target_joint_vel.data.push_back(des_vel.at(i));
00379                 }
00380 
00381                 //send everything
00382                 joint_vel_pub_.publish(target_joint_vel);
00383             }
00384             else
00385             {
00386                 ROS_INFO("An controller error occured!");
00387                 failure_ = true;
00388                 executing_ = false;
00389             }
00390         }
00391         else
00392         {   //WATCHDOG TODO: don't always send
00393             if(watchdog_counter < 10)
00394             {
00395                 std_msgs::Float64MultiArray target_joint_vel;
00396                 for(int i=0; i<DOF; i++)
00397                 {
00398                     target_joint_vel.data.push_back(0.0);
00399                 }
00400                 joint_vel_pub_.publish(target_joint_vel);
00401             }
00402             watchdog_counter++;
00403         }
00404     }
00405 
00406 };
00407 
00408 
00409 
00410 int main(int argc, char ** argv)
00411 {
00412     ros::init(argc, argv, "cob_trajectory_controller");
00413 
00414     cob_trajectory_controller_node tm;
00415 
00417     double frequency = tm.getFrequency();
00418 
00419     ros::Rate loop_rate(frequency);
00420     while (ros::ok())
00421     {
00422         tm.run();
00423         ros::spinOnce();
00424         loop_rate.sleep();
00425     }
00426 }
00427 
00428 
00429 


cob_trajectory_controller
Author(s): Alexander Bubeck
autogenerated on Thu Jun 6 2019 21:19:22