15 #ifndef NAV2_ROUTE__PLUGINS__ROUTE_OPERATION_CLIENT_HPP_
16 #define NAV2_ROUTE__PLUGINS__ROUTE_OPERATION_CLIENT_HPP_
22 #include "rclcpp/rclcpp.hpp"
23 #include "rclcpp_lifecycle/lifecycle_node.hpp"
24 #include "nav2_route/interfaces/route_operation.hpp"
25 #include "nav2_core/route_exceptions.hpp"
26 #include "nav2_util/node_utils.hpp"
27 #include "nav2_util/service_client.hpp"
28 #include "std_srvs/srv/trigger.hpp"
33 using namespace std::chrono_literals;
61 template<
typename SrvT>
81 const rclcpp_lifecycle::LifecycleNode::SharedPtr ,
82 const std::string & ) {}
88 std::shared_ptr<typename SrvT::Request>,
const Metadata * ) {}
101 const rclcpp_lifecycle::LifecycleNode::SharedPtr node,
102 std::shared_ptr<nav2_costmap_2d::CostmapSubscriber>,
103 const std::string & name)
final
105 RCLCPP_INFO(node->get_logger(),
"Configuring route operation client: %s.", name.c_str());
107 logger_ = node->get_logger();
109 callback_group_ = node->create_callback_group(
110 rclcpp::CallbackGroupType::MutuallyExclusive,
112 callback_group_executor_.add_callback_group(callback_group_, node->get_node_base_interface());
114 nav2_util::declare_parameter_if_not_declared(
115 node, getName() +
".service_name", rclcpp::ParameterValue(
""));
116 main_srv_name_ = node->get_parameter(getName() +
".service_name").as_string();
118 configureEvent(node, name);
123 if (!main_srv_name_.empty()) {
124 main_client_ = node->create_client<SrvT>(
125 main_srv_name_, rclcpp::SystemDefaultsQoS().get_rmw_qos_profile(), callback_group_);
145 const geometry_msgs::msg::PoseStamped & ,
148 auto req = std::make_shared<typename SrvT::Request>();
149 std::shared_ptr<typename SrvT::Response> response;
150 populateRequest(req, mdata);
152 std::string srv_name;
153 srv_name = mdata->getValue<std::string>(
"service_name", srv_name);
154 if (srv_name.empty() && !main_client_) {
156 "Route operation service (" + getName() +
") needs 'server_name' "
157 "set in the param file or in the operation's metadata!");
161 if (srv_name.empty()) {
162 srv_name = main_srv_name_;
163 response = callService(main_client_, req);
165 auto node = node_.lock();
168 "Route operation service (" + getName() +
") failed to lock node.");
170 auto client = node->create_client<SrvT>(
171 srv_name, rclcpp::SystemDefaultsQoS().get_rmw_qos_profile(), callback_group_);
172 response = callService(client, req);
174 }
catch (
const std::exception & e) {
176 "Route operation service (" + getName() +
") failed to call service: " +
177 srv_name +
" at Node " + std::to_string(node_achieved->nodeid));
182 "%s: Processed operation at Node %i with service %s.",
183 name_.c_str(), node_achieved->nodeid, srv_name.c_str());
184 return processResponse(response);
187 std::shared_ptr<typename SrvT::Response> callService(
188 typename rclcpp::Client<SrvT>::SharedPtr client,
189 std::shared_ptr<typename SrvT::Request> req,
190 const std::chrono::nanoseconds timeout = std::chrono::nanoseconds(500ms))
192 auto node = node_.lock();
193 if (!client->wait_for_service(1s)) {
195 "Route operation service " +
196 std::string(client->get_service_name()) +
"is not available!");
199 auto result = client->async_send_request(req);
200 if (callback_group_executor_.spin_until_future_complete(result, timeout) !=
201 rclcpp::FutureReturnCode::SUCCESS)
204 "Route operation service " +
205 std::string(client->get_service_name()) +
"failed to call!");
215 std::string
getName()
override {
return name_;}
222 RouteOperationType
processType() final {
return RouteOperationType::ON_GRAPH;}
224 std::string name_, main_srv_name_;
225 std::atomic_bool reroute_;
226 rclcpp::Logger logger_{rclcpp::get_logger(
"RouteOperationClient")};
227 typename rclcpp::Client<SrvT>::SharedPtr main_client_;
228 rclcpp_lifecycle::LifecycleNode::WeakPtr node_;
229 rclcpp::CallbackGroup::SharedPtr callback_group_;
230 rclcpp::executors::SingleThreadedExecutor callback_group_executor_;
A route operation base class to trigger a service event at a node or edge. This is meant to be named ...
virtual OperationResult processResponse(std::shared_ptr< typename SrvT::Response >)
Process response from service to populate a result, if necessary.
virtual void populateRequest(std::shared_ptr< typename SrvT::Request >, const Metadata *)
Populate request with details for service, if necessary.
virtual void configureEvent(const rclcpp_lifecycle::LifecycleNode::SharedPtr, const std::string &)
Configure client with any necessary parameters, etc. May change or reset main_srv_name_ variable to c...
RouteOperationType processType() final
Indication that the adjust speed limit route operation is performed on all state changes.
virtual ~RouteOperationClient()=default
destructor
RouteOperationClient()=default
Constructor.
std::string getName() override
Get name of the plugin for parameter scope mapping.
void configure(const rclcpp_lifecycle::LifecycleNode::SharedPtr node, std::shared_ptr< nav2_costmap_2d::CostmapSubscriber >, const std::string &name) final
Configure.
OperationResult perform(NodePtr node_achieved, EdgePtr, EdgePtr, const Route &, const geometry_msgs::msg::PoseStamped &, const Metadata *mdata) final
The main operation to call a service of arbitrary type and arbitrary name.
A plugin interface to perform an operation while tracking the route such as triggered from the graph ...
An object representing edges between nodes.
An object to store the nodes in the graph file.
a struct to hold return from an operation
An ordered set of nodes and edges corresponding to the planned route.