ros2_canopen  master
C++ ROS CANopen Library
node_canopen_proxy_driver_impl.hpp
Go to the documentation of this file.
1 #ifndef NODE_CANOPEN_PROXY_DRIVER_IMPL_HPP_
2 #define NODE_CANOPEN_PROXY_DRIVER_IMPL_HPP_
3 
6 
7 using namespace ros2_canopen::node_interfaces;
8 
9 template <class NODETYPE>
11 : ros2_canopen::node_interfaces::NodeCanopenBaseDriver<NODETYPE>(node)
12 {
13 }
14 
15 template <class NODETYPE>
16 void NodeCanopenProxyDriver<NODETYPE>::init(bool called_from_base)
17 {
18  RCLCPP_ERROR(this->node_->get_logger(), "Not init implemented.");
19 }
20 
21 template <>
22 void NodeCanopenProxyDriver<rclcpp::Node>::init(bool called_from_base)
23 {
24  nmt_state_publisher = this->node_->create_publisher<std_msgs::msg::String>(
25  std::string(this->node_->get_name()).append("/nmt_state").c_str(), 10);
26  tpdo_subscriber = this->node_->create_subscription<canopen_interfaces::msg::COData>(
27  std::string(this->node_->get_name()).append("/tpdo").c_str(), 10,
28  std::bind(&NodeCanopenProxyDriver<rclcpp::Node>::on_tpdo, this, std::placeholders::_1));
29 
30  rpdo_publisher = this->node_->create_publisher<canopen_interfaces::msg::COData>(
31  std::string(this->node_->get_name()).append("/rpdo").c_str(), 10);
32 
33  nmt_state_reset_service = this->node_->create_service<std_srvs::srv::Trigger>(
34  std::string(this->node_->get_name()).append("/nmt_reset_node").c_str(),
35  std::bind(
37  std::placeholders::_2));
38 
39  nmt_state_start_service = this->node_->create_service<std_srvs::srv::Trigger>(
40  std::string(this->node_->get_name()).append("/nmt_start_node").c_str(),
41  std::bind(
43  std::placeholders::_2));
44 
45  sdo_read_service = this->node_->create_service<canopen_interfaces::srv::CORead>(
46  std::string(this->node_->get_name()).append("/sdo_read").c_str(),
47  std::bind(
48  &NodeCanopenProxyDriver<rclcpp::Node>::on_sdo_read, this, std::placeholders::_1,
49  std::placeholders::_2));
50 
51  sdo_write_service = this->node_->create_service<canopen_interfaces::srv::COWrite>(
52  std::string(this->node_->get_name()).append("/sdo_write").c_str(),
53  std::bind(
54  &NodeCanopenProxyDriver<rclcpp::Node>::on_sdo_write, this, std::placeholders::_1,
55  std::placeholders::_2));
56 }
57 
58 template <>
60 {
61  nmt_state_publisher = this->node_->create_publisher<std_msgs::msg::String>(
62  std::string(this->node_->get_name()).append("/nmt_state").c_str(), 10);
63  tpdo_subscriber = this->node_->create_subscription<canopen_interfaces::msg::COData>(
64  std::string(this->node_->get_name()).append("/tpdo").c_str(), 10,
65  std::bind(
67  std::placeholders::_1));
68 
69  rpdo_publisher = this->node_->create_publisher<canopen_interfaces::msg::COData>(
70  std::string(this->node_->get_name()).append("/rpdo").c_str(), 10);
71 
72  nmt_state_reset_service = this->node_->create_service<std_srvs::srv::Trigger>(
73  std::string(this->node_->get_name()).append("/nmt_reset_node").c_str(),
74  std::bind(
76  std::placeholders::_1, std::placeholders::_2));
77 
78  nmt_state_start_service = this->node_->create_service<std_srvs::srv::Trigger>(
79  std::string(this->node_->get_name()).append("/nmt_start_node").c_str(),
80  std::bind(
82  std::placeholders::_1, std::placeholders::_2));
83 
84  sdo_read_service = this->node_->create_service<canopen_interfaces::srv::CORead>(
85  std::string(this->node_->get_name()).append("/sdo_read").c_str(),
86  std::bind(
88  std::placeholders::_1, std::placeholders::_2));
89 
90  sdo_write_service = this->node_->create_service<canopen_interfaces::srv::COWrite>(
91  std::string(this->node_->get_name()).append("/sdo_write").c_str(),
92  std::bind(
94  std::placeholders::_1, std::placeholders::_2));
95 }
96 
97 template <class NODETYPE>
98 void NodeCanopenProxyDriver<NODETYPE>::on_nmt(canopen::NmtState nmt_state)
99 {
100  if (this->activated_.load())
101  {
102  auto message = std_msgs::msg::String();
103 
104  switch (nmt_state)
105  {
106  case canopen::NmtState::BOOTUP:
107  message.data = "BOOTUP";
108  break;
109  case canopen::NmtState::PREOP:
110  message.data = "PREOP";
111  break;
112  case canopen::NmtState::RESET_COMM:
113  message.data = "RESET_COMM";
114  break;
115  case canopen::NmtState::RESET_NODE:
116  message.data = "RESET_NODE";
117  break;
118  case canopen::NmtState::START:
119  message.data = "START";
120  break;
121  case canopen::NmtState::STOP:
122  message.data = "STOP";
123  break;
124  case canopen::NmtState::TOGGLE:
125  message.data = "TOGGLE";
126  break;
127  default:
128  RCLCPP_ERROR(this->node_->get_logger(), "Unknown NMT State.");
129  message.data = "ERROR";
130  break;
131  }
132  RCLCPP_INFO(
133  this->node_->get_logger(), "Slave %hhu: Switched NMT state to %s",
134  this->lely_driver_->get_id(), message.data.c_str());
135 
136  nmt_state_publisher->publish(message);
137  }
138 }
139 
140 template <class NODETYPE>
141 void NodeCanopenProxyDriver<NODETYPE>::on_tpdo(const canopen_interfaces::msg::COData::SharedPtr msg)
142 {
143  ros2_canopen::COData data = {msg->index, msg->subindex, msg->data};
144  if (!tpdo_transmit(data))
145  {
146  RCLCPP_ERROR(this->node_->get_logger(), "Could transmit PDO because driver not activated.");
147  }
148 }
149 
150 template <class NODETYPE>
152 {
153  if (this->activated_.load())
154  {
155  RCLCPP_INFO(
156  this->node_->get_logger(), "Node ID %hhu: Transmit PDO index %x, subindex %hhu, data %d",
157  this->lely_driver_->get_id(), data.index_, data.subindex_,
158  data.data_); // ToDo: Remove or make debug
159  this->lely_driver_->tpdo_transmit(data);
160  return true;
161  }
162  return false;
163 }
164 
165 template <class NODETYPE>
167 {
168  if (this->activated_.load())
169  {
170  // RCLCPP_INFO(
171  // this->node_->get_logger(), "Node ID %hhu: Received PDO index %#04x, subindex %hhu, data
172  // %x", this->lely_driver_->get_id(), d.index_, d.subindex_, d.data_);
173  auto message = canopen_interfaces::msg::COData();
174  message.index = d.index_;
175  message.subindex = d.subindex_;
176  message.data = d.data_;
177  rpdo_publisher->publish(message);
178  }
179 }
180 
181 template <class NODETYPE>
183  const std_srvs::srv::Trigger::Request::SharedPtr request,
184  std_srvs::srv::Trigger::Response::SharedPtr response)
185 {
186  response->success = reset_node_nmt_command();
187 }
188 
189 template <class NODETYPE>
191 {
192  if (this->activated_.load())
193  {
194  this->lely_driver_->nmt_command(canopen::NmtCommand::RESET_NODE);
195  return true;
196  }
197  RCLCPP_ERROR(
198  this->node_->get_logger(), "Could not reset device via NMT because driver not activated.");
199  return false;
200 }
201 
202 template <class NODETYPE>
204  const std_srvs::srv::Trigger::Request::SharedPtr request,
205  std_srvs::srv::Trigger::Response::SharedPtr response)
206 {
207  response->success = start_node_nmt_command();
208 }
209 
210 template <class NODETYPE>
212 {
213  if (this->activated_.load())
214  {
215  this->lely_driver_->nmt_command(canopen::NmtCommand::START);
216  return true;
217  }
218  RCLCPP_ERROR(
219  this->node_->get_logger(), "Could not start device via NMT because driver not activated.");
220  return false;
221 }
222 
223 template <class NODETYPE>
225  const canopen_interfaces::srv::CORead::Request::SharedPtr request,
226  canopen_interfaces::srv::CORead::Response::SharedPtr response)
227 {
228  ros2_canopen::COData data = {request->index, request->subindex, 0U};
229  response->success = sdo_read(data);
230  response->data = data.data_;
231 }
232 
233 template <class NODETYPE>
235 {
236  if (this->activated_.load())
237  {
238  RCLCPP_INFO(
239  this->node_->get_logger(), "Slave %hhu: SDO Read Call index=0x%x subindex=%hhu",
240  this->lely_driver_->get_id(), data.index_, data.subindex_);
241 
242  // Only allow one SDO request concurrently
243  std::scoped_lock<std::mutex> lk(sdo_mtex);
244  // Send read request
245  auto f = this->lely_driver_->async_sdo_read(data);
246  // Wait for response
247  f.wait();
248  // Process response
249  try
250  {
251  data.data_ = f.get().data_;
252  }
253  catch (std::exception & e)
254  {
255  RCLCPP_ERROR(this->node_->get_logger(), e.what());
256  return false;
257  }
258  return true;
259  }
260  RCLCPP_ERROR(this->node_->get_logger(), "Could not read from SDO because driver not activated.");
261  return false;
262 }
263 
264 template <class NODETYPE>
266  const canopen_interfaces::srv::COWrite::Request::SharedPtr request,
267  canopen_interfaces::srv::COWrite::Response::SharedPtr response)
268 {
269  ros2_canopen::COData data = {request->index, request->subindex, request->data};
270  response->success = sdo_write(data);
271 }
272 
273 template <class NODETYPE>
275 {
276  if (this->activated_.load())
277  {
278  RCLCPP_INFO(
279  this->node_->get_logger(), "Slave %hhu: SDO Write Call index=0x%x subindex=%hhu data=%u",
280  this->lely_driver_->get_id(), data.index_, data.subindex_, data.data_);
281 
282  // Only allow one SDO request concurrently
283  std::scoped_lock<std::mutex> lk(sdo_mtex);
284 
285  // Send write request
286  auto f = this->lely_driver_->async_sdo_write(data);
287  // Wait for request to complete
288  f.wait();
289 
290  // Process response
291  try
292  {
293  return f.get();
294  }
295  catch (std::exception & e)
296  {
297  RCLCPP_ERROR(this->node_->get_logger(), e.what());
298  return false;
299  }
300  return true;
301  }
302  RCLCPP_ERROR(this->node_->get_logger(), "Could not write to SDO because driver not activated.");
303  return false;
304 }
305 
306 #endif
Definition: node_canopen_base_driver.hpp:19
void init()
Initialise the driver.
Definition: node_canopen_driver.hpp:113
Definition: node_canopen_proxy_driver.hpp:12
void on_sdo_read(const canopen_interfaces::srv::CORead::Request::SharedPtr request, canopen_interfaces::srv::CORead::Response::SharedPtr response)
Definition: node_canopen_proxy_driver_impl.hpp:224
virtual bool sdo_write(COData &data)
Definition: node_canopen_proxy_driver_impl.hpp:274
void on_nmt_state_reset(const std_srvs::srv::Trigger::Request::SharedPtr request, std_srvs::srv::Trigger::Response::SharedPtr response)
Definition: node_canopen_proxy_driver_impl.hpp:182
void on_sdo_write(const canopen_interfaces::srv::COWrite::Request::SharedPtr request, canopen_interfaces::srv::COWrite::Response::SharedPtr response)
Definition: node_canopen_proxy_driver_impl.hpp:265
void on_nmt_state_start(const std_srvs::srv::Trigger::Request::SharedPtr request, std_srvs::srv::Trigger::Response::SharedPtr response)
Definition: node_canopen_proxy_driver_impl.hpp:203
virtual void on_rpdo(COData data) override
Definition: node_canopen_proxy_driver_impl.hpp:166
NodeCanopenProxyDriver(NODETYPE *node)
Definition: node_canopen_proxy_driver_impl.hpp:10
virtual bool reset_node_nmt_command()
Definition: node_canopen_proxy_driver_impl.hpp:190
virtual void on_tpdo(const canopen_interfaces::msg::COData::SharedPtr msg)
Definition: node_canopen_proxy_driver_impl.hpp:141
virtual bool tpdo_transmit(COData &data)
Definition: node_canopen_proxy_driver_impl.hpp:151
virtual bool start_node_nmt_command()
Definition: node_canopen_proxy_driver_impl.hpp:211
virtual void on_nmt(canopen::NmtState nmt_state) override
Definition: node_canopen_proxy_driver_impl.hpp:98
virtual bool sdo_read(COData &data)
Definition: node_canopen_proxy_driver_impl.hpp:234
Definition: node_canopen_driver.hpp:32
Definition: configuration_manager.hpp:28
Definition: exchange.hpp:26
uint32_t data_
Definition: exchange.hpp:30
uint8_t subindex_
Definition: exchange.hpp:29
uint16_t index_
Definition: exchange.hpp:28