ros2_canopen master
C++ ROS CANopen Library
Loading...
Searching...
No Matches
device_container.hpp
Go to the documentation of this file.
1// Copyright 2022 Harshavadan Deshpande
2// Christoph Hellmann Santos
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16#ifndef LIFECYCLE_DEVICE_CONTAINER_NODE_HPP
17#define LIFECYCLE_DEVICE_CONTAINER_NODE_HPP
18
19#include <chrono>
20#include <memory>
21#include <rclcpp/executors.hpp>
22#include <rclcpp_components/component_manager.hpp>
23#include <vector>
28#include "canopen_interfaces/srv/co_node.hpp"
29#include "rcl_interfaces/srv/set_parameters.hpp"
30
31using namespace std::chrono_literals;
32
33namespace ros2_canopen
34{
44class DeviceContainer : public rclcpp_components::ComponentManager
45{
46public:
55 std::weak_ptr<rclcpp::Executor> executor =
56 std::weak_ptr<rclcpp::executors::MultiThreadedExecutor>(),
57 std::string node_name = "device_container",
58 const rclcpp::NodeOptions & node_options = rclcpp::NodeOptions())
59 : rclcpp_components::ComponentManager(executor, node_name, node_options)
60 {
61 executor_ = executor;
62 this->declare_parameter<std::string>("can_interface_name", "");
63 this->declare_parameter<std::string>("master_config", "");
64 this->declare_parameter<std::string>("bus_config", "");
65 this->declare_parameter<std::string>("master_bin", "");
66 client_cbg_ = this->create_callback_group(rclcpp::CallbackGroupType::MutuallyExclusive);
67 init_driver_service_ = this->create_service<canopen_interfaces::srv::CONode>(
68 "~/init_driver",
69 std::bind(
70 &DeviceContainer::on_init_driver, this, std::placeholders::_1, std::placeholders::_2),
71 rmw_qos_profile_services_default, client_cbg_);
72
73 this->loadNode_srv_.reset();
74 this->unloadNode_srv_.reset();
76 }
77
88 void init();
89
100 void init(
101 const std::string & can_interface_name, const std::string & master_config,
102 const std::string & bus_config, const std::string & master_bin = "");
103
104 virtual void configure();
111 virtual bool load_drivers();
118 virtual bool load_master();
125 virtual bool load_manager();
126
137 virtual bool load_component(
138 const std::string package_name, const std::string driver_name, const uint16_t node_id,
139 const std::string node_name, std::vector<rclcpp::Parameter> & params,
140 const std::string node_namespace = "");
141
150 virtual void shutdown()
151 {
152 for (auto it = registered_drivers_.begin(); it != registered_drivers_.end(); ++it)
153 {
154 try
155 {
156 it->second->shutdown();
157 }
158 catch (const std::exception & e)
159 {
160 std::cerr << e.what() << '\n';
161 }
162 }
163 try
164 {
165 can_master_->shutdown();
166 }
167 catch (const std::exception & e)
168 {
169 std::cerr << e.what() << '\n';
170 }
171 }
179 virtual void on_list_nodes(
180 const std::shared_ptr<rmw_request_id_t> request_header,
181 const std::shared_ptr<ListNodes::Request> request,
182 std::shared_ptr<ListNodes::Response> response) override;
183
192 virtual std::map<uint16_t, std::shared_ptr<CanopenDriverInterface>> get_registered_drivers()
193 {
194 return registered_drivers_;
195 }
196
202 virtual size_t count_drivers() { return registered_drivers_.size(); }
203
214 std::vector<uint16_t> get_ids_of_drivers_with_type(std::string type)
215 {
216 std::vector<std::string> devices;
217 std::vector<uint16_t> ids;
218 uint32_t count = this->config_->get_all_devices(devices);
219 if (count == 0)
220 {
221 return ids;
222 }
223
224 for (auto it = devices.begin(); it != devices.end(); it++)
225 {
226 auto driver_name = config_->get_entry<std::string>(*it, "driver");
227 if (driver_name.has_value())
228 {
229 std::string name = driver_name.value();
230 if (name.compare(type) == 0)
231 {
232 auto node_id = config_->get_entry<uint16_t>(*it, "node_id");
233 ids.push_back(node_id.value());
234 }
235 }
236 }
237 return ids;
238 }
248 std::string get_driver_type(uint16_t id)
249 {
250 std::vector<std::string> devices;
251 uint32_t count = this->config_->get_all_devices(devices);
252 if (count == 0)
253 {
254 return "";
255 }
256 for (auto it = devices.begin(); it != devices.end(); it++)
257 {
258 auto node_id = config_->get_entry<uint16_t>(*it, "node_id");
259 if (node_id.has_value() && node_id.value() == id)
260 {
261 auto driver_name = config_->get_entry<std::string>(*it, "driver");
262 return driver_name.value();
263 }
264 }
265 }
266
267protected:
268 // Components
269 std::map<uint16_t, std::shared_ptr<CanopenDriverInterface>>
271 std::shared_ptr<ros2_canopen::CanopenMasterInterface>
274 std::unique_ptr<ros2_canopen::LifecycleManager> lifecycle_manager_;
275
276 // Configuration
277 std::shared_ptr<ros2_canopen::ConfigurationManager>
279 std::string dcf_txt_;
280 std::string bus_config_;
281 std::string dcf_bin_;
284
285 // ROS Objects
286 std::weak_ptr<rclcpp::Executor> executor_;
287 rclcpp::Service<canopen_interfaces::srv::CONode>::SharedPtr
289 rclcpp::CallbackGroup::SharedPtr client_cbg_;
290
296 void set_executor(const std::weak_ptr<rclcpp::Executor> executor);
297
310 bool init_driver(uint16_t node_id);
311
319 const canopen_interfaces::srv::CONode::Request::SharedPtr request,
320 canopen_interfaces::srv::CONode::Response::SharedPtr response)
321 {
322 response->success = init_driver(request->nodeid);
323 }
324
330 std::map<uint16_t, std::string> list_components();
331
338 rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_interface)
339 {
340 if (auto exec = executor_.lock())
341 {
342 RCLCPP_INFO(
343 this->get_logger(), "Added %s to executor", node_interface->get_fully_qualified_name());
344 exec->add_node(node_interface, true);
345 }
346 else
347 {
348 RCLCPP_ERROR(
349 this->get_logger(), "Failed to add component %s",
350 node_interface->get_fully_qualified_name());
351 }
352 }
353};
354
355} // namespace ros2_canopen
356#endif // LIFECYCLE_DEVICE_CONTAINER_NODE_HPP
Lifecycle Device Container for CANopen.
Definition device_container.hpp:45
virtual std::map< uint16_t, std::shared_ptr< CanopenDriverInterface > > get_registered_drivers()
Get the registered drivers object.
Definition device_container.hpp:192
std::weak_ptr< rclcpp::Executor > executor_
Pointer to ros executor instance.
Definition device_container.hpp:286
DeviceContainer(std::weak_ptr< rclcpp::Executor > executor=std::weak_ptr< rclcpp::executors::MultiThreadedExecutor >(), std::string node_name="device_container", const rclcpp::NodeOptions &node_options=rclcpp::NodeOptions())
Construct a new Lifecycle Device Container Node object.
Definition device_container.hpp:54
std::unique_ptr< ros2_canopen::LifecycleManager > lifecycle_manager_
Definition device_container.hpp:274
virtual void add_node_to_executor(rclcpp::node_interfaces::NodeBaseInterface::SharedPtr node_interface)
Add node to executor.
Definition device_container.hpp:337
virtual size_t count_drivers()
Get the number of registered drivers.
Definition device_container.hpp:202
virtual void shutdown()
Shutdown all devices.
Definition device_container.hpp:150
virtual bool load_component(const std::string package_name, const std::string driver_name, const uint16_t node_id, const std::string node_name, std::vector< rclcpp::Parameter > &params, const std::string node_namespace="")
Load a component.
bool init_driver(uint16_t node_id)
Initialises a driver.
std::string dcf_bin_
Cached value of .bin file parameter.
Definition device_container.hpp:281
std::string dcf_txt_
Cached value of .dcf file parameter.
Definition device_container.hpp:279
std::string bus_config_
Cached value of bus.yml file parameter.
Definition device_container.hpp:280
void init()
Executes the initialisation.
void on_init_driver(const canopen_interfaces::srv::CONode::Request::SharedPtr request, canopen_interfaces::srv::CONode::Response::SharedPtr response)
Callback for init driver service.
Definition device_container.hpp:318
bool lifecycle_operation_
Definition device_container.hpp:283
virtual bool load_master()
Loads master from configuration.
std::string can_interface_name_
Cached value of can interface name.
Definition device_container.hpp:282
rclcpp::CallbackGroup::SharedPtr client_cbg_
Callback group for services.
Definition device_container.hpp:289
std::shared_ptr< ros2_canopen::ConfigurationManager > config_
Pointer to configuration manager instance.
Definition device_container.hpp:278
std::map< uint16_t, std::shared_ptr< CanopenDriverInterface > > registered_drivers_
Map of drivers registered in busconfiguration. Name is key.
Definition device_container.hpp:270
virtual bool load_manager()
Loads the device manager.
std::map< uint16_t, std::string > list_components()
Returns a list of components.
rclcpp::Service< canopen_interfaces::srv::CONode >::SharedPtr init_driver_service_
Service object for init_driver service.
Definition device_container.hpp:288
std::vector< uint16_t > get_ids_of_drivers_with_type(std::string type)
Get node ids of all drivers with type.
Definition device_container.hpp:214
virtual void on_list_nodes(const std::shared_ptr< rmw_request_id_t > request_header, const std::shared_ptr< ListNodes::Request > request, std::shared_ptr< ListNodes::Response > response) override
Callback for the listing service.
virtual bool load_drivers()
Loads drivers from configuration.
void set_executor(const std::weak_ptr< rclcpp::Executor > executor)
Set the ROS executor object.
uint16_t can_master_id_
Definition device_container.hpp:273
void init(const std::string &can_interface_name, const std::string &master_config, const std::string &bus_config, const std::string &master_bin="")
Executes the initialisation.
std::string get_driver_type(uint16_t id)
Get the type of driver by node id.
Definition device_container.hpp:248
std::shared_ptr< ros2_canopen::CanopenMasterInterface > can_master_
Pointer to can master instance.
Definition device_container.hpp:272
Definition configuration_manager.hpp:28