Skip to content

Commit 01d3446

Browse files
authored
Make the action tutorials work for dashing as well. (ros2#1083)
Signed-off-by: Chris Lalancette <[email protected]>
1 parent 6ec07cb commit 01d3446

File tree

5 files changed

+283
-25
lines changed

5 files changed

+283
-25
lines changed

source/Tutorials/Actions/Writing-a-Cpp-Action-Server-Client.rst

Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -128,29 +128,49 @@ Let's focus on writing an action server that computes the Fibonacci sequence usi
128128

129129
Open up ``action_tutorials_cpp/src/fibonacci_action_server.cpp``, and put the following code in:
130130

131-
.. literalinclude:: server.cpp
132-
:language: c++
133-
:linenos:
131+
.. tabs::
132+
133+
.. group-tab:: Eloquent and newer
134+
135+
.. literalinclude:: server-eloquent-and-newer.cpp
136+
:language: c++
137+
:linenos:
138+
139+
.. group-tab:: Dashing
140+
141+
.. literalinclude:: server-dashing.cpp
142+
:language: c++
143+
:linenos:
134144

135145
The first few lines include all of the headers we need to compile.
136146

137147
Next we create a class that is a derived class of ``rclcpp::Node``:
138148

139-
.. literalinclude:: server.cpp
149+
.. literalinclude:: server-eloquent-and-newer.cpp
140150
:language: c++
141151
:lines: 14
142152

143153
The constructor for the ``FibonacciActionServer`` class initializes the node name as ``fibonacci_action_server``:
144154

145-
.. literalinclude:: server.cpp
155+
.. literalinclude:: server-eloquent-and-newer.cpp
146156
:language: c++
147157
:lines: 21-22
148158

149159
The constructor also instantiates a new action server:
150160

151-
.. literalinclude:: server.cpp
152-
:language: c++
153-
:lines: 26-31
161+
.. tabs::
162+
163+
.. group-tab:: Eloquent and newer
164+
165+
.. literalinclude:: server-eloquent-and-newer.cpp
166+
:language: c++
167+
:lines: 26-31
168+
169+
.. group-tab:: Dashing
170+
171+
.. literalinclude:: server-dashing.cpp
172+
:language: c++
173+
:lines: 26-34
154174

155175
An action server requires 6 things:
156176

@@ -166,31 +186,31 @@ Note that all of the callbacks need to return quickly, otherwise we risk starvin
166186

167187
We start with the callback for handling new goals:
168188

169-
.. literalinclude:: server.cpp
189+
.. literalinclude:: server-eloquent-and-newer.cpp
170190
:language: c++
171191
:lines: 37-44
172192

173193
This implementation just accepts all goals.
174194

175195
Next up is the callback for dealing with cancellation:
176196

177-
.. literalinclude:: server.cpp
197+
.. literalinclude:: server-eloquent-and-newer.cpp
178198
:language: c++
179199
:lines: 46-52
180200

181201
This implementation just tells the client that it accepted the cancellation.
182202

183203
The last of the callbacks accepts a new goal and starts processing it:
184204

185-
.. literalinclude:: server.cpp
205+
.. literalinclude:: server-eloquent-and-newer.cpp
186206
:language: c++
187207
:lines: 54-59
188208

189209
Since the execution is a long-running operation, we spawn off a thread to do the actual work and return from ``handle_accepted`` quickly.
190210

191211
All further processing and updates are done in the ``execute`` method in the new thread:
192212

193-
.. literalinclude:: server.cpp
213+
.. literalinclude:: server-eloquent-and-newer.cpp
194214
:language: c++
195215
:lines: 61-95
196216

@@ -255,29 +275,49 @@ Source the workspace we just built (``action_ws``), and try to run the action se
255275

256276
Open up ``action_tutorials_cpp/src/fibonacci_action_client.cpp``, and put the following code in:
257277

258-
.. literalinclude:: client.cpp
259-
:language: c++
260-
:linenos:
278+
.. tabs::
279+
280+
.. group-tab:: Eloquent and newer
281+
282+
.. literalinclude:: client-eloquent-and-newer.cpp
283+
:language: c++
284+
:linenos:
285+
286+
.. group-tab:: Dashing
287+
288+
.. literalinclude:: client-dashing.cpp
289+
:language: c++
290+
:linenos:
261291

262292
The first few lines include all of the headers we need to compile.
263293

264294
Next we create a class that is a derived class of ``rclcpp::Node``:
265295

266-
.. literalinclude:: client.cpp
296+
.. literalinclude:: client-eloquent-and-newer.cpp
267297
:language: c++
268298
:lines: 15
269299

270300
The constructor for the ``FibonacciActionClient`` class initializes the node name as ``fibonacci_action_client``:
271301

272-
.. literalinclude:: client.cpp
302+
.. literalinclude:: client-eloquent-and-newer.cpp
273303
:language: c++
274304
:lines: 20-22
275305

276306
The constructor also instantiates a new action client:
277307

278-
.. literalinclude:: client.cpp
279-
:language: c++
280-
:lines: 24-26
308+
.. tabs::
309+
310+
.. group-tab:: Eloquent and newer
311+
312+
.. literalinclude:: client-eloquent-and-newer.cpp
313+
:language: c++
314+
:lines: 24-26
315+
316+
.. group-tab:: Dashing
317+
318+
.. literalinclude:: client-dashing.cpp
319+
:language: c++
320+
:lines: 24-29
281321

282322
An action client requires 3 things:
283323

@@ -287,13 +327,13 @@ An action client requires 3 things:
287327

288328
We also instantiate a ROS timer that will kick off the one and only call to ``send_goal``:
289329

290-
.. literalinclude:: client.cpp
330+
.. literalinclude:: client-eloquent-and-newer.cpp
291331
:language: c++
292332
:lines: 27-30
293333

294334
When the timer expires, it will call ``send_goal``:
295335

296-
.. literalinclude:: client.cpp
336+
.. literalinclude:: client-eloquent-and-newer.cpp
297337
:language: c++
298338
:lines: 32-57
299339

@@ -308,21 +348,21 @@ This function does the following:
308348
When the server receives and accepts the goal, it will send a response to the client.
309349
That response is handled by ``goal_response_callback``:
310350

311-
.. literalinclude:: client.cpp
351+
.. literalinclude:: client-eloquent-and-newer.cpp
312352
:language: c++
313353
:lines: 62-71
314354

315355
Assuming the goal was accepted by the server, it will start processing.
316356
Any feedback to the client will be handled by the ``feedback_callback``:
317357

318-
.. literalinclude:: client.cpp
358+
.. literalinclude:: client-eloquent-and-newer.cpp
319359
:language: c++
320360
:lines: 72-83
321361

322362
When the server is finished processing, it will return a result to the client.
323363
The result is handled by the ``result_callback``:
324364

325-
.. literalinclude:: client.cpp
365+
.. literalinclude:: client-eloquent-and-newer.cpp
326366
:language: c++
327367
:lines: 84-107
328368

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#include <functional>
2+
#include <future>
3+
#include <memory>
4+
#include <string>
5+
#include <sstream>
6+
7+
#include "action_tutorials_interfaces/action/fibonacci.hpp"
8+
9+
#include "rclcpp/rclcpp.hpp"
10+
#include "rclcpp_action/rclcpp_action.hpp"
11+
#include "rclcpp_components/register_node_macro.hpp"
12+
13+
namespace action_tutorials_cpp
14+
{
15+
class FibonacciActionClient : public rclcpp::Node
16+
{
17+
public:
18+
using Fibonacci = action_tutorials_interfaces::action::Fibonacci;
19+
using GoalHandleFibonacci = rclcpp_action::ClientGoalHandle<Fibonacci>;
20+
21+
explicit FibonacciActionClient(const rclcpp::NodeOptions & options)
22+
: Node("fibonacci_action_client", options)
23+
{
24+
this->client_ptr_ = rclcpp_action::create_client<Fibonacci>(
25+
this->get_node_base_interface(),
26+
this->get_node_graph_interface(),
27+
this->get_node_logging_interface(),
28+
this->get_node_waitables_interface(),
29+
"fibonacci");
30+
31+
this->timer_ = this->create_wall_timer(
32+
std::chrono::milliseconds(500),
33+
std::bind(&FibonacciActionClient::send_goal, this));
34+
}
35+
36+
void send_goal()
37+
{
38+
using namespace std::placeholders;
39+
40+
this->timer_->cancel();
41+
42+
if (!this->client_ptr_->wait_for_action_server()) {
43+
RCLCPP_ERROR(this->get_logger(), "Action server not available after waiting");
44+
rclcpp::shutdown();
45+
}
46+
47+
auto goal_msg = Fibonacci::Goal();
48+
goal_msg.order = 10;
49+
50+
RCLCPP_INFO(this->get_logger(), "Sending goal");
51+
52+
auto send_goal_options = rclcpp_action::Client<Fibonacci>::SendGoalOptions();
53+
send_goal_options.goal_response_callback =
54+
std::bind(&FibonacciActionClient::goal_response_callback, this, _1);
55+
send_goal_options.feedback_callback =
56+
std::bind(&FibonacciActionClient::feedback_callback, this, _1, _2);
57+
send_goal_options.result_callback =
58+
std::bind(&FibonacciActionClient::result_callback, this, _1);
59+
this->client_ptr_->async_send_goal(goal_msg, send_goal_options);
60+
}
61+
62+
private:
63+
rclcpp_action::Client<Fibonacci>::SharedPtr client_ptr_;
64+
rclcpp::TimerBase::SharedPtr timer_;
65+
66+
void goal_response_callback(std::shared_future<GoalHandleFibonacci::SharedPtr> future)
67+
{
68+
auto goal_handle = future.get();
69+
if (!goal_handle) {
70+
RCLCPP_ERROR(this->get_logger(), "Goal was rejected by server");
71+
} else {
72+
RCLCPP_INFO(this->get_logger(), "Goal accepted by server, waiting for result");
73+
}
74+
}
75+
76+
void feedback_callback(
77+
GoalHandleFibonacci::SharedPtr,
78+
const std::shared_ptr<const Fibonacci::Feedback> feedback)
79+
{
80+
std::stringstream ss;
81+
ss << "Next number in sequence received: ";
82+
for (auto number : feedback->partial_sequence) {
83+
ss << number << " ";
84+
}
85+
RCLCPP_INFO(this->get_logger(), ss.str().c_str());
86+
}
87+
88+
void result_callback(const GoalHandleFibonacci::WrappedResult & result)
89+
{
90+
switch (result.code) {
91+
case rclcpp_action::ResultCode::SUCCEEDED:
92+
break;
93+
case rclcpp_action::ResultCode::ABORTED:
94+
RCLCPP_ERROR(this->get_logger(), "Goal was aborted");
95+
return;
96+
case rclcpp_action::ResultCode::CANCELED:
97+
RCLCPP_ERROR(this->get_logger(), "Goal was canceled");
98+
return;
99+
default:
100+
RCLCPP_ERROR(this->get_logger(), "Unknown result code");
101+
return;
102+
}
103+
std::stringstream ss;
104+
ss << "Result received: ";
105+
for (auto number : result.result->sequence) {
106+
ss << number << " ";
107+
}
108+
RCLCPP_INFO(this->get_logger(), ss.str().c_str());
109+
rclcpp::shutdown();
110+
}
111+
}; // class FibonacciActionClient
112+
113+
} // namespace action_tutorials_cpp
114+
115+
RCLCPP_COMPONENTS_REGISTER_NODE(action_tutorials_cpp::FibonacciActionClient)

0 commit comments

Comments
 (0)