schunk_powercube_chain.cpp
Go to the documentation of this file.
00001 
00060 //##################
00061 //#### includes ####
00062 //##################
00063 
00064 // standard includes
00065 // --
00066 
00067 // ROS includes
00068 #include <ros/ros.h>
00069 #include <urdf/model.h>
00070 
00071 // ROS message includes
00072 #include <sensor_msgs/JointState.h>
00073 #include <trajectory_msgs/JointTrajectory.h>
00074 #include <pr2_controllers_msgs/JointTrajectoryControllerState.h>
00075 #include <diagnostic_msgs/DiagnosticArray.h>
00076 #include <brics_actuator/JointPositions.h>
00077 #include <brics_actuator/JointVelocities.h>
00078 
00079 
00080 // ROS service includes
00081 #include <cob_srvs/Trigger.h>
00082 #include <cob_srvs/SetOperationMode.h>
00083 
00084 // own includes
00085 #include <schunk_powercube_chain/PowerCubeCtrl.h>
00086 #include <schunk_powercube_chain/PowerCubeCtrlParams.h>
00087 //#include <schunk_powercube_chain/Diagnostics.h>
00088 
00094 class PowerCubeChainNode
00095 {
00096 
00097 public:
00099   ros::NodeHandle n_;
00100 
00102   ros::Publisher topicPub_JointState_;
00103   ros::Publisher topicPub_ControllerState_;
00104   ros::Publisher topicPub_OperationMode_;
00105   ros::Publisher topicPub_Diagnostic_;
00106 
00108   ros::Subscriber topicSub_CommandPos_;
00109   ros::Subscriber topicSub_CommandVel_;
00110 
00112   ros::ServiceServer srvServer_Init_;
00113   ros::ServiceServer srvServer_SetOperationMode_;
00114   ros::ServiceServer srvServer_Stop_;
00115   ros::ServiceServer srvServer_Recover_;
00116 
00118   PowerCubeCtrl* pc_ctrl_;
00119 
00121   PowerCubeCtrlParams* pc_params_;
00122 
00124   bool initialized_;
00125   bool stopped_;
00126   bool error_;
00127   std::string error_msg_;
00128   ros::Time last_publish_time_;
00129 
00131   PowerCubeChainNode()
00132   {
00133         n_ = ros::NodeHandle("~");
00134 
00135     pc_params_ = new PowerCubeCtrlParams();
00136     pc_ctrl_ = new PowerCubeCtrl(pc_params_);
00137 
00139     topicPub_JointState_ = n_.advertise<sensor_msgs::JointState> ("/joint_states", 1);
00140     topicPub_ControllerState_ = n_.advertise<pr2_controllers_msgs::JointTrajectoryControllerState> ("state", 1);
00141     topicPub_OperationMode_ = n_.advertise<std_msgs::String> ("current_operationmode", 1);
00142     topicPub_Diagnostic_ = n_.advertise<diagnostic_msgs::DiagnosticArray>("/diagnostics", 1);
00143 
00145     topicSub_CommandPos_ = n_.subscribe("command_pos", 1, &PowerCubeChainNode::topicCallback_CommandPos, this);
00146     topicSub_CommandVel_ = n_.subscribe("command_vel", 1, &PowerCubeChainNode::topicCallback_CommandVel, this);
00147 
00149     srvServer_Init_ = n_.advertiseService("init", &PowerCubeChainNode::srvCallback_Init, this);
00150     srvServer_Stop_ = n_.advertiseService("stop", &PowerCubeChainNode::srvCallback_Stop, this);
00151     srvServer_Recover_ = n_.advertiseService("recover", &PowerCubeChainNode::srvCallback_Recover, this);
00152     srvServer_SetOperationMode_ = n_.advertiseService("set_operation_mode", &PowerCubeChainNode::srvCallback_SetOperationMode, this);
00153 
00154     initialized_ = false;
00155     stopped_ = true;
00156     error_ = false;
00157     last_publish_time_ = ros::Time::now();
00158   }
00159 
00161   ~PowerCubeChainNode()
00162   {
00163           bool closed = pc_ctrl_->Close();
00164           if (closed)
00165       ROS_INFO("PowerCube Device closed!");
00166   }
00167 
00171   void getROSParameters()
00172   {
00173 
00175     std::string CanModule;
00176     if (n_.hasParam("can_module"))
00177     {
00178         n_.getParam("can_module", CanModule);
00179     }
00180 
00181     else
00182     {
00183         ROS_ERROR("Parameter can_module not set, shutting down node...");
00184                 n_.shutdown();
00185     }
00186 
00188     std::string CanDevice;
00189     if (n_.hasParam("can_device"))
00190     {
00191         n_.getParam("can_device", CanDevice);
00192     }
00193 
00194     else
00195     {
00196         ROS_ERROR("Parameter can_device not set, shutting down node...");
00197                   n_.shutdown();
00198     }
00199 
00201     int CanBaudrate;
00202     if (n_.hasParam("can_baudrate"))
00203     {
00204         n_.getParam("can_baudrate", CanBaudrate);
00205     }
00206     else
00207     {
00208         ROS_ERROR("Parameter can_baudrate not set, shutting down node...");
00209         n_.shutdown();
00210     }
00211 
00213     XmlRpc::XmlRpcValue ModulIDsXmlRpc;
00214     std::vector<int> ModulIDs;
00215     if (n_.hasParam("modul_ids"))
00216     {
00217         n_.getParam("modul_ids", ModulIDsXmlRpc);
00218     }
00219 
00220     else
00221     {
00222         ROS_ERROR("Parameter modul_ids not set, shutting down node...");
00223         n_.shutdown();
00224     }
00225 
00227     bool UseMoveVel;
00228     if (n_.hasParam("force_use_movevel"))
00229     {
00230         n_.getParam("force_use_movevel", UseMoveVel);
00231                 ROS_INFO("Parameter force_use_movevel set, using moveVel");
00232     }
00233     else
00234     {
00235         ROS_INFO("Parameter force_use_movevel not set, using moveStep");
00236                 UseMoveVel = false;
00237     }
00238         pc_params_->SetUseMoveVel(UseMoveVel);
00239 
00241     ModulIDs.resize(ModulIDsXmlRpc.size());
00242     for (int i = 0; i < ModulIDsXmlRpc.size(); i++)
00243     {
00244         ModulIDs[i] = (int)ModulIDsXmlRpc[i];
00245     }
00246 
00248     pc_params_->Init(CanModule, CanDevice, CanBaudrate, ModulIDs);
00249 
00251     XmlRpc::XmlRpcValue JointNamesXmlRpc;
00252     std::vector<std::string> JointNames;
00253     if (n_.hasParam("joint_names"))
00254     {
00255         n_.getParam("joint_names", JointNamesXmlRpc);
00256     }
00257 
00258     else
00259     {
00260         ROS_ERROR("Parameter joint_names not set, shutting down node...");
00261         n_.shutdown();
00262     }
00263 
00265     JointNames.resize(JointNamesXmlRpc.size());
00266     for (int i = 0; i < JointNamesXmlRpc.size(); i++)
00267     {
00268         JointNames[i] = (std::string)JointNamesXmlRpc[i];
00269     }
00270 
00272     if ((int)JointNames.size() != pc_params_->GetDOF())
00273     {
00274         ROS_ERROR("Wrong dimensions of parameter joint_names, shutting down node...");
00275         n_.shutdown();
00276     }
00277     pc_params_->SetJointNames(JointNames);
00278 
00280     XmlRpc::XmlRpcValue MaxAccelerationsXmlRpc;
00281     std::vector<double> MaxAccelerations;
00282     if (n_.hasParam("max_accelerations"))
00283     {
00284         n_.getParam("max_accelerations", MaxAccelerationsXmlRpc);
00285     }
00286 
00287     else
00288     {
00289         ROS_ERROR("Parameter max_accelerations not set, shutting down node...");
00290         n_.shutdown();
00291     }
00292 
00294     MaxAccelerations.resize(MaxAccelerationsXmlRpc.size());
00295     for (int i = 0; i < MaxAccelerationsXmlRpc.size(); i++)
00296     {
00297         MaxAccelerations[i] = (double)MaxAccelerationsXmlRpc[i];
00298     }
00299 
00301     if ((int)MaxAccelerations.size() != pc_params_->GetDOF())
00302     {
00303         ROS_ERROR("Wrong dimensions of parameter max_accelerations, shutting down node...");
00304         n_.shutdown();
00305     }
00306     pc_params_->SetMaxAcc(MaxAccelerations);
00307 
00309     double Horizon;
00310     if (n_.hasParam("horizon"))
00311     {
00312         n_.getParam("horizon", Horizon);
00313     }
00314 
00315     else
00316     {
00318         Horizon = 0.05;
00319         ROS_WARN("Parameter horizon not available, setting to default value: %f sec", Horizon);
00320     }
00321     pc_ctrl_->setHorizon(Horizon);
00322   }
00323 
00327   void getRobotDescriptionParameters()
00328   {
00329           unsigned int DOF = pc_params_->GetDOF();
00330           std::vector<std::string> JointNames = pc_params_->GetJointNames();
00331 
00333           std::string param_name = "robot_description";
00334           std::string full_param_name;
00335           std::string xml_string;
00336           n_.searchParam(param_name, full_param_name);
00337           if (n_.hasParam(full_param_name))
00338           {
00339                   n_.getParam(full_param_name.c_str(), xml_string);
00340           }
00341 
00342           else
00343           {
00344                   ROS_ERROR("Parameter %s not set, shutting down node...", full_param_name.c_str());
00345                   n_.shutdown();
00346           }
00347 
00348           if (xml_string.size() == 0)
00349           {
00350                   ROS_ERROR("Unable to load robot model from parameter %s",full_param_name.c_str());
00351                   n_.shutdown();
00352           }
00353           ROS_DEBUG("%s content\n%s", full_param_name.c_str(), xml_string.c_str());
00354 
00356           urdf::Model model;
00357           if (!model.initString(xml_string))
00358           {
00359                   ROS_ERROR("Failed to parse urdf file");
00360                   n_.shutdown();
00361           }
00362           ROS_DEBUG("Successfully parsed urdf file");
00363 
00365           std::vector<double> MaxVelocities(DOF);
00366           for (unsigned int i = 0; i < DOF; i++)
00367           {
00368                   MaxVelocities[i] = model.getJoint(JointNames[i].c_str())->limits->velocity;
00369           }
00370 
00372           std::vector<double> LowerLimits(DOF);
00373           for (unsigned int i = 0; i < DOF; i++)
00374           {
00375                   LowerLimits[i] = model.getJoint(JointNames[i].c_str())->limits->lower;
00376           }
00377 
00378           // Get upper limits out of urdf model
00379           std::vector<double> UpperLimits(DOF);
00380           for (unsigned int i = 0; i < DOF; i++)
00381           {
00382                   UpperLimits[i] = model.getJoint(JointNames[i].c_str())->limits->upper;
00383           }
00384 
00386           std::vector<double> Offsets(DOF);
00387           for (unsigned int i = 0; i < DOF; i++)
00388           {
00389                   Offsets[i] = model.getJoint(JointNames[i].c_str())->calibration->rising.get()[0];
00390           }
00391 
00393           pc_params_->SetMaxVel(MaxVelocities);
00394           pc_params_->SetLowerLimits(LowerLimits);
00395           pc_params_->SetUpperLimits(UpperLimits);
00396           pc_params_->SetOffsets(Offsets);
00397   }
00398 
00405   void topicCallback_CommandPos(const brics_actuator::JointPositions::ConstPtr& msg)
00406   {
00407           ROS_WARN("Received new position command. Skipping command: Position commands currently not implemented");
00408   }
00409 
00416   void topicCallback_CommandVel(const brics_actuator::JointVelocities::ConstPtr& msg)
00417   {
00418           ROS_DEBUG("Received new velocity command");
00419           if (!initialized_)
00420           {     
00421                         ROS_WARN("Skipping command: powercubes not initialized");
00422                         publishState(false);
00423                         return; 
00424                 }
00425                 
00426                 if (pc_ctrl_->getPC_Status() != PowerCubeCtrl::PC_CTRL_OK)
00427                 {
00428                         publishState(false);
00429                         return; 
00430                 }
00431 
00432  
00433           PowerCubeCtrl::PC_CTRL_STATUS status;
00434           std::vector<std::string> errorMessages;
00435           pc_ctrl_->getStatus(status, errorMessages);
00436 
00438 
00439           unsigned int DOF = pc_params_->GetDOF();
00440           std::vector<std::string> jointNames = pc_params_->GetJointNames();
00441           std::vector<double> cmd_vel(DOF);
00442           std::string unit = "rad";
00443 
00445           if (msg->velocities.size() != DOF)
00446           {
00447                   ROS_ERROR("Skipping command: Commanded velocities and DOF are not same dimension.");
00448                   return;
00449           }
00450 
00452           for (unsigned int i = 0; i < DOF; i++)
00453           {
00455                   if (msg->velocities[i].joint_uri != jointNames[i])
00456                   {
00457                           ROS_ERROR("Skipping command: Received joint name %s doesn't match expected joint name %s for joint %d.",msg->velocities[i].joint_uri.c_str(),jointNames[i].c_str(),i);
00458                           return;
00459                   }
00460 
00462                   if (msg->velocities[i].unit != unit)
00463                   {
00464                           ROS_ERROR("Skipping command: Received unit %s doesn't match expected unit %s.",msg->velocities[i].unit.c_str(),unit.c_str());
00465                           return;
00466                   }
00467 
00469                   ROS_DEBUG("Parsing velocity %f for joint %s",msg->velocities[i].value,jointNames[i].c_str());
00470                   cmd_vel[i] = msg->velocities[i].value;
00471           }
00472                 
00474           if (!pc_ctrl_->MoveVel(cmd_vel))
00475           {
00476         error_ = true;
00477                         error_msg_ = pc_ctrl_->getErrorMessage();
00478                   ROS_ERROR("Skipping command: %s",pc_ctrl_->getErrorMessage().c_str());
00479                   return;
00480           }
00481 
00482           ROS_DEBUG("Executed velocity command");
00483          
00484           publishState(false);
00485   }
00486 
00494   bool srvCallback_Init(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00495   {
00496           if (!initialized_)
00497           {
00498                   ROS_INFO("Initializing powercubes...");
00499 
00501                   if (pc_ctrl_->Init(pc_params_))
00502                   {
00503                           initialized_ = true;
00504                           res.success.data = true;
00505                           ROS_INFO("...initializing powercubes successful");
00506                   }
00507 
00508                   else
00509                   {
00510                   error_ = true;
00511                   error_msg_ = pc_ctrl_->getErrorMessage();
00512                           res.success.data = false;
00513                           res.error_message.data = pc_ctrl_->getErrorMessage();
00514                           ROS_INFO("...initializing powercubes not successful. error: %s", res.error_message.data.c_str());
00515                   }
00516           }
00517 
00518           else
00519           {
00520                   res.success.data = true;
00521                   res.error_message.data = "powercubes already initialized";
00522                   ROS_WARN("...initializing powercubes not successful. error: %s",res.error_message.data.c_str());
00523           }
00524 
00525           return true;
00526   }
00527 
00535   bool srvCallback_Stop(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00536   {
00537           ROS_INFO("Stopping powercubes...");
00538 
00540           if (pc_ctrl_->Stop())
00541           {
00542                   res.success.data = true;
00543                   ROS_INFO("...stopping powercubes successful.");
00544           }
00545 
00546           else
00547           {
00548                   res.success.data = false;
00549                   res.error_message.data = pc_ctrl_->getErrorMessage();
00550                   ROS_ERROR("...stopping powercubes not successful. error: %s", res.error_message.data.c_str());
00551           }
00552           return true;
00553   }
00554 
00562   bool srvCallback_Recover(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00563   {
00564           ROS_INFO("Recovering powercubes...");
00565           if (initialized_)
00566           {
00568                   if (pc_ctrl_->Recover())
00569                   {
00570                         error_ = false;
00571                         error_msg_ = "";
00572                         res.success.data = true;
00573                         ROS_INFO("...recovering powercubes successful.");
00574                   }
00575                   else
00576                   {
00577                         res.success.data = false;
00578                         error_ = true;
00579                         error_msg_ = pc_ctrl_->getErrorMessage();
00580                         res.error_message.data = pc_ctrl_->getErrorMessage();
00581                         ROS_ERROR("...recovering powercubes not successful. error: %s", res.error_message.data.c_str());
00582                   }
00583           }
00584           else
00585           {
00586                   res.success.data = false;
00587                   res.error_message.data = "powercubes not initialized";
00588                   ROS_ERROR("...recovering powercubes not successful. error: %s",res.error_message.data.c_str());
00589           }
00590 
00591           return true;
00592   }
00593 
00601   bool srvCallback_SetOperationMode(cob_srvs::SetOperationMode::Request &req, cob_srvs::SetOperationMode::Response &res)
00602   {
00603         if(req.operation_mode.data != "velocity")
00604         {
00605                 ROS_WARN("Powercube chain currently only supports velocity commands");
00606                 res.success.data = false;
00607         }
00608         else
00609         {
00610                 res.success.data = true;
00611         }
00612         return true;
00613   }
00614 
00621   void publishState(bool update=true)
00622   {
00623           if (initialized_)
00624           {
00625                   ROS_DEBUG("publish state");
00626 
00627                   if(update)
00628                         {pc_ctrl_->updateStates();}
00629 
00630                   sensor_msgs::JointState joint_state_msg;
00631                   joint_state_msg.header.stamp = ros::Time::now();
00632                   joint_state_msg.name = pc_params_->GetJointNames();
00633                   joint_state_msg.position = pc_ctrl_->getPositions();
00634                   joint_state_msg.velocity = pc_ctrl_->getVelocities();
00635                   joint_state_msg.effort.resize(pc_params_->GetDOF());
00636 
00637                   pr2_controllers_msgs::JointTrajectoryControllerState controller_state_msg;
00638                   controller_state_msg.header.stamp = joint_state_msg.header.stamp;
00639                   controller_state_msg.joint_names = pc_params_->GetJointNames();
00640                   controller_state_msg.actual.positions = pc_ctrl_->getPositions();
00641                   controller_state_msg.actual.velocities = pc_ctrl_->getVelocities();
00642                   controller_state_msg.actual.accelerations = pc_ctrl_->getAccelerations();
00643 
00644                   std_msgs::String opmode_msg;
00645                   opmode_msg.data = "velocity";
00646 
00648                   topicPub_JointState_.publish(joint_state_msg);
00649                   topicPub_ControllerState_.publish(controller_state_msg);
00650                   topicPub_OperationMode_.publish(opmode_msg);
00651 
00652                   last_publish_time_ = joint_state_msg.header.stamp;
00653 
00654           }
00655 
00656         // check status of PowerCube chain
00657         if (pc_ctrl_->getPC_Status() != PowerCubeCtrl::PC_CTRL_OK) { error_ = true; }
00658         
00659                 // check status of PowerCube chain 
00660                 if (pc_ctrl_->getPC_Status() != PowerCubeCtrl::PC_CTRL_OK) 
00661                 {       
00662                         error_ = true;
00663                 } 
00664                 else 
00665                 {
00666                         error_ = false;
00667                 } 
00668 
00669     // publishing diagnotic messages
00670     diagnostic_msgs::DiagnosticArray diagnostics;
00671     diagnostics.status.resize(1);
00672 
00673     // set data to diagnostics
00674     if(error_)
00675     {
00676       diagnostics.status[0].level = 2;
00677       diagnostics.status[0].name = n_.getNamespace();;
00678       diagnostics.status[0].message =  pc_ctrl_->getErrorMessage();
00679     }
00680     else
00681     {
00682       if (initialized_)
00683       {
00684         diagnostics.status[0].level = 0;
00685         diagnostics.status[0].name = n_.getNamespace(); //"schunk_powercube_chain";
00686         diagnostics.status[0].message = "powercubechain initialized and running";
00687       }
00688       else
00689       {
00690         diagnostics.status[0].level = 1;
00691         diagnostics.status[0].name = n_.getNamespace(); //"schunk_powercube_chain";
00692         diagnostics.status[0].message = "powercubechain not initialized";
00693       }
00694     }
00695     // publish diagnostic message
00696     topicPub_Diagnostic_.publish(diagnostics);
00697   }
00698 }; //PowerCubeChainNode
00699 
00705 int main(int argc, char** argv)
00706 {
00708         ros::init(argc, argv, "powercube_chain");
00709 
00710         // create PowerCubeChainNode
00711         PowerCubeChainNode pc_node;
00712         pc_node.getROSParameters();
00713         pc_node.getRobotDescriptionParameters();
00714 
00716         double frequency;
00717         if (pc_node.n_.hasParam("frequency"))
00718         {
00719                 pc_node.n_.getParam("frequency", frequency);
00720                 //frequency of driver has to be much higher then controller frequency
00721         }
00722 
00723         else
00724         {
00725                 //frequency of driver has to be much higher then controller frequency
00726                 frequency = 10; //Hz
00727                 ROS_WARN("Parameter frequency not available, setting to default value: %f Hz", frequency);
00728         }
00729 
00730         ros::Duration min_publish_duration;
00731         if (pc_node.n_.hasParam("min_publish_duration"))
00732         {
00733                 double sec;
00734                 pc_node.n_.getParam("min_publish_duration", sec);
00735                 min_publish_duration.fromSec(sec);
00736         }
00737         else
00738         {
00739                 ROS_ERROR("Parameter min_publish_time not available");
00740                 return 0;
00741         }
00742 
00743         if((1.0/min_publish_duration.toSec()) > frequency)
00744         {
00745                 ROS_ERROR("min_publish_duration has to be longer then delta_t of controller frequency!");
00746                 return 0;
00747         }
00748 
00750         ros::Rate loop_rate(frequency); // Hz
00751         while (pc_node.n_.ok())
00752         {
00753                 if ((ros::Time::now() - pc_node.last_publish_time_) >= min_publish_duration)
00754                 {
00755                         pc_node.publishState();
00756                 }
00757 
00759                 ros::spinOnce();
00760                 loop_rate.sleep();
00761         }
00762 
00763         return 0;
00764 }


schunk_powercube_chain
Author(s): Florian Weisshardt
autogenerated on Mon Oct 6 2014 07:31:09