ipa_canopen_ros.cpp
Go to the documentation of this file.
00001 
00060 #include "ros/ros.h"
00061 #include <urdf/model.h>
00062 #include "std_msgs/String.h"
00063 #include "sensor_msgs/JointState.h"
00064 #include "control_msgs/JointTrajectoryControllerState.h"
00065 #include "brics_actuator/JointVelocities.h"
00066 #include "cob_srvs/Trigger.h"
00067 #include "cob_srvs/SetOperationMode.h"
00068 #include <diagnostic_msgs/DiagnosticArray.h>
00069 #include <iostream>
00070 #include <map>
00071 #include <boost/bind.hpp>
00072 #include <boost/filesystem.hpp>
00073 #include <ipa_canopen_core/canopen.h>
00074 #include <XmlRpcValue.h>
00075 #include <ipa_canopen_ros/JointLimits.h>
00076 
00077 typedef boost::function<bool(cob_srvs::Trigger::Request&, cob_srvs::Trigger::Response&)> TriggerType;
00078 typedef boost::function<void(const brics_actuator::JointVelocities&)> JointVelocitiesType;
00079 typedef boost::function<bool(cob_srvs::SetOperationMode::Request&, cob_srvs::SetOperationMode::Response&)> SetOperationModeCallbackType;
00080 
00081 std::vector<int> motor_direction;
00082 
00083 std::map<std::string, JointLimits*> joint_limits;
00084 
00085 
00086 struct BusParams
00087 {
00088     std::string baudrate;
00089     uint32_t syncInterval;
00090 };
00091 
00092 //std::map<std::string, BusParams> buses;
00093 
00094 std::string deviceFile;
00095 
00096 std::vector<std::string> chainNames;
00097 
00098 bool CANopenInit(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res, std::string chainName)
00099 {
00100     bool all_initialized = true;
00101 
00102     ROS_INFO("Trying to initialize the chain: %s", chainName.c_str());
00103 
00104     for (auto id : canopen::deviceGroups[chainName].getCANids())
00105     {
00106         if (not canopen::devices[id].getInitialized())
00107         {
00108             all_initialized = false;
00109         }
00110     }
00111 
00112     if(all_initialized)
00113     {
00114         res.success.data = true;
00115         res.error_message.data = "This chain is already initialized";
00116         ROS_INFO("This chain is already initialized");
00117         return true;
00118     }
00119 
00120     bool init_success = canopen::init(deviceFile, chainName, canopen::syncInterval);
00121     std::this_thread::sleep_for(std::chrono::milliseconds(100));
00122 
00123 
00124 
00125     if(init_success)
00126     {
00127         res.success.data = true;
00128         res.error_message.data = "Sucessfuly initialized";
00129         ROS_INFO("This chain was sucessfuly initialized");
00130 
00131     }
00132     else
00133     {
00134         res.success.data = false;
00135         res.error_message.data = "Module could not be initialized";
00136         ROS_WARN("This chain could not be initialized. Check for possible errors and try to initialize it again.");
00137     }
00138 
00139 
00140     return true;
00141 }
00142 
00143 
00144 bool CANopenRecover(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res, std::string chainName)
00145 {
00146 
00147     ROS_INFO("Trying to recover the chain: %s", chainName.c_str());
00148 
00149     for (auto id : canopen::deviceGroups[chainName].getCANids())
00150     {
00151         if (not canopen::devices[id].getInitialized())
00152         {
00153             res.success.data = false;
00154             res.error_message.data = "not initialized yet";
00155             ROS_INFO("not initialized yet");
00156             return true;
00157         }
00158     }
00159 
00160     bool recover_success = canopen::recover(deviceFile,chainName, canopen::syncInterval);
00161     std::this_thread::sleep_for(std::chrono::milliseconds(100));
00162 
00163 
00164 
00165     if(recover_success)
00166     {
00167 
00168         res.success.data = true;
00169         res.error_message.data = "Sucessfuly recovered";
00170         ROS_INFO("The device was sucessfuly recovered");
00171         return true;
00172     }
00173     else
00174     {
00175         res.success.data = false;
00176         res.error_message.data = "Module could not be recovered";
00177         ROS_WARN("Module could not be recovered. Check for possible errors and try to recover it again.");
00178         return true;
00179     }
00180 
00181 }
00182 
00183 
00184 bool CANOpenHalt(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res, std::string chainName)
00185 {
00186 
00187 
00188 
00189     canopen::halt(deviceFile, chainName, canopen::syncInterval);
00190     std::this_thread::sleep_for(std::chrono::milliseconds(100));
00191 
00192     res.success.data = true;
00193     res.error_message.data = "";
00194     return true;
00195 }
00196 
00197 
00198 bool setOperationModeCallback(cob_srvs::SetOperationMode::Request &req, cob_srvs::SetOperationMode::Response &res, std::string chainName)
00199 {
00200     res.success.data = true;  // for now this service is just a dummy, not used elsewhere
00201     return true;
00202 }
00203 
00204 void setVel(const brics_actuator::JointVelocities &msg, std::string chainName)
00205 {
00206     if (!canopen::atFirstInit & !canopen::recover_active)
00207     {
00208         std::vector<double> velocities;
00209         std::vector<double> positions;
00210 
00211 
00212         int counter = 0;
00213 
00214         for (auto it : msg.velocities)
00215         {
00216             velocities.push_back( it.value*motor_direction[counter]);
00217             counter++;
00218         }
00219 
00220         counter = 0;
00221 
00222         for (auto id : canopen::deviceGroups[chainName].getCANids())
00223         {
00224 
00225             double pos = ((double)canopen::devices[id].getDesiredPos() + joint_limits[chainName]->getOffsets()[counter])*motor_direction[counter];
00226             positions.push_back(pos);
00227             counter++;
00228         }
00229 
00230         joint_limits[chainName]->checkVelocityLimits(velocities);
00231         joint_limits[chainName]->checkPositionLimits(positions, velocities);
00232 
00233         canopen::deviceGroups[chainName].setVel(velocities);
00234     }
00235 }
00236 
00237 void readParamsFromParameterServer(ros::NodeHandle n)
00238 {
00239     std::string param;
00240 
00241     BusParams busParam;
00242 //    param = "device";
00243 //    XmlRpc::XmlRpcValue busParams;
00244 //    if (n.hasParam(param))
00245 //    {
00246 //        n.getParam(param, busParams);
00247 //    }
00248 //    else
00249 //    {
00250 //        ROS_ERROR("Parameter %s not set, shutting down node...", param.c_str());
00251 //        n.shutdown();
00252 //    }
00253 
00254 //    // TODO: check for content of busParams
00255 //    for (int i=0; i<busParams.size(); i++)
00256 //    {
00257 //        BusParams busParam;
00258 //        auto name = static_cast<std::string>(busParams[i]["name"]);
00259 //        busParam.baudrate = static_cast<std::string>(busParams[i]["baudrate"]);
00260 //        canopen::baudRate = busParam.baudrate;
00261 //        busParam.syncInterval = static_cast<int>(busParams[i]["sync_interval"]);
00262 //        buses[name] = busParam;
00263 //    }
00264 
00265     param = "device";
00266     XmlRpc::XmlRpcValue device;
00267     if (n.hasParam(param))
00268     {
00269         n.getParam(param, device);
00270     }
00271     else
00272     {
00273         ROS_ERROR("Parameter %s not set, shutting down node...", param.c_str());
00274         n.shutdown();
00275     }
00276 
00277 
00278 
00279     deviceFile = static_cast<std::string>(device);
00280 
00281     param = "sync_interval";
00282     XmlRpc::XmlRpcValue interval;
00283     if (n.hasParam(param))
00284     {
00285         n.getParam(param, interval);
00286     }
00287     else
00288     {
00289         ROS_ERROR("Parameter %s not set, shutting down node...", param.c_str());
00290         n.shutdown();
00291     }
00292 
00293     canopen::syncInterval = std::chrono::milliseconds(static_cast<int>(interval));
00294 
00295     param = "baudrate";
00296     XmlRpc::XmlRpcValue baudRate;
00297     if (n.hasParam(param))
00298     {
00299         n.getParam(param, baudRate);
00300     }
00301     else
00302     {
00303         ROS_ERROR("Parameter %s not set, shutting down node...", param.c_str());
00304         n.shutdown();
00305     }
00306 
00307     // TODO: check for content of chainNames_XMLRPC
00308 
00309     canopen::baudRate = static_cast<std::string>(baudRate);
00310     busParam.baudrate = canopen::baudRate;
00311 
00312     param = "chains";
00313     XmlRpc::XmlRpcValue chainNames_XMLRPC;
00314     if (n.hasParam(param))
00315     {
00316         n.getParam(param, chainNames_XMLRPC);
00317     }
00318     else
00319     {
00320         ROS_ERROR("Parameter %s not set, shutting down node...", param.c_str());
00321         n.shutdown();
00322     }
00323 
00324     // TODO: check for content of chainNames_XMLRPC
00325     for (int i=0; i<chainNames_XMLRPC.size(); i++)
00326         chainNames.push_back(static_cast<std::string>(chainNames_XMLRPC[i]));
00327 
00328     for (auto chainName : chainNames)
00329     {
00330         std::vector<std::string> jointNames;
00331 
00332         param = "/" + chainName + "/joint_names";
00333         XmlRpc::XmlRpcValue jointNames_XMLRPC;
00334         if (n.hasParam(param))
00335         {
00336             n.getParam(param, jointNames_XMLRPC);
00337         }
00338         else
00339         {
00340             ROS_ERROR("Parameter %s not set, shutting down node...", param.c_str());
00341             n.shutdown();
00342         }
00343 
00344         // TODO: check for content of jointNames_XMLRPC
00345         for (int i=0; i<jointNames_XMLRPC.size(); i++)
00346             jointNames.push_back(static_cast<std::string>(jointNames_XMLRPC[i]));
00347 
00348         int DOF = jointNames.size();
00349 
00350         param = "/" + chainName + "/motor_direction";
00351         XmlRpc::XmlRpcValue motorDirections_XMLRPC;
00352         if (n.hasParam(param))
00353         {
00354             n.getParam(param, motorDirections_XMLRPC);
00355 
00356             if( motorDirections_XMLRPC.size() != DOF)
00357             {
00358                 ROS_ERROR("The size of the motor direction parameter is different from the size of the degrees of freedom. Shutting down node...");
00359                 n.shutdown();
00360                 exit(EXIT_FAILURE);
00361             }
00362 
00363             // TODO: check for content of motorDirections
00364             for (int i=0; i<motorDirections_XMLRPC.size(); i++)
00365             {
00366                 int this_direction = static_cast<int>(motorDirections_XMLRPC[i]);
00367 
00368                 if(this_direction != 1 && this_direction != -1 )
00369                 {
00370                     ROS_ERROR("The value %d is not valid for the motor direction.Please use 1 or -1. Shutting down node...", this_direction);
00371                     n.shutdown();
00372                     exit(EXIT_FAILURE);
00373                 }
00374 
00375                 motor_direction.push_back(this_direction);
00376             }
00377         }
00378         else
00379         {
00380             ROS_WARN("Parameter %s not set, using default [1]...", param.c_str());
00381             for (int i=0; i < DOF; i++)
00382                 motor_direction.push_back(1);
00383         }
00384 
00385 
00386         param = "/" + chainName + "/module_ids";
00387         XmlRpc::XmlRpcValue moduleIDs_XMLRPC;
00388         if (n.hasParam(param))
00389         {
00390             n.getParam(param, moduleIDs_XMLRPC);
00391         }
00392         else
00393         {
00394             ROS_ERROR("Parameter %s not set, shutting down node...", param.c_str());
00395             n.shutdown();
00396         }
00397 
00398         if( moduleIDs_XMLRPC.size() != DOF)
00399         {
00400             ROS_ERROR("The size of the ids parameter is different from the size of the degrees of freedom. Shutting down node...");
00401             n.shutdown();
00402             exit(EXIT_FAILURE);
00403         }
00404 
00405         // TODO: check for content of moduleIDs
00406         std::vector<uint8_t> moduleIDs;
00407         for (int i=0; i<moduleIDs_XMLRPC.size(); i++)
00408             moduleIDs.push_back(static_cast<int>(moduleIDs_XMLRPC[i]));
00409 
00410         for (unsigned int i=0; i<jointNames.size(); i++)
00411             canopen::devices[ moduleIDs[i] ] = canopen::Device(moduleIDs[i], jointNames[i], chainName);
00412 
00413         canopen::deviceGroups[ chainName ] = canopen::DeviceGroup(moduleIDs, jointNames);
00414 
00415     }
00416 
00417 }
00418 
00419 void setJointConstraints(ros::NodeHandle n)
00420 {
00421     /******************************************
00422      *
00423      *
00424      *
00425      */
00426 
00427     for (auto chainName : chainNames)
00428     {
00429         joint_limits[chainName] = new JointLimits();
00431 
00432         int DOF = canopen::deviceGroups[chainName].getNames().size();
00433 
00434         std::string param_name = "/robot_description";
00435         std::string full_param_name;
00436         std::string xml_string;
00437 
00438         n.searchParam(param_name, full_param_name);
00439         if (n.hasParam(full_param_name))
00440         {
00441             n.getParam(full_param_name.c_str(), xml_string);
00442         }
00443 
00444         else
00445         {
00446             ROS_ERROR("Parameter %s not set, shutting down node...", full_param_name.c_str());
00447             n.shutdown();
00448         }
00449 
00450         if (xml_string.size() == 0)
00451         {
00452             ROS_ERROR("Unable to load robot model from parameter %s",full_param_name.c_str());
00453             n.shutdown();
00454         }
00455         ROS_INFO("Robot model loaded succesfully");
00456         //ROS_INFO("%s content\n%s", full_param_name.c_str(), xml_string.c_str());
00457 
00459         urdf::Model model;
00460 
00461         if (!model.initString(xml_string))
00462         {
00463             ROS_ERROR("Failed to parse urdf file");
00464             n.shutdown();
00465         }
00466         ROS_INFO("Successfully parsed urdf file");
00467 
00469         std::vector<double> MaxVelocities(DOF);
00470         std::vector<double> LowerLimits(DOF);
00471         std::vector<double> UpperLimits(DOF);
00472         std::vector<double> Offsets(DOF);
00473 
00474         std::vector<std::string> jointNames = canopen::deviceGroups[chainName].getNames();
00475         for (int i = 0; i < DOF; i++)
00476         {
00477             if(!model.getJoint(jointNames[i].c_str()))
00478             {
00479                 ROS_ERROR("Joint %s is not available",jointNames[i].c_str());
00480                 n.shutdown();
00481                 exit(1);
00482             }
00483             if(!model.getJoint(jointNames[i].c_str())->limits)
00484             {
00485                 ROS_ERROR("Parameter limits could not be found in the URDF contents.");
00486                 n.shutdown();
00487                 exit(1);
00488             }
00489             else if(!model.getJoint(jointNames[i].c_str())->limits->velocity)
00490             {
00491                 ROS_ERROR("Limits has no velocity attribute");
00492                 n.shutdown();
00493                 exit(1);
00494             }
00495             if(!model.getJoint(jointNames[i].c_str())->limits->lower)
00496             {
00497                 ROS_ERROR("Limits has no lower attribute");
00498                 n.shutdown();
00499                 exit(1);
00500             }
00501             else if(!model.getJoint(jointNames[i].c_str())->limits->upper)
00502             {
00503                 ROS_ERROR("Limits has no upper attribute");
00504                 n.shutdown();
00505                 exit(1);
00506             }
00507             //Get maximum velocities out of urdf model
00508             MaxVelocities[i] = model.getJoint(jointNames[i].c_str())->limits->velocity;
00509 
00511             LowerLimits[i] = model.getJoint(jointNames[i].c_str())->limits->lower;
00512 
00513             // Get upper limits out of urdf model
00514             UpperLimits[i] = model.getJoint(jointNames[i].c_str())->limits->upper;
00515 
00517             if(!model.getJoint(jointNames[i].c_str())->calibration)
00518             {
00519                 ROS_ERROR("Parameter calibration could not be found in the URDF contents.");
00520                 n.shutdown();
00521                 exit(1);
00522             }
00523             else if(!model.getJoint(jointNames[i].c_str())->calibration->rising)
00524             {
00525                 ROS_ERROR("Calibration has no rising attribute");
00526                 n.shutdown();
00527                 exit(1);
00528             }
00529             Offsets[i] = model.getJoint(jointNames[i].c_str())->calibration->rising.get()[0];
00530         }
00531         ROS_INFO("Successfully got offsets and limits");
00532 
00534 
00535         joint_limits[chainName]->setDOF(DOF);
00536         joint_limits[chainName]->setUpperLimits(UpperLimits);
00537         joint_limits[chainName]->setLowerLimits(LowerLimits);
00538         joint_limits[chainName]->setMaxVelocities(MaxVelocities);
00539         joint_limits[chainName]->setOffsets(Offsets);
00540 
00541         /********************************************
00542          *
00543          *
00544          ********************************************/
00545     }
00546 }
00547 
00548 
00549 int main(int argc, char **argv)
00550 {
00551     // todo: allow identical module IDs of modules when they are on different CAN buses
00552 
00553 
00554     ros::init(argc, argv, "ipa_canopen_ros");
00555     ros::NodeHandle n(""); // ("~");
00556 
00557     readParamsFromParameterServer(n);
00558 
00559 //    std::cout << "Sync Interval" << buses.begin()->second.syncInterval << std::endl;
00560 //    canopen::syncInterval = std::chrono::milliseconds( buses.begin()->second.syncInterval );
00561 //    // ^ todo: this only works with a single CAN bus; add support for more buses!
00562 //    deviceFile = buses.begin()->first;
00563 
00564     //canopen::pre_init();
00565 
00566     /********************************************/
00567 
00568     // add custom PDOs:
00569     canopen::sendPos = canopen::defaultPDOOutgoing_interpolated;
00570     for (auto it : canopen::devices) {
00571         canopen::incomingPDOHandlers[ 0x180 + it.first ] = [it](const TPCANRdMsg mS) { canopen::defaultPDO_incoming_status( it.first, mS ); };
00572         canopen::incomingPDOHandlers[ 0x480 + it.first ] = [it](const TPCANRdMsg mP) { canopen::defaultPDO_incoming_pos( it.first, mP ); };
00573         canopen::incomingEMCYHandlers[ 0x081 + it.first ] = [it](const TPCANRdMsg mE) { canopen::defaultEMCY_incoming( it.first, mE ); };
00574     }
00575 
00576     // set up services, subscribers, and publishers for each of the chains:
00577     std::vector<TriggerType> initCallbacks;
00578     std::vector<ros::ServiceServer> initServices;
00579     std::vector<TriggerType> recoverCallbacks;
00580     std::vector<ros::ServiceServer> recoverServices;
00581     std::vector<TriggerType> stopCallbacks;
00582     std::vector<ros::ServiceServer> stopServices;
00583     std::vector<SetOperationModeCallbackType> setOperationModeCallbacks;
00584     std::vector<ros::ServiceServer> setOperationModeServices;
00585 
00586     std::vector<JointVelocitiesType> jointVelocitiesCallbacks;
00587     std::vector<ros::Subscriber> jointVelocitiesSubscribers;
00588     std::map<std::string, ros::Publisher> currentOperationModePublishers;
00589     std::map<std::string, ros::Publisher> statePublishers;
00590     ros::Publisher jointStatesPublisher = n.advertise<sensor_msgs::JointState>("/joint_states", 1);
00591     ros::Publisher diagnosticsPublisher = n.advertise<diagnostic_msgs::DiagnosticArray>("/diagnostics", 1);
00592 
00593     for (auto it : canopen::deviceGroups)
00594     {
00595         ROS_INFO("Configuring %s", it.first.c_str());
00596 
00597         initCallbacks.push_back( boost::bind(CANopenInit, _1, _2, it.first) );
00598         initServices.push_back( n.advertiseService("/" + it.first + "/init", initCallbacks.back()) );
00599         recoverCallbacks.push_back( boost::bind(CANopenRecover, _1, _2, it.first) );
00600         recoverServices.push_back( n.advertiseService("/" + it.first + "/recover", recoverCallbacks.back()) );
00601         stopCallbacks.push_back( boost::bind(CANOpenHalt, _1, _2, it.first) );
00602         stopServices.push_back( n.advertiseService("/" + it.first + "/halt", stopCallbacks.back()) );
00603         setOperationModeCallbacks.push_back( boost::bind(setOperationModeCallback, _1, _2, it.first) );
00604         setOperationModeServices.push_back( n.advertiseService("/" + it.first + "/set_operation_mode", setOperationModeCallbacks.back()) );
00605 
00606         jointVelocitiesCallbacks.push_back( boost::bind(setVel, _1, it.first) );
00607         jointVelocitiesSubscribers.push_back( n.subscribe<brics_actuator::JointVelocities>("/" + it.first + "/command_vel", 1, jointVelocitiesCallbacks.back()) );
00608 
00609         currentOperationModePublishers[it.first] = n.advertise<std_msgs::String>("/" + it.first + "/current_operationmode", 1);
00610 
00611         statePublishers[it.first] = n.advertise<control_msgs::JointTrajectoryControllerState>("/" + it.first + "/state", 1);
00612     }
00613 
00614     double lr = 1000.0 / std::chrono::duration_cast<std::chrono::milliseconds>(canopen::syncInterval).count();
00615 
00616     ros::Rate loop_rate(lr);
00617 
00618     setJointConstraints(n);
00619 
00620     while (ros::ok())
00621     {
00622 
00623         // iterate over all chains, get current pos and vel and publish as topics:
00624 
00625 
00626         for (auto dg : (canopen::deviceGroups))
00627         {
00628 
00629             int counter = 0;
00630             std::vector <double> positions;
00631             std::vector <double> desired_positions;
00632 
00633             for (auto id : dg.second.getCANids())
00634             {
00635 
00636                 double pos = ((double)canopen::devices[id].getActualPos() + joint_limits[dg.first]->getOffsets()[counter])*motor_direction[counter];
00637                 double des_pos = ((double)canopen::devices[id].getDesiredPos() + joint_limits[dg.first]->getOffsets()[counter])*motor_direction[counter];
00638                 positions.push_back(pos);
00639                 desired_positions.push_back(des_pos);
00640                 counter++;
00641             }
00642 
00643 
00644             sensor_msgs::JointState js;
00645             js.name = dg.second.getNames();
00646             js.header.stamp = ros::Time::now(); // todo: possibly better use timestamp of hardware msg?
00647 
00648             js.position = positions;//dg.second.getActualPos();
00649             //std::cout << "Position" << js.position[0] << std::endl;
00650             js.velocity = dg.second.getActualVel();
00651             js.effort = std::vector<double>(dg.second.getNames().size(), 0.0);
00652             jointStatesPublisher.publish(js);
00653 
00654             control_msgs::JointTrajectoryControllerState jtcs;
00655             jtcs.header.stamp = js.header.stamp;
00656             jtcs.actual.positions = js.position;
00657             jtcs.actual.velocities = js.velocity;
00658             jtcs.desired.positions = desired_positions;//dg.second.getDesiredPos();
00659             jtcs.desired.velocities = dg.second.getDesiredVel();
00660             statePublishers[dg.first].publish(jtcs);
00661 
00662             std_msgs::String opmode;
00663             opmode.data = "velocity";
00664             currentOperationModePublishers[dg.first].publish(opmode);
00665             counter++;
00666         }
00667 
00668         // publishing diagnostic messages
00669         diagnostic_msgs::DiagnosticArray diagnostics;
00670         diagnostic_msgs::DiagnosticStatus diagstatus;
00671         std::vector<diagnostic_msgs::DiagnosticStatus> diagstatus_msg;
00672 
00673         diagnostic_msgs::KeyValue keyval;
00674         std::vector<diagnostic_msgs::KeyValue> keyvalues;
00675 
00676 
00677 
00678         diagnostics.status.resize(1);
00679 
00680         for (auto dg : (canopen::deviceGroups))
00681         {
00682             for (auto id : dg.second.getCANids())
00683             {
00684 
00685             std::string name = canopen::devices[id].getName();
00686             //ROS_INFO("Name %s", name.c_str() );
00687 
00688             keyval.key = "Node ID";
00689             uint16_t node_id = canopen::devices[id].getCANid();
00690             std::stringstream result;
00691             result << node_id;
00692             keyval.value = result.str().c_str();
00693             keyvalues.push_back(keyval);
00694 
00695             keyval.key = "Device Name";
00696             keyval.value = name.c_str();
00697             //std::vector<char> dev_name = canopen::devices[id].getManufacturerDevName();
00698             //keyval.value = std::string(dev_name.begin(), dev_name.end());
00699             keyvalues.push_back(keyval);
00700 
00701             /*
00702             keyval.key = "Hardware Version";
00703             std::vector<char> manhw = canopen::devices[id].getManufacturerHWVersion();
00704             keyval.value = std::string(manhw.begin(), manhw.end());
00705             keyvalues.push_back(keyval);
00706 
00707             keyval.key = "Software Version";
00708             std::vector<char> mansw = canopen::devices[id].getManufacturerSWVersion();
00709             keyval.value = std::string(mansw.begin(), mansw.end());
00710             keyvalues.push_back(keyval);
00711 
00712 
00713 
00714             keyval.key = "Vendor ID";
00715             std::vector<uint16_t> vendor_id = canopen::devices[id].getVendorID();
00716             std::stringstream result1;
00717             for (auto it : vendor_id)
00718             {
00719                 result1 <<  std::hex << it;
00720             }
00721             keyval.value = result1.str().c_str();
00722             keyvalues.push_back(keyval);
00723 
00724             keyval.key = "Revision Number";
00725             uint16_t rev_number = canopen::devices[id].getRevNumber();
00726             std::stringstream result2;
00727             result2 << rev_number;
00728             keyval.value = result2.str().c_str();
00729             keyvalues.push_back(keyval);
00730 
00731             keyval.key = "Product Code";
00732             std::vector<uint16_t> prod_code = canopen::devices[id].getProdCode();
00733             std::stringstream result3;
00734             std::copy(prod_code.begin(), prod_code.end(), std::ostream_iterator<uint16_t>(result3, " "));
00735             keyval.value = result3.str().c_str();
00736             keyvalues.push_back(keyval);
00737             */
00738 
00739             bool error_ = canopen::devices[id].getFault();
00740             bool initialized_ = canopen::devices[id].getInitialized();
00741 
00742             if(initialized_)
00743             {
00744                 std::stringstream operation_string;
00745                 operation_string << "Mode of operation for Node" << node_id;
00746                 keyval.key = operation_string.str().c_str();
00747                 int8_t mode_display = canopen::devices[id].getCurrentModeofOperation();
00748                 keyval.value = canopen::modesDisplay[mode_display];
00749                 keyvalues.push_back(keyval);
00750 
00751                 std::stringstream error_register_string;
00752                 error_register_string << "Error Register from Node" << node_id;
00753                 keyval.key = error_register_string.str().c_str();
00754                 keyval.value = canopen::devices[id].getErrorRegister();
00755                 keyvalues.push_back(keyval);
00756 
00757                 std::stringstream driver_temperature_string;
00758                 driver_temperature_string << "Current Driver Temperature for Node" << node_id;
00759                 keyval.key = driver_temperature_string.str().c_str();
00760                 double driver_temperature = canopen::devices[id].getDriverTemperature();
00761                 keyval.value = std::to_string(driver_temperature);
00762                 keyvalues.push_back(keyval);
00763             }
00764 
00765             //ROS_INFO("Fault: %d", error_);
00766             //ROS_INFO("Referenced: %d", initialized_);
00767 
00768             std::stringstream diag_string;
00769             diag_string << dg.first;
00770             diagstatus.name = diag_string.str().c_str();
00771                 
00772             // set data to diagnostics
00773             if(error_)
00774             {
00775                 diagstatus.level = 2;
00776                 diagstatus.message = "Fault occured.";
00777                 diagstatus.values = keyvalues;
00778                 break;
00779             }
00780             else
00781             {
00782                 if (initialized_)
00783                 {
00784                     diagstatus.level = 0;
00785                     diagstatus.message = "Device initialized and running";
00786                     diagstatus.values = keyvalues;
00787                 }
00788                 else
00789                 {
00790                     diagstatus.level = 1;
00791                     diagstatus.message = "Device not initialized";
00792                     diagstatus.values = keyvalues;
00793                     break;
00794                 }
00795             }
00796         }
00797     }
00798         diagstatus_msg.push_back(diagstatus);
00799         // publish diagnostic message
00800         diagnostics.status = diagstatus_msg;
00801         diagnostics.header.stamp = ros::Time::now();
00802         diagnosticsPublisher.publish(diagnostics);
00803 
00804         ros::spinOnce();
00805         loop_rate.sleep();
00806     }
00807 
00808     return 0;
00809 }
00810 


ipa_canopen_ros
Author(s): Tobias Sing, Thiago de Freitas
autogenerated on Thu Aug 27 2015 13:32:22