canopen_ros_common.cpp
Go to the documentation of this file.
00001 //ROS typedefs
00002 #include "ros/ros.h"
00003 #include <control_msgs/JointTrajectoryControllerState.h>
00004 #include <sensor_msgs/JointState.h>
00005 #include <diagnostic_msgs/DiagnosticArray.h>
00006 #include <std_msgs/String.h>
00007 #include <brics_actuator/JointVelocities.h>
00008 #include <cob_srvs/Trigger.h>
00009 #include <cob_srvs/Trigger.h>
00010 
00011 /* protected region user include files on begin */
00012 #include <ipa_canopen_core/canopen.h>
00013 #include <ipa_canopen_ros/JointLimits.h>
00014 #include <urdf/model.h>
00015 /* protected region user include files end */
00016 
00017 class canopen_ros_config
00018 {
00019 public:
00020                 std::string can_device;
00021                 std::string can_baudrate;
00022                 std::string modul_ids;
00023                 std::string joint_names;
00024                 std::string robot_description;
00025 
00026 };
00027 
00028 class canopen_ros_data
00029 {
00030 // autogenerated: don't touch this class
00031 public:
00032 //input data
00033         brics_actuator::JointVelocities in_command_vel;
00034   
00035         
00036 //output data
00037         control_msgs::JointTrajectoryControllerState out_state;
00038         sensor_msgs::JointState out_joint_states;
00039         diagnostic_msgs::DiagnosticArray out_diagnostics;
00040         std_msgs::String out_current_operationmode;
00041  
00042 
00043 };
00044 
00045 class canopen_ros_impl
00046 {
00047         /* protected region user member variables on begin */
00048         bool is_initialized_;
00049         std::string chain_name_; // FIXME: get from parameter server
00050         int dof_;
00051         std::vector<std::string> joint_names_; // HACK: does not work yet because BRIDE doesn't support list parameters
00052         std::vector<uint8_t> modul_ids_; // HACK: does not work yet because BRIDE doesn't support list parameters
00053         JointLimits* joint_limits_;
00054         /* protected region user member variables end */
00055 
00056 public:
00057     canopen_ros_impl() 
00058     {
00059         /* protected region user constructor on begin */
00060         is_initialized_ = false;
00061 
00062         chain_name_ = "arm_controller"; // FIXME: get from parameter server
00063         joint_names_.push_back("arm_1_joint"); // HACK: does not work yet because BRIDE doesn't support list parameters
00064         //joint_names_.push_back("arm_2_joint"); // HACK: does not work yet because BRIDE doesn't support list parameters
00065         //joint_names_.push_back("arm_3_joint"); // HACK: does not work yet because BRIDE doesn't support list parameters
00066         modul_ids_.push_back(uint16_t(1)); // HACK: does not work yet because BRIDE doesn't support list parameters
00067 
00068         joint_limits_ = new JointLimits();
00069                 /* protected region user constructor end */
00070     }
00071     void configure(canopen_ros_config config) 
00072     {
00073         /* protected region user configure on begin */
00074         // get dof from joint_names vector
00075         std::cout << "joint_names: " << config.joint_names << std::endl;
00076         // dof_ = config.joint_names.size();
00077         dof_ = joint_names_.size(); // HACK: does not work yet because BRIDE doesn't support list parameters
00078         ROS_INFO("DOF: %d", dof_);
00079         joint_limits_->setDOF(dof_);
00080 
00081         if (config.robot_description.size() == 0)
00082         {
00083                 ROS_ERROR("Unable to load robot model from parameter robot_description, shutting down node...");
00084                 exit(EXIT_FAILURE);
00085         }
00086 
00088                 urdf::Model model;
00089                 if (!model.initString(config.robot_description))
00090                 {
00091                         ROS_ERROR("Failed to parse urdf file, shutting down node...");
00092                         exit(EXIT_FAILURE);
00093                 }
00094                 ROS_INFO("Successfully parsed urdf file");
00095 
00097                 std::vector<double> MaxVelocities(dof_);
00098                 for (int i = 0; i < dof_; i++)
00099                 {
00100                         //MaxVelocities[i] = model.getJoint(config.joint_names[i].c_str())->limits->velocity;
00101                         MaxVelocities[i] = model.getJoint(joint_names_[i].c_str())->limits->velocity; // HACK: does not work yet because BRIDE doesn't support list parameters
00102                         std::cout << "MaxVelocities[" << joint_names_[i].c_str() <<"]: " << MaxVelocities[i] << std::endl;
00103                 }
00104                 joint_limits_->setMaxVelocities(MaxVelocities);
00105 
00107                 std::vector<double> LowerLimits(dof_);
00108                 for (int i = 0; i < dof_; i++)
00109                 {
00110                         //LowerLimits[i] = model.getJoint(config.joint_names[i].c_str())->limits->lower;
00111                         LowerLimits[i] = model.getJoint(joint_names_[i].c_str())->limits->lower; // HACK: does not work yet because BRIDE doesn't support list parameters
00112                         std::cout << "LowerLimits[" << joint_names_[i].c_str() <<"]: " << LowerLimits[i] << std::endl;
00113                 }
00114                 joint_limits_->setLowerLimits(LowerLimits);
00115 
00116                 // Get upper limits out of urdf model
00117                 std::vector<double> UpperLimits(dof_);
00118                 for (int i = 0; i < dof_; i++)
00119                 {
00120                         //UpperLimits[i] = model.getJoint(config.joint_names[i][i].c_str())->limits->upper;
00121                         UpperLimits[i] = model.getJoint(joint_names_[i].c_str())->limits->upper; // HACK: does not work yet because BRIDE doesn't support list parameters
00122                         std::cout << "UpperLimits[" << joint_names_[i].c_str() <<"]: " << UpperLimits[i] << std::endl;
00123                 }
00124                 joint_limits_->setUpperLimits(UpperLimits);
00125 
00127                 std::vector<double> Offsets(dof_);
00128                 for (int i = 0; i < dof_; i++)
00129                 {
00130                         //Offsets[i] = model.getJoint(config.joint_names[i][i].c_str())->calibration->rising.get()[0];
00131                         Offsets[i] = model.getJoint(joint_names_[i].c_str())->calibration->rising.get()[0]; // HACK: does not work yet because BRIDE doesn't support list parameters
00132                         std::cout << "Offsets[" << joint_names_[i].c_str() <<"]: " << Offsets[i] << std::endl;
00133                 }
00134                 joint_limits_->setOffsets(Offsets);
00135 
00136                 // create device groups
00137         std::vector<std::string> devices;
00138         devices.push_back(static_cast<std::string>(config.can_device));
00139 
00140         for (unsigned int i=0; i<dof_; i++)
00141         {
00142                 canopen::devices[ modul_ids_[i] ] = canopen::Device(modul_ids_[i], joint_names_[i], chain_name_, devices[i]);
00143         }
00144 
00145         canopen::deviceGroups[ chain_name_ ] = canopen::DeviceGroup(modul_ids_, joint_names_);
00146 
00147         /* protected region user configure end */
00148     }
00149     void update(canopen_ros_data &data, canopen_ros_config config)
00150     {
00151         /* protected region user update on begin */
00152         //ROS_WARN("update start");
00153         if (is_initialized_)
00154         {
00155                 //TODO:
00156                 //send new vel to canopen
00157                 //std::cout << data.in_command_vel << std::endl;
00158                 //move(data.in_command_vel)
00159 
00160                 std::vector<double> velocities;
00161                 for (int i=0; i<data.in_command_vel.velocities.size(); i++ )
00162                 {
00163                         velocities.push_back(data.in_command_vel.velocities[i].value);
00164                 }
00165 
00166                 canopen::deviceGroups[chain_name_].setVel(velocities);
00167 
00168 
00169 
00170                 int counter = 0;
00171                         std::vector <double> positions;
00172                         std::vector <double> desired_positions;
00173 
00174                         for (auto device : canopen::devices)
00175                         {
00176                                 double pos = (double)device.second.getActualPos() + joint_limits_->getOffsets()[counter];
00177                                 double des_pos = (double)device.second.getDesiredPos() + joint_limits_->getOffsets()[counter];
00178                                 positions.push_back(pos);
00179                                 desired_positions.push_back(des_pos);
00180                                 counter++;
00181                         }
00182 
00183                         for (auto dg : (canopen::deviceGroups))
00184                         {
00185                                 // joint state
00186                                 data.out_joint_states.name = dg.second.getNames();
00187                                 data.out_joint_states.header.stamp = ros::Time::now(); // todo: possibly better use timestamp of hardware msg?
00188 
00189                                 data.out_joint_states.position = positions;
00190                                 data.out_joint_states.velocity = dg.second.getActualVel();
00191                                 data.out_joint_states.effort = std::vector<double>(dg.second.getNames().size(), 0.0);
00192 
00193                                 // controller state
00194                                 data.out_state.header.stamp = data.out_joint_states.header.stamp;
00195                                 data.out_state.actual.positions = data.out_joint_states.position;
00196                                 data.out_state.actual.velocities = data.out_joint_states.velocity;
00197                                 data.out_state.desired.positions = desired_positions;//dg.second.getDesiredPos();
00198                                 data.out_state.desired.velocities = dg.second.getDesiredVel();
00199 
00200                                 // operation mode
00201                                 data.out_current_operationmode.data = "velocity";
00202                         }
00203 
00204                 //get current joint states
00205                 //joint_pos = ...
00206                 //joint_vel = ...
00207 
00208                 //set current joint_states to out_joint_state and out_state
00209                 //data.out_joint_state =
00210                 //data.out_state =
00211 
00212                 //get diagnostics info from canopen
00213                 diagnostic_msgs::DiagnosticStatus diagnostic_status;
00214                 //diagnostic_status = ...
00215 
00216                 //set diagostics to out_diagnostics
00217                 data.out_diagnostics.status.push_back(diagnostic_status);
00218         }
00219                 /* protected region user update end */
00220     }
00221 
00222         bool callback_init(cob_srvs::Trigger::Request  &req, cob_srvs::Trigger::Response &res , canopen_ros_config config)
00223         {
00224                 /* protected region user implementation of service callback for init on begin */
00225                 ROS_INFO("Initializing canopen...");
00226                 if (!is_initialized_)
00227                 {
00228                         // open device
00229                         ROS_WARN("open device");
00230                         is_initialized_ = canopen::openConnection(config.can_device, config.can_baudrate); // TODO: add feature for different baudrates, // TODO: check for return value
00231 
00232 
00233                         // default PDO mapping
00234                         ROS_WARN("default PDO mapping");
00235                         canopen::sendPos = canopen::defaultPDOOutgoing_interpolated;
00236                     for (auto it : canopen::devices) {
00237                         canopen::incomingPDOHandlers[ 0x180 + it.first ] = [it](const TPCANRdMsg mS) { canopen::defaultPDO_incoming_status( it.first, mS ); };
00238                                 canopen::incomingPDOHandlers[ 0x480 + it.first ] = [it](const TPCANRdMsg mP) { canopen::defaultPDO_incoming_pos( it.first, mP ); };
00239                         canopen::incomingEMCYHandlers[ 0x081 + it.first ] = [it](const TPCANRdMsg mE) { canopen::defaultEMCY_incoming( it.first, mE ); };
00240                     }
00241 
00242                     // init device
00243                     ROS_WARN("init device");
00244                     canopen::init(config.can_device, canopen::syncInterval); // TODO: check for return value
00245                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
00246 
00247                     // init modules
00248                     ROS_WARN("init modules");
00249                     for (auto device : canopen::devices)
00250                     {
00251                         canopen::sendSDO(device.second.getCANid(), canopen::MODES_OF_OPERATION, canopen::MODES_OF_OPERATION_INTERPOLATED_POSITION_MODE); // TODO: check for return value
00252                         std::cout << "Setting IP mode for: " << (uint16_t)device.second.getCANid() << std::endl;
00253                         std::this_thread::sleep_for(std::chrono::milliseconds(100));
00254                     }
00255 
00256                     std::this_thread::sleep_for(std::chrono::milliseconds(100));
00257 
00258                     // init device thread
00259                     ROS_WARN("init device thread");
00260                     canopen::initDeviceManagerThread(canopen::deviceManager); // TODO: check for return value
00261 
00262                         if (is_initialized_)
00263                         {
00264                            res.success.data = true;
00265                            res.error_message.data = "initializing canopen successful";
00266                           ROS_INFO("... initializing canopen successful");
00267                         }
00268                         else
00269                         {
00270                           res.success.data = false;
00271                           res.error_message.data = "dummy error message"; // TODO get error message from canopen
00272                           ROS_ERROR("...initializing canopen not successful. error: %s", res.error_message.data.c_str());
00273                         }
00274                 }
00275                 else
00276                 {
00277                         res.success.data = true;
00278                         res.error_message.data = "canopen already initialized, please user recover";
00279                         ROS_WARN("...initializing canopen not successful. error: %s",res.error_message.data.c_str());
00280                 }
00281 
00282                 /* protected region user implementation of service callback for init end */
00283                 return true;
00284         }
00285         bool callback_recover(cob_srvs::Trigger::Request  &req, cob_srvs::Trigger::Response &res , canopen_ros_config config)
00286         {
00287                 /* protected region user implementation of service callback for recover on begin */
00288                 ROS_INFO("Recovering canopen...");
00289                 if (is_initialized_)
00290                 {
00291                         bool is_recovered = true; // TODO: fill in canopen command
00292                         canopen::recover(config.can_device, canopen::syncInterval);
00293                         std::this_thread::sleep_for(std::chrono::milliseconds(100));
00294 
00295                         for (auto device : canopen::devices)
00296                         {
00297                                 canopen::sendSDO(device.second.getCANid(), canopen::MODES_OF_OPERATION, canopen::MODES_OF_OPERATION_INTERPOLATED_POSITION_MODE);
00298                                 std::cout << "Setting IP mode for: " << (uint16_t)device.second.getCANid() << std::endl;
00299                                 std::this_thread::sleep_for(std::chrono::milliseconds(100));
00300 
00301                                 canopen::devices[device.second.getCANid()].setDesiredPos((double)device.second.getActualPos());
00302                                 canopen::devices[device.second.getCANid()].setDesiredVel(0);
00303 
00304                                 canopen::sendPos((uint16_t)device.second.getCANid(), (double)device.second.getDesiredPos());
00305                                 canopen::sendPos((uint16_t)device.second.getCANid(), (double)device.second.getDesiredPos());
00306 
00307                         }
00308 
00309 
00310                         if (is_recovered)
00311                         {
00312                                 res.success.data = true;
00313                                 res.error_message.data = "recovering canopen successful";
00314                                 ROS_INFO("...recovering canopen successful.");
00315                         }
00316                         else
00317                         {
00318                                 res.success.data = false;
00319                                 res.error_message.data = "dummy error message"; // TODO get error message from canopen;
00320                                 ROS_ERROR("...recovering canopen not successful. error: %s", res.error_message.data.c_str());
00321                         }
00322                 }
00323                 else
00324                 {
00325                   res.success.data = false;
00326                   res.error_message.data = "canopen not initialized, please use init first";
00327                   ROS_WARN("...recovering canopen not successful. error: %s",res.error_message.data.c_str());
00328                 }
00329                 /* protected region user implementation of service callback for recover end */
00330                 return true;
00331         }
00332     
00333 
00334 
00335     
00336     /* protected region user additional functions on begin */
00337         /* protected region user additional functions end */
00338     
00339 };


ipa_canopen_ros_simple
Author(s): Thiago de Freitas
autogenerated on Mon Oct 6 2014 00:59:37