Skip to content

Commit 7057ef3

Browse files
authored
Merge pull request #1 from AIResearchLab/nav-runner
added waypoint runner and modified action_runner
2 parents 46a57be + 4d26f8c commit 7057ef3

14 files changed

Lines changed: 342 additions & 98 deletions

File tree

Lines changed: 129 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
#pragma once
22

3-
#include <capabilities2_runner/runner_base.hpp>
3+
#include <thread>
4+
5+
#include <rclcpp/rclcpp.hpp>
46
#include <rclcpp_action/rclcpp_action.hpp>
7+
#include <action_msgs/srv/cancel_goal.hpp>
8+
9+
#include <capabilities2_runner/runner_base.hpp>
510

611
namespace capabilities2_runner
712
{
@@ -10,71 +15,136 @@ namespace capabilities2_runner
1015
* @brief action runner base class
1116
*
1217
* Create an action client to run an action based capability
13-
*
1418
*/
1519
template <typename ActionT>
1620
class ActionRunner : public RunnerBase
1721
{
1822
public:
19-
ActionRunner() : RunnerBase()
20-
{
21-
}
22-
23-
// helpers
24-
// init action base members
25-
void init_action(rclcpp::Node::SharedPtr node, const runner_opts& opts, const std::string& action_type)
26-
{
27-
// store node pointer and opts
28-
init_base(node, opts);
29-
30-
// create an action client
31-
action_client_ = rclcpp_action::create_client<ActionT>(node_, get_action_name_by_type(action_type));
32-
33-
// wait for action server
34-
RCLCPP_INFO(node_->get_logger(), "%s waiting for action: %s", run_config_.interface.c_str(),
35-
get_action_name_by_type(action_type).c_str());
36-
37-
if (!action_client_->wait_for_action_server())
38-
{
39-
RCLCPP_ERROR(node_->get_logger(), "%s failed to connect to action server", run_config_.interface.c_str());
40-
throw runner_exception("failed to connect to action server");
41-
}
42-
}
43-
44-
// find resource name by action type
45-
std::string get_action_name_by_type(const std::string& action_type)
46-
{
47-
for (const auto& resource : run_config_.resources)
48-
{
49-
if (resource.resource_type == "action")
50-
{
51-
if (resource.msg_type == action_type)
52-
{
53-
return resource.name;
54-
}
55-
}
56-
}
57-
58-
throw runner_exception("no action resource found: " + action_type);
59-
}
60-
61-
// get first action resource
62-
std::string get_first_action_name()
63-
{
64-
for (const auto& resource : run_config_.resources)
65-
{
66-
if (resource.resource_type == "action")
67-
{
68-
return resource.name;
69-
}
70-
}
71-
72-
throw runner_exception("no action resources found for interface: " + run_config_.interface);
73-
}
23+
24+
/**
25+
* @brief Constructor which needs to be empty due to plugin semantics
26+
*/
27+
ActionRunner() : RunnerBase()
28+
{}
29+
30+
/**
31+
* @brief Initializer function for initializing the action runner in place of constructor due to plugin semantics
32+
*
33+
* @param node shared pointer to the capabilities node. Allows to use ros node related functionalities
34+
* @param run_config runner configuration loaded from the yaml file
35+
* @param action_name action name used in the yaml file, used to load specific configuration from the run_config
36+
* @param on_started function pointer to trigger at the start of the action client in the runner
37+
* @param on_terminated function pointer to trigger at the termination of the action client in the runner
38+
*/
39+
virtual void init_action(rclcpp::Node::SharedPtr node, const runner_opts& run_config, const std::string& action_name,
40+
std::function<void(const std::string&)> on_started = nullptr,
41+
std::function<void(const std::string&)> on_terminated = nullptr)
42+
{
43+
// initialize the runner base by storing node pointer and run config
44+
init_base(node, run_config);
45+
46+
// initialize the used for message timestamps
47+
clock_ = node_->get_clock();
48+
49+
// create an action client
50+
action_client_ = rclcpp_action::create_client<ActionT>(node_, action_name);
51+
52+
// wait for action server
53+
RCLCPP_INFO(node_->get_logger(), "%s waiting for action: %s", run_config_.interface.c_str(), action_name.c_str());
54+
55+
if (!action_client_->wait_for_action_server(std::chrono::seconds(3)))
56+
{
57+
RCLCPP_ERROR(node_->get_logger(), "%s failed to connect to action server", run_config_.interface.c_str());
58+
throw runner_exception("failed to connect to action server");
59+
}
60+
61+
// goal response callback
62+
send_goal_options_.goal_response_callback =
63+
[this, on_started, on_terminated](const typename rclcpp_action::ClientGoalHandle<ActionT>::SharedPtr& goal_handle)
64+
{
65+
// store goal handle to be used with stop funtion
66+
goal_handle_ = goal_handle;
67+
};
68+
69+
// result callback
70+
send_goal_options_.result_callback =
71+
[this, on_started, on_terminated](const typename rclcpp_action::ClientGoalHandle<ActionT>::WrappedResult& wrapped_result)
72+
{
73+
if (wrapped_result.code == rclcpp_action::ResultCode::SUCCEEDED)
74+
{
75+
// publish event
76+
if (on_started)
77+
{
78+
on_started(run_config_.interface);
79+
}
80+
} else
81+
{
82+
// send terminated event
83+
if (on_terminated)
84+
{
85+
on_terminated(run_config_.interface);
86+
}
87+
}
88+
};
89+
}
90+
91+
virtual void stop(std::function<void(const std::string&)> on_stopped = nullptr) override
92+
{
93+
// if the node pointer is empty then throw an error
94+
// this means that the runner was not started and is being used out of order
95+
96+
if (!node_) throw runner_exception("cannot stop runner that was not started");
97+
98+
// throw an error if the action client is null
99+
// this can happen if the runner is not able to find the action resource
100+
101+
if (!action_client_) throw runner_exception("cannot stop runner action that was not started");
102+
103+
// stop runner using action client
104+
if (goal_handle_)
105+
{
106+
try
107+
{
108+
auto cancel_future = action_client_->async_cancel_goal(
109+
goal_handle_,
110+
[this, on_stopped](action_msgs::srv::CancelGoal_Response::SharedPtr response)
111+
{
112+
if (response->return_code != action_msgs::srv::CancelGoal_Response::ERROR_NONE)
113+
{
114+
// throw runner_exception("failed to cancel runner");
115+
}
116+
117+
// publish event
118+
if (on_stopped)
119+
{
120+
on_stopped(run_config_.interface);
121+
}
122+
}
123+
);
124+
125+
// wait for action to be stopped. hold the thread for 2 seconds to help keep callbacks in scope
126+
rclcpp::spin_until_future_complete(node_, cancel_future, std::chrono::seconds(2));
127+
}
128+
catch (const rclcpp_action::exceptions::UnknownGoalHandleError& e)
129+
{
130+
throw runner_exception(e.what());
131+
}
132+
}
133+
}
74134

75135
protected:
76-
// action client
77-
std::shared_ptr<rclcpp_action::Client<ActionT>> action_client_;
136+
137+
/**< action client */
138+
std::shared_ptr<rclcpp_action::Client<ActionT>> action_client_;
139+
140+
/**< rclcpp clock to get time */
141+
rclcpp::Clock::SharedPtr clock_;
142+
143+
/**< Send Goal Option struct to link result_callback, feedback_callback and goal_response_callback with action client */
144+
typename rclcpp_action::Client<ActionT>::SendGoalOptions send_goal_options_;
145+
146+
/**< goal handle parameter to capture goal response from goal_response_callback */
147+
typename rclcpp_action::ClientGoalHandle<ActionT>::SharedPtr goal_handle_;
78148
};
79149

80150
} // namespace capabilities2_runner

