demonstrator_node.cpp
Go to the documentation of this file.
00001 #include <ros/ros.h>
00002 #include <urdf/model.h>
00003 //#include <pthread.h>
00004 #include <actionlib/server/simple_action_server.h>
00005 
00006 //ROS Message Includes
00007 #include <sensor_msgs/JointState.h>
00008 #include <brics_actuator/JointPositions.h>
00009 #include <brics_actuator/JointVelocities.h>
00010 #include <diagnostic_msgs/DiagnosticArray.h>
00011 #include <control_msgs/FollowJointTrajectoryAction.h>
00012 
00013 //ROS Service Includes
00014 #include <cob_srvs/Trigger.h>
00015 #include <cob_srvs/SetOperationMode.h>
00016 
00017 //Own includes
00018 #include <cob_3d_mapping_demonstrator/demonstrator_params.h>
00019 #include <cob_3d_mapping_demonstrator/demonstrator_control.h>
00020 #include <cob_3d_mapping_demonstrator/demonstrator_control_maestro.h>
00021 //#include <cob_3d_mapping_demonstrator/SerialDevice.h>
00022 
00023 //using namespace serial_com;
00024 
00025 class DemonstratorNode
00026 {
00027 public:
00029   ros::NodeHandle n_;
00030 
00032   ros::Publisher topic_pub_joint_state_;
00033   //ros::Publisher topic_pub_operation_mode_;
00034   ros::Publisher topic_pub_diagnostic_;
00035 
00037   ros::Subscriber topic_sub_command_pos_;
00038   //ros::Subscriber topic_sub_command_vel_;
00039 
00041   ros::ServiceServer srv_server_init_;
00042   ros::ServiceServer srv_server_stop_;
00043   ros::ServiceServer srv_server_recover_;
00044   //ros::ServiceServer srv_server_operation_mode_;
00045 
00046   actionlib::SimpleActionServer<control_msgs::FollowJointTrajectoryAction> as_;
00047 
00049   MapDemonCtrlMaestro* md_ctrl_;
00050 
00052   DemonstratorParams* md_params_;
00053 
00055   //SerialDevice* md_sd_;
00056 
00058   bool initialized_;
00059   bool stopped_;
00060   bool error_;
00061   bool auto_init_;
00062   std::string error_msg_;
00063   ros::Time last_publish_time_;
00064 
00066   DemonstratorNode()
00067   :n_("~"),
00068    as_(n_, "follow_joint_trajectory", boost::bind(&DemonstratorNode::executeTrajectory, this, _1), false)
00069   {
00070     //n_ = ros::NodeHandle("~");
00071     //md_sd_ = new SerialDevice();
00072 
00073     md_params_ = new DemonstratorParams();
00074     md_ctrl_ = new MapDemonCtrlMaestro(md_params_);
00075 
00077     topic_pub_joint_state_ = n_.advertise<sensor_msgs::JointState> ("joint_states", 1);
00078     //topic_pub_operation_mode_ = n_.advertise<std_msgs::String> ("current_operationmode", 1);
00079     topic_pub_diagnostic_ = n_.advertise<diagnostic_msgs::DiagnosticArray>("diagnostics", 1);
00080 
00082     topic_sub_command_pos_ = n_.subscribe("command_pos", 1, &DemonstratorNode::topicCallbackCommandPos, this);
00083     //topic_sub_command_vel_ = n_.subscribe("command_vel", 1, &DemonstratorNode::topicCallbackCommandVel, this);
00084 
00086     srv_server_init_ = n_.advertiseService("init", &DemonstratorNode::srvCallbackInit, this);
00087     srv_server_stop_ = n_.advertiseService("stop", &DemonstratorNode::srvCallbackStop, this);
00088     srv_server_recover_ = n_.advertiseService("recover", &DemonstratorNode::srvCallbackRecover, this);
00089     //srv_server_operation_mode_ = n_.advertiseService("set_operation_mode", &DemonstratorNode::srvCallbackSetOperationMode, this);
00090 
00091     as_.start();
00092 
00093     initialized_ = false;
00094     stopped_ = true;
00095     error_ = false;
00096     last_publish_time_ = ros::Time::now();
00097   }
00098 
00100   ~DemonstratorNode()
00101   {
00102     delete md_ctrl_;
00103   }
00104 
00106   bool getROSParameters()
00107   {
00109     std::string serial_device = "ttyUSB0";
00110     if(n_.hasParam("serial_device"))
00111     {
00112       n_.getParam("serial_device", serial_device);
00113     }
00114     ROS_INFO("Serial device set to:\t\t%s", serial_device.c_str());
00115 
00117     int serial_baud_rate = 57600;
00118     if(n_.hasParam("serial_baudrate"))
00119     {
00120       n_.getParam("serial_baudrate", serial_baud_rate);
00121     }
00122     ROS_INFO("Serial baudrate set to:\t\t%d bps.", serial_baud_rate);
00124     md_params_->init(serial_device, serial_baud_rate);
00125 
00127     XmlRpc::XmlRpcValue joint_names_xml_rpc;
00128     std::vector<std::string> joint_names;
00129     if (n_.hasParam("joint_names"))
00130     {
00131       n_.getParam("joint_names", joint_names_xml_rpc);
00132       joint_names.resize(joint_names_xml_rpc.size());
00133       for (int i = 0; i < joint_names_xml_rpc.size(); i++)
00134       {
00135         joint_names[i] = (std::string)joint_names_xml_rpc[i];
00136       }
00137       md_params_->setJointNames(joint_names);
00138     }
00139     else
00140     {
00141       ROS_ERROR("Parameter joint_names not set, shutting down node...");
00142       return false;
00143     }
00144 
00146     //std::string opmode = "position";
00147     //if(n_.hasParam("operation_mode"))
00148     //{
00149     //  n_.getParam("operation_mode", opmode);
00150     //  md_params_->setOperationMode(opmode);
00151     //}
00152     //ROS_INFO("Operation mode set to: %s.", opmode.c_str());
00153 
00154     XmlRpc::XmlRpcValue velocities_xml_rpc;
00155     std::vector<double> velocities;
00156     if(n_.hasParam("velocities"))
00157     {
00158       n_.getParam("velocities", velocities_xml_rpc);
00159       velocities.resize(velocities_xml_rpc.size());
00160       for (int i = 0; i < velocities_xml_rpc.size(); i++)
00161       {
00162         velocities[i] = (double)velocities_xml_rpc[i];
00163       }
00164       md_params_->setVels(velocities);
00165     }
00166     ROS_INFO("Loaded position velocities");
00167 
00168     XmlRpc::XmlRpcValue accels_xml_rpc;
00169     std::vector<double> accelerations;
00170     if(n_.hasParam("accelerations"))
00171     {
00172       n_.getParam("accelerations", accels_xml_rpc);
00173       accelerations.resize(accels_xml_rpc.size());
00174       for (int i = 0; i < accels_xml_rpc.size(); i++)
00175       {
00176         accelerations[i] = (double)accels_xml_rpc[i];
00177       }
00178       md_params_->setAccels(accelerations);
00179     }
00180     ROS_INFO("Loaded position accelerations");
00181 
00182     joint_names.resize(joint_names_xml_rpc.size());
00183     for (int i = 0; i < joint_names_xml_rpc.size(); i++)
00184     {
00185       joint_names[i] = (std::string)joint_names_xml_rpc[i];
00186     }
00187 
00188     auto_init_ = true;
00189     if(n_.hasParam("auto_initialize"))
00190     {
00191       n_.getParam("auto_initialize", auto_init_);
00192     }
00193     ROS_INFO("Auto initialize set to: %d", auto_init_);
00194 
00195     ROS_INFO("Parameters initialisation successful.");
00196   }
00197 
00198   void getRobotDescriptionParameters()
00199   {
00200     std::vector<std::string> joint_names = md_params_->getJointNames();
00201     unsigned int dof = joint_names.size();      
00202     md_params_->setDOF(dof);
00203 
00204     urdf::Model model;
00205     ROS_DEBUG("Loading urdf");
00206     //Get robot urdf xml string from parameter server
00207     std::string param_descr = "/robot_description";
00208     if (n_.hasParam(param_descr))
00209     {
00210       model.initParam(param_descr);
00211       ROS_INFO("Successfuly loaded URDF description.");
00212     }
00213     else
00214     {
00215       ROS_ERROR("URDF not found, shutting down node...");
00216       n_.shutdown();
00217     }
00218 
00221     std::vector<double> max_velocities(dof);
00222     for (unsigned int i = 0; i < dof; i++)
00223     {
00224       max_velocities[i] = model.getJoint(joint_names[i].c_str())->limits->velocity;
00225     }
00227     std::vector<double> lower_limits(dof);
00228     for (unsigned int i = 0; i < dof; i++)
00229     {
00230       lower_limits[i] = model.getJoint(joint_names[i].c_str())->limits->lower;
00231     }
00232 
00233     // Get upper limits out of urdf model
00234     std::vector<double> upper_limits(dof);
00235     for (unsigned int i = 0; i < dof; i++)
00236     {
00237       upper_limits[i] = model.getJoint(joint_names[i].c_str())->limits->upper;
00238     }
00239 
00241     std::vector<double> offsets(dof);
00242     for (unsigned int i = 0; i < dof; i++)
00243     {
00244       offsets[i] = model.getJoint(joint_names[i].c_str())->calibration->rising.get()[0];
00245     }
00246 
00248     md_params_->setMaxVel(max_velocities);
00249     md_params_->setLowerLimits(lower_limits);
00250     md_params_->setUpperLimits(upper_limits);
00251     md_params_->setOffsets(offsets);
00252 
00253     ROS_DEBUG("Loading complete");
00254   }
00255 
00256   void runAutoInit()
00257   {
00258     if (md_ctrl_->init(md_params_))
00259     {
00260       initialized_ = true;
00261       ROS_INFO("...initializing COB3DMD successful");
00262     }
00263     else
00264     {
00265       error_ = true;
00266       error_msg_ = md_ctrl_->getErrorMessage();
00267       ROS_ERROR("...initializing COB3DMD unsuccessful. Error: %s", error_msg_.c_str());
00268     }
00269 
00270   }
00271 
00272   void executeTrajectory(const control_msgs::FollowJointTrajectoryGoalConstPtr &goal)
00273   {
00274     //ROS_INFO("trajectory");
00275     stopped_ = false;
00276     trajectory_msgs::JointTrajectory traj = goal->trajectory;
00277     for( unsigned int j = 0; j <traj.points.size(); j++)
00278     {
00279       brics_actuator::JointPositions::Ptr joint_pos(new brics_actuator::JointPositions());
00280       for(unsigned int i=0; i<traj.joint_names.size(); i++)
00281       {
00282         brics_actuator::JointValue jv;
00283         jv.joint_uri = traj.joint_names[i];
00284         jv.unit = "rad";
00285         jv.value = traj.points[j].positions[i];
00286         joint_pos->positions.push_back(jv);
00287       }
00288       topicCallbackCommandPos(joint_pos);
00289       while(!md_ctrl_->is_moving_ && !stopped_) usleep(1000);
00290       while(md_ctrl_->is_moving_ && !stopped_)
00291       {
00292         //is_moving_ = md_ctrl_->is_moving_;
00293         usleep(10000);
00294       }
00295     /*while(is_moving)
00296     {
00297       std::vector<double> pos = md_ctrl_->getPositions();
00298       //ROS_INFO("%f, %f", traj.points[0].positions[0], pos[0]);
00299       if( fabs(traj.points[0].positions[0]-pos[0])<0.05 &&  fabs(traj.points[0].positions[1]-pos[1])<0.05 )
00300         is_moving = false;
00301       if ( as_.isPreemptRequested() || stopped_)
00302       {
00303         as_.setPreempted();
00304         return;
00305       }
00306       usleep(1000);
00307     }*/
00308     }
00309     as_.setSucceeded();
00310   }
00311 
00312 
00313   void topicCallbackCommandPos(const brics_actuator::JointPositions::ConstPtr& msg)
00314   {
00315     ROS_DEBUG("Received new position command.");
00316     if(!initialized_)
00317     {
00318       ROS_WARN("Skipping command: mapping_demonstrator is not initialized");
00319       return;
00320     }
00321     if(stopped_) return;
00322 
00323     unsigned int DOF = md_params_->getDOF();
00324     std::vector<std::string> joint_names = md_params_->getJointNames();
00325     std::vector<double> cmd_pos(DOF);
00326     /*std::vector<double> lowerLimits = md_params_->getLowerLimits();
00327     std::vector<double> upperLimits = md_params_->getUpperLimits();
00328     std::vector<double> maxVels = md_params_->getMaxVel();*/
00329     std::string unit = "rad";
00330 
00332     if (msg->positions.size() != DOF)
00333     {
00334       ROS_ERROR("Skipping command: Commanded positions and DOF are not same dimension.");
00335       return;
00336     }
00337 
00339     for (unsigned int i = 0; i < DOF; i++)
00340     {
00342       if (msg->positions[i].joint_uri != joint_names[i])
00343       {
00344         ROS_ERROR("Skipping command: Received joint name %s doesn't match expected joint name %s for joint %d.", msg->positions[i].joint_uri.c_str(), joint_names[i].c_str(), i);
00345         return;
00346       }
00347 
00349       if (msg->positions[i].unit != unit)
00350       {
00351         ROS_ERROR("Skipping command: Received unit %s doesn't match expected unit %s.", msg->positions[i].unit.c_str(), unit.c_str());
00352         return;
00353       }
00354 
00356       /*if(msg->positions[i].value > upperLimits[i])
00357       {
00358         ROS_WARN("Position %f exceeds limit %f for axis %s.", msg->positions[i].value, upperLimits[i], JointNames[i].c_str());
00359         cmd_pos[i] = upperLimits[i];    // command upperLimit position
00360       }
00361       else if(msg->positions[i].value < lowerLimits[i])
00362       {
00363         ROS_WARN("Position %f exceeds limit %f for axis %s.", msg->positions[i].value, lowerLimits[i], JointNames[i].c_str());
00364         cmd_pos[i] = lowerLimits[i];    // command lowerLimit position
00365       }
00366       else
00367       {*/
00369       ROS_DEBUG("Parsing of position %f for joint %s successful.", msg->positions[i].value, joint_names[i].c_str());
00370       cmd_pos[i] = msg->positions[i].value;
00371       //}
00372     }
00373     // send both positions in the vector. '1' is ok. Any negative number is the index of the joint with error. 0 means that Jointnames were incorrect
00374     if( !md_ctrl_->movePos(cmd_pos) )
00375     {
00376       error_ = true;
00377       error_msg_ = md_ctrl_->getErrorMessage();
00378       ROS_ERROR("Joint reposition error: %s", md_ctrl_->getErrorMessage().c_str());
00379       return;
00380     }
00381 
00382     ROS_INFO("Successfully executed position command");
00383   }
00384 
00385   /*void topicCallbackCommandVel(const brics_actuator::JointVelocities::ConstPtr& msg)
00386   {
00387     ROS_DEBUG("Received new velocity command.");
00388 
00389     if(initialized_)
00390     {
00391       unsigned int DOF = md_params_->GetDOF();
00392       std::vector<std::string> JointNames = md_params_->GetJointNames();
00393       std::vector<double> cmd_vel(DOF);
00394       std::vector<double> maxVels = md_params_->GetMaxVel();
00395       std::string unit = "rad";
00396 
00398       if (msg->velocities.size() != DOF)
00399       {
00400         ROS_ERROR("Skipping command: Commanded velocities and DOF are not same dimension.");
00401         return;
00402       }
00403 
00405       for (unsigned int i = 0; i < DOF; i++)
00406       {
00408         if (msg->velocities[i].joint_uri != JointNames[i])
00409         {
00410           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);
00411           return;
00412         }
00413 
00415         if (msg->velocities[i].unit != unit)
00416         {
00417           ROS_ERROR("Skipping command: Received unit %s doesn't match expected unit %s.", msg->velocities[i].unit.c_str(), unit.c_str());
00418           return;
00419         }
00420 
00422         if(fabs(msg->velocities[i].value) > maxVels[i])
00423         {
00424           ROS_WARN("Velocity %f exceeds limit %f for axis %s.", msg->velocities[i].value, maxVels[i], JointNames[i].c_str());
00425           cmd_vel[i] = maxVels[i];      // command upperLimit position
00426         }
00427         else
00428         {
00430           ROS_DEBUG("Parsing of velocities %f for joint %s successful.", msg->velocities[i].value, JointNames[i].c_str());
00431           cmd_vel[i] = msg->velocities[i].value;
00432         }
00433       }
00434 
00435       if (!md_ctrl_->MoveVel(cmd_vel))  // send both positions in the vector
00436       {
00437         error_ = true;
00438         error_msg_ = md_ctrl_->getErrorMessage();
00439         ROS_ERROR("Skipping command: %s", md_ctrl_->getErrorMessage().c_str());
00440         return;
00441       }
00442 
00443       ROS_DEBUG("Executed velocity command");
00444     }
00445     else
00446     {
00447       ROS_WARN("Skipping command: mapping_demonstrator is not initialized");
00448     }
00449   }*/
00450 
00451   bool srvCallbackInit(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00452   {
00453     if (!initialized_)
00454     {
00455       ROS_INFO("Initializing COB3DMD...");
00456 
00458       if (md_ctrl_->init(md_params_))
00459       {
00460         initialized_ = true;
00461         res.success.data = true;        //Trigger.srv response
00462         ROS_INFO("...initializing COB3DMD successful");
00463       }
00464       else
00465       {
00466         error_ = true;
00467         error_msg_ = md_ctrl_->getErrorMessage();
00468         res.success.data = false;
00469         res.error_message.data = md_ctrl_->getErrorMessage();
00470         ROS_ERROR("...initializing COB3DMD unsuccessful. Error: %s", res.error_message.data.c_str());
00471       }
00472     }
00473     else
00474     {
00475       error_ = false;
00476       res.success.data = false;
00477       res.error_message.data = "COB3DMD already initialized";
00478       ROS_WARN("...initializing COB3DMD unsuccessful. Warn: %s", res.error_message.data.c_str());
00479     }
00480 
00481     return true;
00482   }
00486   bool srvCallbackStop(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00487   {
00488     if( initialized_ )
00489     {
00490       stopped_ = true;
00491       if( md_ctrl_->stop() )
00492       {
00493         ROS_INFO("Stopping COB3DMD successful");
00494         res.success.data = true;        //Trigger.srv response
00495         //stopped_ = true;
00496       }
00497       else
00498       {
00499         res.success.data = false;
00500         md_ctrl_->getErrorMessage();
00501         ROS_ERROR("!!...stopping COB3DMD unsuccessful. Error: %s", res.error_message.data.c_str());
00502       }
00503     }
00504     else
00505     {
00506       res.success.data = false;
00507       res.error_message.data = "Not initialized";
00508       ROS_WARN("...stopping COB3DMD unsuccessful. Warn: %s", res.error_message.data.c_str());
00509     }
00510     return true;
00511   }
00512 
00513   bool srvCallbackRecover(cob_srvs::Trigger::Request &req, cob_srvs::Trigger::Response &res)
00514   {
00515     ROS_WARN("Attempting to recover...");
00516 
00517     if (!initialized_)
00518     {
00519       error_msg_ = "Not Initialized";
00520       res.success.data = false;
00521       res.error_message.data = error_msg_;
00522       ROS_ERROR("...recovering COB3DMD unsuccessful. Error: %s", error_msg_.c_str());
00523       return false;
00524     }
00525     else
00526     {
00527       ROS_WARN("Recalibrating COB3DMD now...");
00528       if( !md_ctrl_->recover() )
00529       {
00530         error_ = true;
00531         error_msg_ = md_ctrl_->getErrorMessage();
00532         res.success.data = false;
00533         res.error_message.data = md_ctrl_->getErrorMessage();
00534         ROS_ERROR("...recovering COB3DMD unsuccessful. Error: %s", res.error_message.data.c_str());
00535         return false;
00536       }
00537       else
00538       {
00539         error_ = false;
00540         error_msg_ = "";
00541         res.success.data = true;
00542         res.error_message.data = error_msg_;
00543         ROS_INFO("...recovering COB3DMD successful");
00544         return true;
00545       }
00546     }
00547   }
00548 
00549   /*bool srvCallbackSetOperationMode(cob_srvs::SetOperationMode::Request &req, cob_srvs::SetOperationMode::Response &res)
00550   {
00551     if (req.operation_mode.data == "velocity")
00552     {
00553       md_params_->SetOperationMode("velocity");
00554       res.success.data = true;
00555     }
00556     else if (req.operation_mode.data == "position")
00557     {
00558       md_params_->SetOperationMode("position");
00559       res.success.data = true;
00560     }
00561     else
00562     {
00563       res.success.data = false;
00564     }
00565 
00566     ROS_INFO("Operation mode change request to %s succeded.", req.operation_mode.data.c_str());
00567     return true;
00568   }*/
00569 
00570   bool publishStates()
00571   {
00572     last_publish_time_ = ros::Time::now();
00573 
00574     if(initialized_)     
00575     {
00576       if( md_ctrl_->updatePositions() )
00577       {
00579         sensor_msgs::JointState joint_state_msg;
00580         joint_state_msg.header.stamp = ros::Time::now();
00581         joint_state_msg.header.frame_id = "COB3DMD";
00582         joint_state_msg.name = md_params_->getJointNames();
00583         joint_state_msg.position = md_ctrl_->getPositions();
00584         joint_state_msg.velocity = md_ctrl_->getVelocities();
00585 
00586         ROS_DEBUG("Publishing COB3DMD state");
00587         topic_pub_joint_state_.publish(joint_state_msg);
00588       }
00589       else
00590       {
00591         ROS_ERROR("Pan reported position incongruency. Run recal");
00592         error_ = true;
00593       }
00594     }
00595 
00597     /*std_msgs::String opmode_msg;
00598     opmode_msg.data = md_node->md_params_->GetOperationMode();
00599     md_node->topic_pub_operation_mode_.publish(opmode_msg);*/
00600 
00601     // publishing diagnotic messages
00602     diagnostic_msgs::DiagnosticArray diagnostics;
00603     diagnostics.status.resize(1);
00604 
00605     // set diagnostics
00606     if(error_)
00607     {
00608       diagnostics.status[0].level = 2;
00609       diagnostics.status[0].name = n_.getNamespace();;
00610       diagnostics.status[0].message = md_ctrl_->getErrorMessage();
00611     }
00612     else
00613     {
00614       if (initialized_)
00615       {
00616         diagnostics.status[0].level = 0;
00617         diagnostics.status[0].name = n_.getNamespace();
00618         diagnostics.status[0].message = "cob_3d_mapping_demonstrator is running";
00619       }
00620       else
00621       {
00622         diagnostics.status[0].level = 1;
00623         diagnostics.status[0].name = n_.getNamespace();
00624         diagnostics.status[0].message = "cob_3d_mapping_demonstrator not initialized";
00625       }
00626     }
00627     // publish diagnostic message
00628     topic_pub_diagnostic_.publish(diagnostics);
00629 
00630     return true;
00631   }
00632 };      // MapDemonDriverNode
00633 
00634 
00635 int main(int argc, char **argv)
00636 {
00637   //pthread_t th;       //publisher thread
00638 
00640   ros::init(argc, argv, "cob_3d_mapping_demonstrator_node");
00641 
00642   DemonstratorNode md_node;     
00643 
00644   if(!md_node.getROSParameters()) return 0;                                     
00645   md_node.getRobotDescriptionParameters();      
00646   if( md_node.auto_init_ )
00647     md_node.runAutoInit();
00648 
00650   double frequency;
00651   if (md_node.n_.hasParam("frequency"))
00652   {
00653     md_node.n_.getParam("frequency", frequency);
00654     ROS_INFO("Parameter frequency set to %f Hz", frequency);
00655   }
00656   else
00657   {
00658     frequency = 50 ;    //Hz
00659     ROS_WARN("Parameter frequency not defined, setting to %f Hz", frequency);
00660   }
00661 
00663   ros::Duration min_publish_duration;
00664   if (md_node.n_.hasParam("min_publish_duration"))
00665   {
00666     double sec;
00667     md_node.n_.getParam("min_publish_duration", sec);
00668     ROS_INFO("Parameter min publish duration set to %f seconds", sec);
00669     min_publish_duration.fromSec(sec);
00670   }
00671   else
00672   {
00673     min_publish_duration.fromSec(1 / frequency);
00674     ROS_WARN("Parameter min_publish_duration not defined, setting to %f sec", min_publish_duration.toSec());
00675   }
00676 
00678   ros::Rate loop_rate(frequency); // Hz
00679 
00680   while (md_node.n_.ok())
00681   {
00682     //if ((ros::Time::now() - md_node.last_publish_time_) >= min_publish_duration)
00683     {
00684       md_node.publishStates();
00685     }
00686 
00688     ros::spinOnce();
00689     loop_rate.sleep();
00690   }
00691 
00692   return 0;
00693 }


cob_3d_mapping_demonstrator
Author(s): Georg Arbeiter
autogenerated on Wed Aug 26 2015 11:03:46