Go to the documentation of this file.00001
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
00012 #include <ipa_canopen_core/canopen.h>
00013 #include <ipa_canopen_ros/JointLimits.h>
00014 #include <urdf/model.h>
00015
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
00031 public:
00032
00033 brics_actuator::JointVelocities in_command_vel;
00034
00035
00036
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
00048 bool is_initialized_;
00049 std::string chain_name_;
00050 int dof_;
00051 std::vector<std::string> joint_names_;
00052 std::vector<uint8_t> modul_ids_;
00053 JointLimits* joint_limits_;
00054
00055
00056 public:
00057 canopen_ros_impl()
00058 {
00059
00060 is_initialized_ = false;
00061
00062 chain_name_ = "arm_controller";
00063 joint_names_.push_back("arm_1_joint");
00064
00065
00066 modul_ids_.push_back(uint16_t(1));
00067
00068 joint_limits_ = new JointLimits();
00069
00070 }
00071 void configure(canopen_ros_config config)
00072 {
00073
00074
00075 std::cout << "joint_names: " << config.joint_names << std::endl;
00076
00077 dof_ = joint_names_.size();
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
00101 MaxVelocities[i] = model.getJoint(joint_names_[i].c_str())->limits->velocity;
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
00111 LowerLimits[i] = model.getJoint(joint_names_[i].c_str())->limits->lower;
00112 std::cout << "LowerLimits[" << joint_names_[i].c_str() <<"]: " << LowerLimits[i] << std::endl;
00113 }
00114 joint_limits_->setLowerLimits(LowerLimits);
00115
00116
00117 std::vector<double> UpperLimits(dof_);
00118 for (int i = 0; i < dof_; i++)
00119 {
00120
00121 UpperLimits[i] = model.getJoint(joint_names_[i].c_str())->limits->upper;
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
00131 Offsets[i] = model.getJoint(joint_names_[i].c_str())->calibration->rising.get()[0];
00132 std::cout << "Offsets[" << joint_names_[i].c_str() <<"]: " << Offsets[i] << std::endl;
00133 }
00134 joint_limits_->setOffsets(Offsets);
00135
00136
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
00148 }
00149 void update(canopen_ros_data &data, canopen_ros_config config)
00150 {
00151
00152
00153 if (is_initialized_)
00154 {
00155
00156
00157
00158
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
00186 data.out_joint_states.name = dg.second.getNames();
00187 data.out_joint_states.header.stamp = ros::Time::now();
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
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;
00198 data.out_state.desired.velocities = dg.second.getDesiredVel();
00199
00200
00201 data.out_current_operationmode.data = "velocity";
00202 }
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213 diagnostic_msgs::DiagnosticStatus diagnostic_status;
00214
00215
00216
00217 data.out_diagnostics.status.push_back(diagnostic_status);
00218 }
00219
00220 }
00221
00222 bool callback_init(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res , canopen_ros_config config)
00223 {
00224
00225 ROS_INFO("Initializing canopen...");
00226 if (!is_initialized_)
00227 {
00228
00229 ROS_WARN("open device");
00230 is_initialized_ = canopen::openConnection(config.can_device, config.can_baudrate);
00231
00232
00233
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
00243 ROS_WARN("init device");
00244 canopen::init(config.can_device, canopen::syncInterval);
00245 std::this_thread::sleep_for(std::chrono::milliseconds(100));
00246
00247
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);
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
00259 ROS_WARN("init device thread");
00260 canopen::initDeviceManagerThread(canopen::deviceManager);
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";
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
00283 return true;
00284 }
00285 bool callback_recover(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res , canopen_ros_config config)
00286 {
00287
00288 ROS_INFO("Recovering canopen...");
00289 if (is_initialized_)
00290 {
00291 bool is_recovered = true;
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";
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
00330 return true;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339 };