ros2_canopen  master
C++ ROS CANopen Library
node_canopen_driver.hpp
Go to the documentation of this file.
1 #ifndef NODE_CANOPEN_DRIVER_HPP_
2 #define NODE_CANOPEN_DRIVER_HPP_
3 
4 #include <yaml-cpp/yaml.h>
5 #include <atomic>
6 #include <lely/coapp/driver.hpp>
7 #include <map>
8 #include <memory>
9 #include <rclcpp/node_interfaces/node_base_interface.hpp>
10 #include <rclcpp/node_interfaces/node_clock_interface.hpp>
11 #include <rclcpp/node_interfaces/node_graph_interface.hpp>
12 #include <rclcpp/node_interfaces/node_logging_interface.hpp>
13 #include <rclcpp/node_interfaces/node_parameters_interface.hpp>
14 #include <rclcpp/node_interfaces/node_services_interface.hpp>
15 #include <rclcpp/node_interfaces/node_time_source_interface.hpp>
16 #include <rclcpp/node_interfaces/node_timers_interface.hpp>
17 #include <rclcpp/node_interfaces/node_topics_interface.hpp>
18 #include <rclcpp/node_interfaces/node_waitables_interface.hpp>
19 #include <rclcpp/rclcpp.hpp>
20 #include <rclcpp_lifecycle/lifecycle_node.hpp>
21 #include <type_traits>
22 #include <vector>
26 #include "canopen_interfaces/srv/co_node.hpp"
27 
28 using namespace rclcpp;
29 namespace ros2_canopen
30 {
31 namespace node_interfaces
32 {
44 template <class NODETYPE>
46 {
47  static_assert(
48  std::is_base_of<rclcpp::Node, NODETYPE>::value ||
49  std::is_base_of<rclcpp_lifecycle::LifecycleNode, NODETYPE>::value,
50  "NODETYPE must derive from rclcpp::Node or rclcpp_lifecycle::LifecycleNode");
51 
52 protected:
53  NODETYPE * node_;
54 
55  std::shared_ptr<lely::ev::Executor> exec_;
56  std::shared_ptr<lely::canopen::AsyncMaster> master_;
57  std::shared_ptr<lely::canopen::BasicDriver> driver_;
58 
59  std::chrono::milliseconds non_transmit_timeout_;
60  YAML::Node config_;
61  uint8_t node_id_;
62  std::string container_name_;
63  std::string eds_;
64  std::string bin_;
65 
66  rclcpp::CallbackGroup::SharedPtr client_cbg_;
67  rclcpp::CallbackGroup::SharedPtr timer_cbg_;
68 
69  std::atomic<bool> master_set_;
70  std::atomic<bool> initialised_;
71  std::atomic<bool> configured_;
72  std::atomic<bool> activated_;
73 
74 public:
75  NodeCanopenDriver(NODETYPE * node)
76  : master_set_(false), initialised_(false), configured_(false), activated_(false)
77  {
78  node_ = node;
79  }
80 
88  virtual void set_master(
89  std::shared_ptr<lely::ev::Executor> exec, std::shared_ptr<lely::canopen::AsyncMaster> master)
90  {
91  RCLCPP_DEBUG(node_->get_logger(), "set_master_start");
92  if (!configured_.load())
93  {
94  throw DriverException("Set Master: driver is not configured");
95  }
96  if (activated_.load())
97  {
98  throw DriverException("Set Master: driver is not activated");
99  }
100  this->exec_ = exec;
101  this->master_ = master;
102  this->master_set_.store(true);
103  RCLCPP_DEBUG(node_->get_logger(), "set_master_end");
104  }
105 
113  void init()
114  {
115  RCLCPP_DEBUG(node_->get_logger(), "init_start");
116  if (configured_.load())
117  {
118  throw DriverException("Init: Driver is already configured");
119  }
120  if (activated_.load())
121  {
122  throw DriverException("Init: Driver is already activated");
123  }
124  client_cbg_ = node_->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
125  timer_cbg_ = node_->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
126 
127  node_->declare_parameter("container_name", "");
128  node_->declare_parameter("node_id", 0);
129  node_->declare_parameter("non_transmit_timeout", 100);
130  node_->declare_parameter("config", "");
131  this->init(true);
132  this->initialised_.store(true);
133  RCLCPP_DEBUG(node_->get_logger(), "init_end");
134  }
135 
148  virtual void init(bool called_from_base) {}
149 
161  void configure()
162  {
163  RCLCPP_DEBUG(node_->get_logger(), "configure_start");
164  if (!initialised_.load())
165  {
166  throw DriverException("Configure: driver is not initialised");
167  }
168  if (configured_.load())
169  {
170  throw DriverException("Configure: driver is already configured");
171  }
172  if (activated_.load())
173  {
174  throw DriverException("Configure: driver is already activated");
175  }
176  int non_transmit_timeout;
177  std::string config;
178  node_->get_parameter("container_name", container_name_);
179  node_->get_parameter("non_transmit_timeout", non_transmit_timeout);
180  node_->get_parameter("node_id", this->node_id_);
181  node_->get_parameter("config", config);
182  this->config_ = YAML::Load(config);
183  this->non_transmit_timeout_ = std::chrono::milliseconds(non_transmit_timeout);
184  auto path = this->config_["dcf_path"].as<std::string>();
185  auto dcf = this->config_["dcf"].as<std::string>();
186  auto name = this->node_->get_name();
187  eds_ = path + "/" + dcf;
188  bin_ = path + "/" + name + ".bin";
189  this->configure(true);
190  this->configured_.store(true);
191  RCLCPP_DEBUG(node_->get_logger(), "configure_end");
192  }
200  virtual void configure(bool called_from_base) {}
201 
209  void activate()
210  {
211  RCLCPP_DEBUG(node_->get_logger(), "activate_start");
212  if (!master_set_.load())
213  {
214  throw DriverException("Activate: master is not set");
215  }
216  if (!initialised_.load())
217  {
218  throw DriverException("Activate: driver is not initialised");
219  }
220  if (!configured_.load())
221  {
222  throw DriverException("Activate: driver is not configured");
223  }
224  if (activated_.load())
225  {
226  throw DriverException("Activate: driver is already activated");
227  }
228  this->add_to_master();
229  this->activate(true);
230  this->activated_.store(true);
231  RCLCPP_DEBUG(node_->get_logger(), "activate_end");
232  }
233 
242  virtual void activate(bool called_from_base) {}
243 
251  void deactivate()
252  {
253  RCLCPP_DEBUG(node_->get_logger(), "deactivate_start");
254  if (!master_set_.load())
255  {
256  throw DriverException("Activate: master is not set");
257  }
258  if (!initialised_.load())
259  {
260  throw DriverException("Deactivate: driver is not initialised");
261  }
262  if (!configured_.load())
263  {
264  throw DriverException("Deactivate: driver is not configured");
265  }
266  if (!activated_.load())
267  {
268  throw DriverException("Deactivate: driver is not activated");
269  }
270  this->activated_.store(false);
271  this->remove_from_master();
272  this->deactivate(true);
273  RCLCPP_DEBUG(node_->get_logger(), "deactivate_end");
274  }
282  virtual void deactivate(bool called_from_base) {}
283 
291  void cleanup()
292  {
293  if (!initialised_.load())
294  {
295  throw DriverException("Cleanup: driver is not initialised");
296  }
297  if (!configured_.load())
298  {
299  throw DriverException("Cleanup: driver is not configured");
300  }
301  if (activated_.load())
302  {
303  throw DriverException("Cleanup: driver is still activated");
304  }
305  this->configured_.store(false);
306  }
307 
315  virtual void cleanup(bool called_from_base) {}
316 
323  void shutdown()
324  {
325  RCLCPP_DEBUG(this->node_->get_logger(), "Shutting down.");
326  if (this->activated_)
327  {
328  this->deactivate();
329  }
330  if (this->configured_)
331  {
332  this->cleanup();
333  }
334  shutdown(true);
335  this->master_set_.store(false);
336  this->initialised_.store(false);
337  this->configured_.store(false);
338  this->activated_.store(false);
339  }
347  virtual void shutdown(bool called_from_base) {}
348 
349  virtual void demand_set_master();
350 
351 protected:
356  virtual void add_to_master() { throw DriverException("Add to master not implemented."); }
357 
362  virtual void remove_from_master()
363  {
364  throw DriverException("Remove from master not implemented.");
365  }
366 };
367 } // namespace node_interfaces
368 } // namespace ros2_canopen
369 
370 #endif
Driver Exception.
Definition: driver_error.hpp:17
Node Canopen Driver Interface.
Definition: node_canopen_driver_interface.hpp:19
Node Canopen Driver.
Definition: node_canopen_driver.hpp:46
std::string bin_
Definition: node_canopen_driver.hpp:64
virtual void remove_from_master()
Remove the driver from master.
Definition: node_canopen_driver.hpp:362
std::atomic< bool > initialised_
Definition: node_canopen_driver.hpp:70
void shutdown()
Shutdown the driver.
Definition: node_canopen_driver.hpp:323
virtual void init(bool called_from_base)
Initialises the driver.
Definition: node_canopen_driver.hpp:148
std::atomic< bool > master_set_
Definition: node_canopen_driver.hpp:69
std::string eds_
Definition: node_canopen_driver.hpp:63
void deactivate()
Deactivate the driver.
Definition: node_canopen_driver.hpp:251
std::atomic< bool > configured_
Definition: node_canopen_driver.hpp:71
void cleanup()
Cleanup the driver.
Definition: node_canopen_driver.hpp:291
void activate()
Activate the driver.
Definition: node_canopen_driver.hpp:209
std::string container_name_
Definition: node_canopen_driver.hpp:62
NODETYPE * node_
Definition: node_canopen_driver.hpp:50
virtual void demand_set_master()
Demand set Master.
uint8_t node_id_
Definition: node_canopen_driver.hpp:61
std::atomic< bool > activated_
Definition: node_canopen_driver.hpp:72
virtual void set_master(std::shared_ptr< lely::ev::Executor > exec, std::shared_ptr< lely::canopen::AsyncMaster > master)
Set Master.
Definition: node_canopen_driver.hpp:88
rclcpp::CallbackGroup::SharedPtr client_cbg_
Definition: node_canopen_driver.hpp:66
virtual void deactivate(bool called_from_base)
Deactivates the driver.
Definition: node_canopen_driver.hpp:282
std::shared_ptr< lely::canopen::BasicDriver > driver_
Definition: node_canopen_driver.hpp:57
void init()
Initialise the driver.
Definition: node_canopen_driver.hpp:113
void configure()
Configure the driver.
Definition: node_canopen_driver.hpp:161
virtual void cleanup(bool called_from_base)
Cleanup the driver.
Definition: node_canopen_driver.hpp:315
rclcpp::CallbackGroup::SharedPtr timer_cbg_
Definition: node_canopen_driver.hpp:67
virtual void add_to_master()
Add the driver to master.
Definition: node_canopen_driver.hpp:356
virtual void shutdown(bool called_from_base)
Shuts down the driver.
Definition: node_canopen_driver.hpp:347
virtual void activate(bool called_from_base)
Activates the driver.
Definition: node_canopen_driver.hpp:242
std::chrono::milliseconds non_transmit_timeout_
Definition: node_canopen_driver.hpp:59
std::shared_ptr< lely::canopen::AsyncMaster > master_
Definition: node_canopen_driver.hpp:56
YAML::Node config_
Definition: node_canopen_driver.hpp:60
NodeCanopenDriver(NODETYPE *node)
Definition: node_canopen_driver.hpp:75
std::shared_ptr< lely::ev::Executor > exec_
Definition: node_canopen_driver.hpp:55
virtual void configure(bool called_from_base)
Configure the driver.
Definition: node_canopen_driver.hpp:200
Definition: configuration_manager.hpp:28