ros_chain.cpp
Go to the documentation of this file.
1 #include <ros/package.h>
2 
4 
5 #include <std_msgs/Int8.h>
6 #include <std_msgs/Int16.h>
7 #include <std_msgs/Int32.h>
8 #include <std_msgs/Int64.h>
9 #include <std_msgs/UInt8.h>
10 #include <std_msgs/UInt16.h>
11 #include <std_msgs/UInt32.h>
12 #include <std_msgs/UInt64.h>
13 #include <std_msgs/Float32.h>
14 #include <std_msgs/Float64.h>
15 #include <std_msgs/String.h>
16 
17 namespace canopen {
18 
19 PublishFunc::FuncType PublishFunc::create(ros::NodeHandle &nh, const std::string &name, canopen::NodeSharedPtr node, const std::string &key, bool force){
20  ObjectStorageSharedPtr s = node->getStorage();
21 
22  switch(ObjectDict::DataTypes(s->dict_->get(key)->data_type)){
23  case ObjectDict::DEFTYPE_INTEGER8: return create< std_msgs::Int8 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_INTEGER8>::type>(key), force);
24  case ObjectDict::DEFTYPE_INTEGER16: return create< std_msgs::Int16 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_INTEGER16>::type>(key), force);
25  case ObjectDict::DEFTYPE_INTEGER32: return create< std_msgs::Int32 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_INTEGER32>::type>(key), force);
26  case ObjectDict::DEFTYPE_INTEGER64: return create< std_msgs::Int64 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_INTEGER64>::type>(key), force);
27 
28  case ObjectDict::DEFTYPE_UNSIGNED8: return create< std_msgs::UInt8 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_UNSIGNED8>::type>(key), force);
29  case ObjectDict::DEFTYPE_UNSIGNED16: return create< std_msgs::UInt16 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_UNSIGNED16>::type>(key), force);
30  case ObjectDict::DEFTYPE_UNSIGNED32: return create< std_msgs::UInt32 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_UNSIGNED32>::type>(key), force);
31  case ObjectDict::DEFTYPE_UNSIGNED64: return create< std_msgs::UInt64 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_UNSIGNED64>::type>(key), force);
32 
33  case ObjectDict::DEFTYPE_REAL32: return create< std_msgs::Float32 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_REAL32>::type>(key), force);
34  case ObjectDict::DEFTYPE_REAL64: return create< std_msgs::Float64 >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_REAL64>::type>(key), force);
35 
36  case ObjectDict::DEFTYPE_VISIBLE_STRING: return create< std_msgs::String >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_VISIBLE_STRING>::type>(key), force);
37  case ObjectDict::DEFTYPE_OCTET_STRING: return create< std_msgs::String >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_DOMAIN>::type>(key), force);
38  case ObjectDict::DEFTYPE_UNICODE_STRING: return create< std_msgs::String >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_UNICODE_STRING>::type>(key), force);
39  case ObjectDict::DEFTYPE_DOMAIN: return create< std_msgs::String >(nh, name, s->entry<ObjectStorage::DataType<ObjectDict::DEFTYPE_DOMAIN>::type>(key), force);
40 
41  default: return 0;
42  }
43 }
44 
46  can::DriverInterfaceSharedPtr interface = interface_;
47  std::string msg;
48  if(interface && !interface->translateError(s.internal_error, msg)) msg = "Undefined"; ;
49  ROS_INFO_STREAM("Current state: " << s.driver_state << " device error: " << s.error_code << " internal_error: " << s.internal_error << " (" << msg << ")");
50 }
51 
53  running_ = true;
54  time_point abs_time = boost::chrono::high_resolution_clock::now();
55  while(running_){
56  LayerStatus s;
57  try{
58  read(s);
59  write(s);
62  }
63  catch(const canopen::Exception& e){
64  ROS_ERROR_STREAM_THROTTLE(1, boost::diagnostic_information(e));
65  }
66  if(!sync_){
67  abs_time += update_duration_;
68  boost::this_thread::sleep_until(abs_time);
69  }
70  }
71 }
72 
73 bool RosChain::handle_init(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res){
74  ROS_INFO("Initializing XXX");
75  boost::mutex::scoped_lock lock(mutex_);
76  if(getLayerState() > Off){
77  res.success = true;
78  res.message = "already initialized";
79  return true;
80  }
81  thread_.reset(new boost::thread(&RosChain::run, this));
82  LayerReport status;
83  try{
84  init(status);
85  res.success = status.bounded<LayerStatus::Ok>();
86  res.message = status.reason();
87  if(!status.bounded<LayerStatus::Warn>()){
88  diag(status);
89  res.message = status.reason();
90  }else{
91  heartbeat_timer_.restart();
92  return true;
93  }
94  }
95  catch( const std::exception &e){
96  std::string info = boost::diagnostic_information(e);
97  ROS_ERROR_STREAM(info);
98  res.message = info;
99  status.error(res.message);
100  }
101  catch(...){
102  res.message = "Unknown exception";
103  status.error(res.message);
104  }
105 
106  res.success = false;
107  shutdown(status);
108 
109  return true;
110 }
111 bool RosChain::handle_recover(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res){
112  ROS_INFO("Recovering XXX");
113  boost::mutex::scoped_lock lock(mutex_);
114  res.success = false;
115 
116  if(getLayerState() > Init){
117  LayerReport status;
118  try{
119  if(!reset_errors_before_recover_ || emcy_handlers_->callFunc<LayerStatus::Warn>(&EMCYHandler::resetErrors, status)){
120  recover(status);
121  }
122  if(!status.bounded<LayerStatus::Warn>()){
123  diag(status);
124  }
125  res.success = status.bounded<LayerStatus::Warn>();
126  res.message = status.reason();
127  }
128  catch( const std::exception &e){
129  std::string info = boost::diagnostic_information(e);
130  ROS_ERROR_STREAM(info);
131  res.message = info;
132  }
133  catch(...){
134  res.message = "Unknown exception";
135  }
136  }else{
137  res.message = "not running";
138  }
139  return true;
140 }
141 
142 void RosChain::handleWrite(LayerStatus &status, const LayerState &current_state) {
143  LayerStack::handleWrite(status, current_state);
144  if(current_state > Shutdown){
145  for(std::vector<PublishFunc::FuncType>::iterator it = publishers_.begin(); it != publishers_.end(); ++it) (*it)();
146  }
147 }
148 
150  boost::mutex::scoped_lock lock(diag_mutex_);
151  heartbeat_timer_.stop();
153  if(running_){
154  running_ = false;
155  thread_->interrupt();
156  thread_->join();
157  thread_.reset();
158  }
159 }
160 
161 bool RosChain::handle_shutdown(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res){
162  ROS_INFO("Shuting down XXX");
163  boost::mutex::scoped_lock lock(mutex_);
164  res.success = true;
165  if(getLayerState() > Init){
166  LayerStatus s;
167  halt(s);
168  shutdown(s);
169  }else{
170  res.message = "not running";
171  }
172  return true;
173 }
174 
175 bool RosChain::handle_halt(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res){
176  ROS_INFO("Halting down XXX");
177  boost::mutex::scoped_lock lock(mutex_);
178  res.success = true;
179  if(getLayerState() > Init){
180  LayerStatus s;
181  halt(s);
182  }else{
183  res.message = "not running";
184  }
185  return true;
186 }
187 
188 bool RosChain::handle_get_object(canopen_chain_node::GetObject::Request &req, canopen_chain_node::GetObject::Response &res){
189  std::map<std::string, canopen::NodeSharedPtr >::iterator it = nodes_lookup_.find(req.node);
190  if(it == nodes_lookup_.end()){
191  res.message = "node not found";
192  }else{
193  try {
194  res.value = it->second->getStorage()->getStringReader(canopen::ObjectDict::Key(req.object), req.cached)();
195  res.success = true;
196  } catch(std::exception& e) {
197  res.message = boost::diagnostic_information(e);
198  }
199  }
200  return true;
201 }
202 
203 bool RosChain::handle_set_object(canopen_chain_node::SetObject::Request &req, canopen_chain_node::SetObject::Response &res){
204  std::map<std::string, canopen::NodeSharedPtr >::iterator it = nodes_lookup_.find(req.node);
205  if(it == nodes_lookup_.end()){
206  res.message = "node not found";
207  }else{
208  try {
209  it->second->getStorage()->getStringWriter(canopen::ObjectDict::Key(req.object), req.cached)(req.value);
210  res.success = true;
211  } catch(std::exception& e) {
212  res.message = boost::diagnostic_information(e);
213  }
214  }
215  return true;
216 }
217 
219  ros::NodeHandle bus_nh(nh_priv_,"bus");
220  std::string can_device;
221  std::string driver_plugin;
222  std::string master_alloc;
223  bool loopback;
224 
225  if(!bus_nh.getParam("device",can_device)){
226  ROS_ERROR("Device not set");
227  return false;
228  }
229 
230  bus_nh.param("loopback",loopback, false);
231 
232  bus_nh.param("driver_plugin",driver_plugin, std::string("can::SocketCANInterface"));
233 
234  try{
235  interface_ = driver_loader_.createInstance(driver_plugin);
236  }
237 
239  ROS_ERROR_STREAM(ex.what());
240  return false;
241  }
242 
243  state_listener_ = interface_->createStateListener(can::StateInterface::StateDelegate(this, &RosChain::logState));
244 
245  if(bus_nh.getParam("master_type",master_alloc)){
246  ROS_ERROR("please migrate to master allocators");
247  return false;
248  }
249 
250  bus_nh.param("master_allocator",master_alloc, std::string("canopen::SimpleMaster::Allocator"));
251 
252  try{
253  master_= master_allocator_.allocateInstance(master_alloc, can_device, interface_);
254  }
255  catch( const std::exception &e){
256  std::string info = boost::diagnostic_information(e);
257  ROS_ERROR_STREAM(info);
258  return false;
259  }
260 
261  if(!master_){
262  ROS_ERROR_STREAM("Could not allocate master.");
263  return false;
264  }
265 
266  add(boost::make_shared<CANLayer>(interface_, can_device, loopback));
267 
268  return true;
269 }
270 
272  ros::NodeHandle sync_nh(nh_priv_,"sync");
273 
274  int sync_ms = 0;
275  int sync_overflow = 0;
276 
277  if(!sync_nh.getParam("interval_ms", sync_ms)){
278  ROS_WARN("Sync interval was not specified, so sync is disabled per default");
279  }
280 
281  if(sync_ms < 0){
282  ROS_ERROR_STREAM("Sync interval "<< sync_ms << " is invalid");
283  return false;
284  }
285 
286  int update_ms = sync_ms;
287  if(sync_ms == 0) nh_priv_.getParam("update_ms", update_ms);
288  if(update_ms == 0){
289  ROS_ERROR_STREAM("Update interval "<< sync_ms << " is invalid");
290  return false;
291  }else{
292  update_duration_ = boost::chrono::milliseconds(update_ms);
293  }
294 
295  if(sync_ms){
296  if(!sync_nh.getParam("overflow", sync_overflow)){
297  ROS_WARN("Sync overflow was not specified, so overflow is disabled per default");
298  }
299  if(sync_overflow == 1 || sync_overflow > 240){
300  ROS_ERROR_STREAM("Sync overflow "<< sync_overflow << " is invalid");
301  return false;
302  }
303  if(sync_nh.param("silence_us", 0) != 0){
304  ROS_WARN("silence_us is not supported anymore");
305  }
306 
307  // TODO: parse header
308  sync_ = master_->getSync(SyncProperties(can::MsgHeader(0x80), sync_ms, sync_overflow));
309 
310  if(!sync_ && sync_ms){
311  ROS_ERROR_STREAM("Initializing sync master failed");
312  return false;
313  }
314  add(sync_);
315  }
316  return true;
317 }
318 
320  ros::NodeHandle hb_nh(nh_priv_,"heartbeat");
321  std::string msg;
322  double rate = 0;
323 
324  bool got_any = hb_nh.getParam("msg", msg);
325  got_any = hb_nh.getParam("rate", rate) || got_any;
326 
327  if( !got_any) return true; // nothing todo
328 
329  if(rate <=0 ){
330  ROS_ERROR_STREAM("Rate '"<< rate << "' is invalid");
331  return false;
332  }
333 
334  hb_sender_.frame = can::toframe(msg);
335 
336 
337  if(!hb_sender_.frame.isValid()){
338  ROS_ERROR_STREAM("Message '"<< msg << "' is invalid");
339  return false;
340  }
341 
342  hb_sender_.interface = interface_;
343 
344  heartbeat_timer_.start(Timer::TimerDelegate(&hb_sender_, &HeartbeatSender::send) , boost::chrono::duration<double>(1.0/rate), false);
345 
346  return true;
347 
348 
349 }
350 std::pair<std::string, bool> parseObjectName(std::string obj_name){
351  size_t pos = obj_name.find('!');
352  bool force = pos != std::string::npos;
353  if(force) obj_name.erase(pos);
354  return std::make_pair(obj_name, force);
355 }
356 
357 bool addLoggerEntries(XmlRpc::XmlRpcValue merged, const std::string param, uint8_t level, Logger &logger){
358  if(merged.hasMember(param)){
359  try{
360  XmlRpc::XmlRpcValue objs = merged[param];
361  for(int i = 0; i < objs.size(); ++i){
362  std::pair<std::string, bool> obj_name = parseObjectName(objs[i]);
363 
364  if(!logger.add(level, obj_name.first, obj_name.second)){
365  ROS_ERROR_STREAM("Could not create logger for '" << obj_name.first << "'");
366  return false;
367  }
368  }
369  }
370  catch(...){
371  ROS_ERROR_STREAM("Could not parse " << param << " parameter");
372  return false;
373  }
374  }
375  return true;
376 }
377 
379  nodes_.reset(new canopen::LayerGroupNoDiag<canopen::Node>("301 layer"));
380  add(nodes_);
381 
382  emcy_handlers_.reset(new canopen::LayerGroupNoDiag<canopen::EMCYHandler>("EMCY layer"));
383 
384  XmlRpc::XmlRpcValue nodes;
385  if(!nh_priv_.getParam("nodes", nodes)){
386  ROS_WARN("falling back to 'modules', please switch to 'nodes'");
387  nh_priv_.getParam("modules", nodes);
388  }
389  MergedXmlRpcStruct defaults;
390  nh_priv_.getParam("defaults", defaults);
391 
393  XmlRpc::XmlRpcValue new_stuct;
394  for(size_t i = 0; i < nodes.size(); ++i){
395  if(nodes[i].hasMember("name")){
396  std::string &name = nodes[i]["name"];
397  new_stuct[name] = nodes[i];
398  }else{
399  ROS_ERROR_STREAM("Node at list index " << i << " has no name");
400  return false;
401  }
402  }
403  nodes = new_stuct;
404  }
405 
406  for(XmlRpc::XmlRpcValue::iterator it = nodes.begin(); it != nodes.end(); ++it){
407  int node_id;
408  try{
409  node_id = it->second["id"];
410  }
411  catch(...){
412  ROS_ERROR_STREAM("Node '" << it->first << "' has no id");
413  return false;
414  }
415  MergedXmlRpcStruct merged(it->second, defaults);
416 
417  if(!it->second.hasMember("name")){
418  merged["name"]=it->first;
419  }
420 
421  ObjectDict::Overlay overlay;
422  if(merged.hasMember("dcf_overlay")){
423  XmlRpc::XmlRpcValue dcf_overlay = merged["dcf_overlay"];
424  if(dcf_overlay.getType() != XmlRpc::XmlRpcValue::TypeStruct){
425  ROS_ERROR_STREAM("dcf_overlay is no struct");
426  return false;
427  }
428  for(XmlRpc::XmlRpcValue::iterator ito = dcf_overlay.begin(); ito!= dcf_overlay.end(); ++ito){
429  if(ito->second.getType() != XmlRpc::XmlRpcValue::TypeString){
430  ROS_ERROR_STREAM("dcf_overlay '" << ito->first << "' must be string");
431  return false;
432  }
433  overlay.push_back(ObjectDict::Overlay::value_type(ito->first, ito->second));
434  }
435 
436  }
437 
438  std::string eds;
439 
440  try{
441  eds = (std::string) merged["eds_file"];
442  }
443  catch(...){
444  ROS_ERROR_STREAM("EDS path '" << eds << "' invalid");
445  return false;
446  }
447 
448  try{
449  if(merged.hasMember("eds_pkg")){
450  std::string pkg = merged["eds_pkg"];
451  std::string p = ros::package::getPath(pkg);
452  if(p.empty()){
453  ROS_WARN_STREAM("Package '" << pkg << "' was not found");
454  }else{
455  eds = (boost::filesystem::path(p)/eds).make_preferred().native();;
456  }
457  }
458  }
459  catch(...){
460  }
461 
462  ObjectDictSharedPtr dict = ObjectDict::fromFile(eds, overlay);
463  if(!dict){
464  ROS_ERROR_STREAM("EDS '" << eds << "' could not be parsed");
465  return false;
466  }
467  canopen::NodeSharedPtr node = boost::make_shared<canopen::Node>(interface_, dict, node_id, sync_);
468 
469  LoggerSharedPtr logger = boost::make_shared<Logger>(node);
470 
471  if(!nodeAdded(merged, node, logger)) return false;
472 
473  if(!addLoggerEntries(merged, "log", diagnostic_updater::DiagnosticStatusWrapper::OK, *logger)) return false;
474  if(!addLoggerEntries(merged, "log_warn", diagnostic_updater::DiagnosticStatusWrapper::WARN, *logger)) return false;
475  if(!addLoggerEntries(merged, "log_error", diagnostic_updater::DiagnosticStatusWrapper::ERROR, *logger)) return false;
476 
477  loggers_.push_back(logger);
478  diag_updater_.add(it->first, boost::bind(&Logger::log, logger, _1));
479 
480  std::string node_name = std::string(merged["name"]);
481 
482  if(merged.hasMember("publish")){
483  try{
484  XmlRpc::XmlRpcValue objs = merged["publish"];
485  for(int i = 0; i < objs.size(); ++i){
486  std::pair<std::string, bool> obj_name = parseObjectName(objs[i]);
487 
488  PublishFunc::FuncType pub = PublishFunc::create(nh_, node_name +"_"+obj_name.first, node, obj_name.first, obj_name.second);
489  if(!pub){
490  ROS_ERROR_STREAM("Could not create publisher for '" << obj_name.first << "'");
491  return false;
492  }
493  publishers_.push_back(pub);
494  }
495  }
496  catch(...){
497  ROS_ERROR("Could not parse publish parameter");
498  return false;
499  }
500  }
501  nodes_->add(node);
502  nodes_lookup_.insert(std::make_pair(node_name, node));
503 
504  boost::shared_ptr<canopen::EMCYHandler> emcy = boost::make_shared<canopen::EMCYHandler>(interface_, node->getStorage());
505  emcy_handlers_->add(emcy);
506  logger->add(emcy);
507 
508  }
509  return true;
510 }
512  return true;
513 }
514 
516  boost::mutex::scoped_lock lock(diag_mutex_);
517  LayerReport r;
518  if(getLayerState() == Off){
519  stat.summary(stat.WARN,"Not initailized");
520  }else if(!running_){
521  stat.summary(stat.ERROR,"Thread is not running");
522  }else{
523  diag(r);
524  if(r.bounded<LayerStatus::Unbounded>()){ // valid
525  stat.summary(r.get(), r.reason());
526  for(std::vector<std::pair<std::string, std::string> >::const_iterator it = r.values().begin(); it != r.values().end(); ++it){
527  stat.add(it->first, it->second);
528  }
529  }
530  }
531 }
532 
534 : LayerStack("ROS stack"),driver_loader_("socketcan_interface", "can::DriverInterface"),
535  master_allocator_("canopen_master", "canopen::Master::Allocator"),
536  nh_(nh), nh_priv_(nh_priv),
537  diag_updater_(nh_,nh_priv_),
538  running_(false),
539  reset_errors_before_recover_(false){}
540 
542  boost::mutex::scoped_lock lock(mutex_);
543  bool okay = setup_chain();
544  if(okay) add(emcy_handlers_);
545  return okay;
546 }
547 
549  std::string hw_id;
550  nh_priv_.param("hardware_id", hw_id, std::string("none"));
551  nh_priv_.param("reset_errors_before_recover", reset_errors_before_recover_, false);
552 
555 
557 
558  ros::NodeHandle nh_driver(nh_, "driver");
559 
560  srv_init_ = nh_driver.advertiseService("init",&RosChain::handle_init, this);
561  srv_recover_ = nh_driver.advertiseService("recover",&RosChain::handle_recover, this);
562  srv_halt_ = nh_driver.advertiseService("halt",&RosChain::handle_halt, this);
563  srv_shutdown_ = nh_driver.advertiseService("shutdown",&RosChain::handle_shutdown, this);
564 
565  srv_get_object_ = nh_driver.advertiseService("get_object",&RosChain::handle_get_object, this);
566  srv_set_object_ = nh_driver.advertiseService("set_object",&RosChain::handle_set_object, this);
567 
568  return setup_bus() && setup_sync() && setup_heartbeat() && setup_nodes();
569 }
570 
572  try{
573  LayerStatus s;
574  halt(s);
575  shutdown(s);
576  }catch(...){ LOG("CATCH"); }
577 }
578 
579 }
bool addLoggerEntries(XmlRpc::XmlRpcValue merged, const std::string param, uint8_t level, Logger &logger)
Definition: ros_chain.cpp:357
msg
virtual void add(const VectorMemberSharedPtr &l)
ros::Timer diag_timer_
Definition: ros_chain.h:181
ros::ServiceServer srv_shutdown_
Definition: ros_chain.h:187
#define ROS_ERROR_STREAM_THROTTLE(period, args)
std::list< std::pair< std::string, std::string > > Overlay
virtual void handleWrite(LayerStatus &status, const LayerState &current_state)
Definition: ros_chain.cpp:142
#define ROS_WARN_STREAM_THROTTLE(period, args)
ValueStruct::iterator iterator
ros::ServiceServer srv_set_object_
Definition: ros_chain.h:189
void shutdown(LayerStatus &status)
virtual bool handle_halt(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Definition: ros_chain.cpp:175
void summary(unsigned char lvl, const std::string s)
void init(const M_string &remappings)
int size() const
void setHardwareID(const std::string &hwid)
XmlRpcServer s
static FuncType create(ros::NodeHandle &nh, const std::string &name, canopen::NodeSharedPtr node, const std::string &key, bool force)
Definition: ros_chain.cpp:19
void add(const std::string &name, TaskFunction f)
virtual bool handle_init(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Definition: ros_chain.cpp:73
const std::string reason() const
bool reset_errors_before_recover_
Definition: ros_chain.h:205
static ObjectDictSharedPtr fromFile(const std::string &path, const Overlay &overlay=Overlay())
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
Type const & getType() const
virtual bool handle_recover(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Definition: ros_chain.cpp:111
#define ROS_WARN(...)
boost::mutex mutex_
Definition: ros_chain.h:183
bool handle_get_object(canopen_chain_node::GetObject::Request &req, canopen_chain_node::GetObject::Response &res)
Definition: ros_chain.cpp:188
ros::ServiceServer srv_init_
Definition: ros_chain.h:184
boost::function< void()> FuncType
Definition: ros_chain.h:22
Frame toframe(const std::string &s)
ros::ServiceServer srv_get_object_
Definition: ros_chain.h:188
ros::ServiceServer srv_halt_
Definition: ros_chain.h:186
void halt(LayerStatus &status)
virtual bool handle_shutdown(std_srvs::Trigger::Request &req, std_srvs::Trigger::Response &res)
Definition: ros_chain.cpp:161
boost::chrono::high_resolution_clock::time_point time_point
virtual ~RosChain()
Definition: ros_chain.cpp:571
virtual void handleShutdown(LayerStatus &status)
Definition: ros_chain.cpp:149
void report_diagnostics(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: ros_chain.cpp:515
void logState(const can::State &s)
Definition: ros_chain.cpp:45
bool setup_heartbeat()
Definition: ros_chain.cpp:319
#define LOG(log)
ros::NodeHandle nh_priv_
Definition: ros_chain.h:178
#define ROS_INFO(...)
std::pair< std::string, bool > parseObjectName(std::string obj_name)
Definition: ros_chain.cpp:350
bool param(const std::string &param_name, T &param_val, const T &default_val) const
virtual void log(diagnostic_updater::DiagnosticStatusWrapper &stat)
Definition: ros_chain.h:97
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
void resetErrors(LayerStatus &status)
const std::vector< std::pair< std::string, std::string > > & values() const
#define ROS_WARN_STREAM(args)
enum can::State::DriverState driver_state
ROSLIB_DECL std::string getPath(const std::string &package_name)
virtual bool nodeAdded(XmlRpc::XmlRpcValue &params, const canopen::NodeSharedPtr &node, const LoggerSharedPtr &logger)
Definition: ros_chain.cpp:511
bool hasMember(const std::string &name) const
RosChain(const ros::NodeHandle &nh, const ros::NodeHandle &nh_priv)
Definition: ros_chain.cpp:533
#define ROS_INFO_STREAM(args)
ROSCONSOLE_DECL void shutdown()
bool getParam(const std::string &key, std::string &s) const
virtual bool setup_chain()
Definition: ros_chain.cpp:548
const void error(const std::string &r)
virtual void handleWrite(LayerStatus &status, const LayerState &current_state)
diagnostic_updater::Updater diag_updater_
Definition: ros_chain.h:180
unsigned int internal_error
void add(const std::string &key, const T &val)
#define ROS_ERROR_STREAM(args)
#define ROS_ERROR(...)
bool add(uint8_t level, const std::string &key, bool forced)
Definition: ros_chain.h:79
bool bounded() const
ros::ServiceServer srv_recover_
Definition: ros_chain.h:185
ros::NodeHandle nh_
Definition: ros_chain.h:177
virtual void handleShutdown(LayerStatus &status)
bool handle_set_object(canopen_chain_node::SetObject::Request &req, canopen_chain_node::SetObject::Response &res)
Definition: ros_chain.cpp:203
boost::system::error_code error_code
boost::shared_ptr< canopen::LayerGroupNoDiag< canopen::EMCYHandler > > emcy_handlers_
Definition: ros_chain.h:167


canopen_chain_node
Author(s): Mathias Lüdtke
autogenerated on Sat May 4 2019 02:40:46