capabilities2_runner/include/capabilities2_runner/launch_runner.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ namespace capabilities2_runner
1414
* @brief launch runner base class
1515
*
1616
* Create a launch file runner to run a launch file based capability
17-
*
1817
*/
1918
class LaunchRunner : public ActionRunner<capabilities2_msgs::action::Launch>
2019
{
@@ -23,12 +22,12 @@ class LaunchRunner : public ActionRunner<capabilities2_msgs::action::Launch>
2322
{
2423
}
2524

26-
virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& opts,
25+
virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& run_config,
2726
std::function<void(const std::string&)> on_started = nullptr,
2827
std::function<void(const std::string&)> on_terminated = nullptr) override
2928
{
30-
// store node pointer and opts
31-
init_base(node, opts);
29+
// store node pointer and run_config
30+
init_base(node, run_config);
3231

3332
// create an action client
3433
action_client_ = rclcpp_action::create_client<capabilities2_msgs::action::Launch>(node_, "/capabilities_launch_"
@@ -76,6 +75,7 @@ class LaunchRunner : public ActionRunner<capabilities2_msgs::action::Launch>
7675
// store goal handle
7776
goal_handle_ = goal_handle;
7877
};
78+
7979
// result callback
8080
send_goal_options.result_callback =
8181
[this, on_started, on_terminated](

capabilities2_runner/include/capabilities2_runner/runner_base.hpp

Lines changed: 40 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ struct resource
4141
/**
4242
* @brief runner options
4343
*
44-
* Contains the options required to start and maintain a consistent runner
44+
* Contains the options required to start and maintain a consistent runner. normally
45+
* loaded from the yaml file
4546
*
4647
*/
4748
struct runner_opts
@@ -71,59 +72,86 @@ class RunnerBase
7172
/**
7273
* @brief start the runner
7374
*
74-
* @param node
75-
* @param opts
76-
* @param on_started
77-
* @param on_terminated
75+
* @param node shared pointer to the capabilities node. Allows to use ros node related functionalities
76+
* @param run_config runner configuration loaded from the yaml file
77+
* @param on_started pointer to function to execute on starting the runner
78+
* @param on_terminated pointer to function to execute on terminating the runner
7879
*/
79-
virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& opts,
80+
virtual void start(rclcpp::Node::SharedPtr node, const runner_opts& run_config,
8081
std::function<void(const std::string&)> on_started = nullptr,
8182
std::function<void(const std::string&)> on_terminated = nullptr) = 0;
8283

8384
/**
8485
* @brief stop the runner
8586
*
86-
* @param on_stopped
87+
* @param on_stopped pointer to function to execute on stopping the runner
8788
*/
8889
virtual void stop(std::function<void(const std::string&)> on_stopped = nullptr) = 0;
8990

90-
// helpers
91-
// init base members
92-
void init_base(rclcpp::Node::SharedPtr node, const runner_opts& opts)
91+
92+
/**
93+
* @brief Initializer function for initializing the base runner in place of constructor due to plugin semantics
94+
*
95+
* @param node shared pointer to the capabilities node. Allows to use ros node related functionalities
96+
* @param run_config runner configuration loaded from the yaml file
97+
*/
98+
void init_base(rclcpp::Node::SharedPtr node, const runner_opts& run_config)
9399
{
94100
// store node pointer and opts
95101
node_ = node;
96-
run_config_ = opts;
102+
run_config_ = run_config;
97103
}
98104

105+
/**
106+
* @brief get the package name to which the runner belong to.
107+
*/
99108
const std::string get_package_name()
100109
{
101110
return run_config_.interface.substr(0, run_config_.interface.find("/"));
102111
}
103112

104-
// getters
113+
/**
114+
* @brief get the interface of the runner.
115+
*/
105116
const std::string& get_interface() const
106117
{
107118
return run_config_.interface;
108119
}
109120

121+
/**
122+
* @brief get the provider of the runner.
123+
*/
110124
const std::string& get_provider() const
111125
{
112126
return run_config_.provider;
113127
}
114128

129+
/**
130+
* @brief get the starter of the runner.
131+
*/
115132
const std::string& get_started_by() const
116133
{
117134
return run_config_.started_by;
118135
}
119136

137+
/**
138+
* @brief get the pid of the runner.
139+
*/
120140
const std::string& get_pid() const
121141
{
122142
return run_config_.pid;
123143
}
124144

125145
protected:
146+
147+
/**
148+
* @param node shared pointer to the capabilities node. Allows to use ros node related functionalities
149+
*/
126150
rclcpp::Node::SharedPtr node_;
151+
152+
/**
153+
* @param node runner configuration
154+
*/
127155
runner_opts run_config_;
128156
};
129157

capabilities2_runner/readme.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@ provide runners for common capabilities like nav2, moveit2, etc. Plugins extend
88
- `action runner` - runner for capabilities that are implemented as actions. This is also a base class for as most runners will be actions.
99
- `launch runner` - runner for capabilities that are implemented as launch files.
1010

11+
12+
## Inheritance Diagram
13+
14+
![inheritance diagram](/images/inheritance-diagram.png)
15+
1116
## creating a new runner
1217

1318
New runners can be created to perform new capabilities. The runner can be specified in a capability provider as the `runner` tag:

0 commit comments

Comments
 (0)