Skip to content

Commit 36ee1ec

Browse files
authored
Merge branch 'master' into feature/add-param-for-thread-num
2 parents f2e8738 + 5ecc5b6 commit 36ee1ec

File tree

104 files changed

+3266
-1438
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+3266
-1438
lines changed

rclcpp/CHANGELOG.rst

+65
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,71 @@
22
Changelog for package rclcpp
33
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44

5+
13.1.0 (2021-10-18)
6+
-------------------
7+
* Fix dangerous std::bind capture in TimeSource implementation. (`#1768 <https://github.com/ros2/rclcpp/issues/1768>`_)
8+
* Fix dangerous std::bind capture in ParameterEventHandler implementation. (`#1770 <https://github.com/ros2/rclcpp/issues/1770>`_)
9+
* Handle sigterm, in the same way sigint is being handled. (`#1771 <https://github.com/ros2/rclcpp/issues/1771>`_)
10+
* rclcpp::Node copy constructor: make copy of node_waitables\_ member. (`#1799 <https://github.com/ros2/rclcpp/issues/1799>`_)
11+
* Extend NodeGraph to match what rcl provides. (`#1484 <https://github.com/ros2/rclcpp/issues/1484>`_)
12+
* Context::sleep_for(): replace recursion with do-while to avoid potential stack-overflow. (`#1765 <https://github.com/ros2/rclcpp/issues/1765>`_)
13+
* extend_sub_namespace(): Verify string::empty() before calling string::front(). (`#1764 <https://github.com/ros2/rclcpp/issues/1764>`_)
14+
* Deprecate the `void shared_ptr<MessageT>` subscription callback signatures. (`#1713 <https://github.com/ros2/rclcpp/issues/1713>`_)
15+
* Contributors: Abrar Rahman Protyasha, Chris Lalancette, Emerson Knapp, Geoffrey Biggs, Ivan Santiago Paunovic, Jorge Perez, Tomoya Fujita, William Woodall, Yong-Hao Zou, livanov93
16+
17+
13.0.0 (2021-08-23)
18+
-------------------
19+
* Remove can_be_nullptr assignment check for QNX case. (`#1752 <https://github.com/ros2/rclcpp/issues/1752>`_)
20+
* Update client API to be able to remove pending requests. (`#1734 <https://github.com/ros2/rclcpp/issues/1734>`_)
21+
* Fix: Allow to add a node while spinning in the StaticSingleThreadedExecutor. (`#1690 <https://github.com/ros2/rclcpp/issues/1690>`_)
22+
* Add tracing instrumentation for executor and message taking. (`#1738 <https://github.com/ros2/rclcpp/issues/1738>`_)
23+
* Fix: Reset timer trigger time before execute in StaticSingleThreadedExecutor. (`#1739 <https://github.com/ros2/rclcpp/issues/1739>`_)
24+
* Use FindPython3 and make python3 dependency explicit. (`#1745 <https://github.com/ros2/rclcpp/issues/1745>`_)
25+
* Use rosidl_get_typesupport_target(). (`#1729 <https://github.com/ros2/rclcpp/issues/1729>`_)
26+
* Fix returning invalid namespace if sub_namespace is empty. (`#1658 <https://github.com/ros2/rclcpp/issues/1658>`_)
27+
* Add free function to wait for a subscription message. (`#1705 <https://github.com/ros2/rclcpp/issues/1705>`_)
28+
* Use rcpputils/scope_exit.hpp and remove rclcpp/scope_exit.hpp. (`#1727 <https://github.com/ros2/rclcpp/issues/1727>`_)
29+
* Contributors: Ahmed Sobhy, Christophe Bedard, Ivan Santiago Paunovic, Karsten Knese, M. Hofstätter, Mauro Passerino, Shane Loretz, mauropasse
30+
31+
12.0.0 (2021-07-26)
32+
-------------------
33+
* Remove unsafe get_callback_groups API.
34+
Callers should change to using for_each_callback_group(), or
35+
store the callback groups they need internally.
36+
* Add in callback_groups_for_each.
37+
The main reason to add this method in is to make accesses to the
38+
callback_groups\_ vector thread-safe. By having a
39+
callback_groups_for_each that accepts a std::function, we can
40+
just have the callers give us the callback they are interested
41+
in, and we can take care of the locking.
42+
The rest of this fairly large PR is cleaning up all of the places
43+
that use get_callback_groups() to instead use
44+
callback_groups_for_each().
45+
* Use a different mechanism to avoid timers being scheduled multiple times by the MultiThreadedExecutor (`#1692 <https://github.com/ros2/rclcpp/issues/1692>`_)
46+
* Fix windows CI (`#1726 <https://github.com/ros2/rclcpp/issues/1726>`_)
47+
Fix bug in AnyServiceCallback introduced in `#1709 <https://github.com/ros2/rclcpp/issues/1709>`_.
48+
* Contributors: Chris Lalancette, Ivan Santiago Paunovic
49+
50+
11.2.0 (2021-07-21)
51+
-------------------
52+
* Support to defer to send a response in services. (`#1709 <https://github.com/ros2/rclcpp/issues/1709>`_)
53+
Signed-off-by: Ivan Santiago Paunovic <ivanpauno@ekumenlabs.com>
54+
* Fix documentation bug. (`#1719 <https://github.com/ros2/rclcpp/issues/1719>`_)
55+
Signed-off-by: William Woodall <william@osrfoundation.org>
56+
* Contributors: Ivan Santiago Paunovic, William Woodall
57+
58+
11.1.0 (2021-07-13)
59+
-------------------
60+
* Removed left over ``is_initialized()`` implementation (`#1711 <https://github.com/ros2/rclcpp/issues/1711>`_)
61+
Leftover from https://github.com/ros2/rclcpp/pull/1622
62+
* Fixed declare parameter methods for int and float vectors (`#1696 <https://github.com/ros2/rclcpp/issues/1696>`_)
63+
* Cleaned up implementation of the intra-process manager (`#1695 <https://github.com/ros2/rclcpp/issues/1695>`_)
64+
* Added the node name to an executor ``runtime_error`` (`#1686 <https://github.com/ros2/rclcpp/issues/1686>`_)
65+
* Fixed a typo "Attack" -> "Attach" (`#1687 <https://github.com/ros2/rclcpp/issues/1687>`_)
66+
* Removed use of std::allocator<>::rebind (`#1678 <https://github.com/ros2/rclcpp/issues/1678>`_)
67+
rebind is deprecated in c++17 and removed in c++20
68+
* Contributors: Alberto Soragna, Chen Lihui, Chris Lalancette, Petter Nilsson, Steve Macenski, William Woodall
69+
570
11.0.0 (2021-05-18)
671
-------------------
772
* Allow declare uninitialized parameters (`#1673 <https://github.com/ros2/rclcpp/issues/1673>`_)

rclcpp/CMakeLists.txt

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
cmake_minimum_required(VERSION 3.5)
1+
cmake_minimum_required(VERSION 3.12)
22

33
project(rclcpp)
44

@@ -41,7 +41,6 @@ set(${PROJECT_NAME}_SRCS
4141
src/rclcpp/clock.cpp
4242
src/rclcpp/context.cpp
4343
src/rclcpp/contexts/default_context.cpp
44-
src/rclcpp/detail/mutex_two_priorities.cpp
4544
src/rclcpp/detail/resolve_parameter_overrides.cpp
4645
src/rclcpp/detail/rmw_implementation_specific_payload.cpp
4746
src/rclcpp/detail/rmw_implementation_specific_publisher_payload.cpp
@@ -110,6 +109,8 @@ set(${PROJECT_NAME}_SRCS
110109
src/rclcpp/waitable.cpp
111110
)
112111

112+
find_package(Python3 REQUIRED COMPONENTS Interpreter)
113+
113114
# "watch" template for changes
114115
configure_file(
115116
"resource/logging.hpp.em"
@@ -123,7 +124,7 @@ set(python_code_logging
123124
string(REPLACE ";" "$<SEMICOLON>" python_code_logging "${python_code_logging}")
124125
add_custom_command(OUTPUT include/rclcpp/logging.hpp
125126
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp"
126-
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_code_logging}"
127+
COMMAND Python3::Interpreter ARGS -c "${python_code_logging}"
127128
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/logging.hpp.em.watch"
128129
COMMENT "Expanding logging.hpp.em"
129130
VERBATIM
@@ -147,7 +148,7 @@ foreach(interface_file ${interface_files})
147148
string(REPLACE ";" "$<SEMICOLON>" python_${interface_name}_traits "${python_${interface_name}_traits}")
148149
add_custom_command(OUTPUT include/rclcpp/node_interfaces/${interface_name}_traits.hpp
149150
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp/node_interfaces"
150-
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_${interface_name}_traits}"
151+
COMMAND Python3::Interpreter ARGS -c "${python_${interface_name}_traits}"
151152
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${interface_name}_traits.hpp.em.watch"
152153
COMMENT "Expanding interface_traits.hpp.em into ${interface_name}_traits.hpp"
153154
VERBATIM
@@ -167,7 +168,7 @@ foreach(interface_file ${interface_files})
167168
string(REPLACE ";" "$<SEMICOLON>" python_get_${interface_name} "${python_get_${interface_name}}")
168169
add_custom_command(OUTPUT include/rclcpp/node_interfaces/get_${interface_name}.hpp
169170
COMMAND ${CMAKE_COMMAND} -E make_directory "include/rclcpp/node_interfaces"
170-
COMMAND ${PYTHON_EXECUTABLE} ARGS -c "${python_get_${interface_name}}"
171+
COMMAND Python3::Interpreter ARGS -c "${python_get_${interface_name}}"
171172
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/get_${interface_name}.hpp.em.watch"
172173
COMMENT "Expanding get_interface.hpp.em into get_${interface_file}.hpp"
173174
VERBATIM

rclcpp/include/rclcpp/any_service_callback.hpp

+167-54
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
#ifndef RCLCPP__ANY_SERVICE_CALLBACK_HPP_
1616
#define RCLCPP__ANY_SERVICE_CALLBACK_HPP_
1717

18+
#include <variant>
1819
#include <functional>
1920
#include <memory>
2021
#include <stdexcept>
2122
#include <type_traits>
23+
#include <utility>
2224

2325
#include "rclcpp/function_traits.hpp"
2426
#include "rclcpp/visibility_control.hpp"
@@ -29,93 +31,204 @@
2931
namespace rclcpp
3032
{
3133

32-
template<typename ServiceT>
33-
class AnyServiceCallback
34+
namespace detail
3435
{
35-
private:
36-
using SharedPtrCallback = std::function<
37-
void (
38-
const std::shared_ptr<typename ServiceT::Request>,
39-
std::shared_ptr<typename ServiceT::Response>
40-
)>;
41-
using SharedPtrWithRequestHeaderCallback = std::function<
42-
void (
43-
const std::shared_ptr<rmw_request_id_t>,
44-
const std::shared_ptr<typename ServiceT::Request>,
45-
std::shared_ptr<typename ServiceT::Response>
46-
)>;
36+
template<typename T, typename = void>
37+
struct can_be_nullptr : std::false_type {};
4738

48-
SharedPtrCallback shared_ptr_callback_;
49-
SharedPtrWithRequestHeaderCallback shared_ptr_with_request_header_callback_;
39+
// Some lambdas define a comparison with nullptr,
40+
// but we see a warning that they can never be null when using it.
41+
// We also test if `T &` can be assigned to `nullptr` to avoid the issue.
42+
template<typename T>
43+
#ifdef __QNXNTO__
44+
struct can_be_nullptr<T, std::void_t<
45+
decltype(std::declval<T>() == nullptr)>>: std::true_type {};
46+
#else
47+
struct can_be_nullptr<T, std::void_t<
48+
decltype(std::declval<T>() == nullptr), decltype(std::declval<T &>() = nullptr)>>
49+
: std::true_type {};
50+
#endif
51+
} // namespace detail
5052

53+
// Forward declare
54+
template<typename ServiceT>
55+
class Service;
56+
57+
template<typename ServiceT>
58+
class AnyServiceCallback
59+
{
5160
public:
5261
AnyServiceCallback()
53-
: shared_ptr_callback_(nullptr), shared_ptr_with_request_header_callback_(nullptr)
62+
: callback_(std::monostate{})
5463
{}
5564

56-
AnyServiceCallback(const AnyServiceCallback &) = default;
57-
5865
template<
5966
typename CallbackT,
60-
typename std::enable_if<
67+
typename std::enable_if_t<!detail::can_be_nullptr<CallbackT>::value, int> = 0>
68+
void
69+
set(CallbackT && callback)
70+
{
71+
// Workaround Windows issue with std::bind
72+
if constexpr (
6173
rclcpp::function_traits::same_arguments<
6274
CallbackT,
6375
SharedPtrCallback
64-
>::value
65-
>::type * = nullptr
66-
>
67-
void set(CallbackT callback)
68-
{
69-
shared_ptr_callback_ = callback;
76+
>::value)
77+
{
78+
callback_.template emplace<SharedPtrCallback>(callback);
79+
} else if constexpr ( // NOLINT, can't satisfy both cpplint and uncrustify
80+
rclcpp::function_traits::same_arguments<
81+
CallbackT,
82+
SharedPtrWithRequestHeaderCallback
83+
>::value)
84+
{
85+
callback_.template emplace<SharedPtrWithRequestHeaderCallback>(callback);
86+
} else if constexpr ( // NOLINT
87+
rclcpp::function_traits::same_arguments<
88+
CallbackT,
89+
SharedPtrDeferResponseCallback
90+
>::value)
91+
{
92+
callback_.template emplace<SharedPtrDeferResponseCallback>(callback);
93+
} else if constexpr ( // NOLINT
94+
rclcpp::function_traits::same_arguments<
95+
CallbackT,
96+
SharedPtrDeferResponseCallbackWithServiceHandle
97+
>::value)
98+
{
99+
callback_.template emplace<SharedPtrDeferResponseCallbackWithServiceHandle>(callback);
100+
} else {
101+
// the else clause is not needed, but anyways we should only be doing this instead
102+
// of all the above workaround ...
103+
callback_ = std::forward<CallbackT>(callback);
104+
}
70105
}
71106

72107
template<
73108
typename CallbackT,
74-
typename std::enable_if<
109+
typename std::enable_if_t<detail::can_be_nullptr<CallbackT>::value, int> = 0>
110+
void
111+
set(CallbackT && callback)
112+
{
113+
if (!callback) {
114+
throw std::invalid_argument("AnyServiceCallback::set(): callback cannot be nullptr");
115+
}
116+
// Workaround Windows issue with std::bind
117+
if constexpr (
118+
rclcpp::function_traits::same_arguments<
119+
CallbackT,
120+
SharedPtrCallback
121+
>::value)
122+
{
123+
callback_.template emplace<SharedPtrCallback>(callback);
124+
} else if constexpr ( // NOLINT
75125
rclcpp::function_traits::same_arguments<
76126
CallbackT,
77127
SharedPtrWithRequestHeaderCallback
78-
>::value
79-
>::type * = nullptr
80-
>
81-
void set(CallbackT callback)
82-
{
83-
shared_ptr_with_request_header_callback_ = callback;
128+
>::value)
129+
{
130+
callback_.template emplace<SharedPtrWithRequestHeaderCallback>(callback);
131+
} else if constexpr ( // NOLINT
132+
rclcpp::function_traits::same_arguments<
133+
CallbackT,
134+
SharedPtrDeferResponseCallback
135+
>::value)
136+
{
137+
callback_.template emplace<SharedPtrDeferResponseCallback>(callback);
138+
} else if constexpr ( // NOLINT
139+
rclcpp::function_traits::same_arguments<
140+
CallbackT,
141+
SharedPtrDeferResponseCallbackWithServiceHandle
142+
>::value)
143+
{
144+
callback_.template emplace<SharedPtrDeferResponseCallbackWithServiceHandle>(callback);
145+
} else {
146+
// the else clause is not needed, but anyways we should only be doing this instead
147+
// of all the above workaround ...
148+
callback_ = std::forward<CallbackT>(callback);
149+
}
84150
}
85151

86-
void dispatch(
87-
std::shared_ptr<rmw_request_id_t> request_header,
88-
std::shared_ptr<typename ServiceT::Request> request,
89-
std::shared_ptr<typename ServiceT::Response> response)
152+
// template<typename Allocator = std::allocator<typename ServiceT::Response>>
153+
std::shared_ptr<typename ServiceT::Response>
154+
dispatch(
155+
const std::shared_ptr<rclcpp::Service<ServiceT>> & service_handle,
156+
const std::shared_ptr<rmw_request_id_t> & request_header,
157+
std::shared_ptr<typename ServiceT::Request> request)
90158
{
91159
TRACEPOINT(callback_start, static_cast<const void *>(this), false);
92-
if (shared_ptr_callback_ != nullptr) {
160+
if (std::holds_alternative<std::monostate>(callback_)) {
161+
// TODO(ivanpauno): Remove the set method, and force the users of this class
162+
// to pass a callback at construnciton.
163+
throw std::runtime_error{"unexpected request without any callback set"};
164+
}
165+
if (std::holds_alternative<SharedPtrDeferResponseCallback>(callback_)) {
166+
const auto & cb = std::get<SharedPtrDeferResponseCallback>(callback_);
167+
cb(request_header, std::move(request));
168+
return nullptr;
169+
}
170+
if (std::holds_alternative<SharedPtrDeferResponseCallbackWithServiceHandle>(callback_)) {
171+
const auto & cb = std::get<SharedPtrDeferResponseCallbackWithServiceHandle>(callback_);
172+
cb(service_handle, request_header, std::move(request));
173+
return nullptr;
174+
}
175+
// auto response = allocate_shared<typename ServiceT::Response, Allocator>();
176+
auto response = std::make_shared<typename ServiceT::Response>();
177+
if (std::holds_alternative<SharedPtrCallback>(callback_)) {
93178
(void)request_header;
94-
shared_ptr_callback_(request, response);
95-
} else if (shared_ptr_with_request_header_callback_ != nullptr) {
96-
shared_ptr_with_request_header_callback_(request_header, request, response);
97-
} else {
98-
throw std::runtime_error("unexpected request without any callback set");
179+
const auto & cb = std::get<SharedPtrCallback>(callback_);
180+
cb(std::move(request), response);
181+
} else if (std::holds_alternative<SharedPtrWithRequestHeaderCallback>(callback_)) {
182+
const auto & cb = std::get<SharedPtrWithRequestHeaderCallback>(callback_);
183+
cb(request_header, std::move(request), response);
99184
}
100185
TRACEPOINT(callback_end, static_cast<const void *>(this));
186+
return response;
101187
}
102188

103189
void register_callback_for_tracing()
104190
{
105191
#ifndef TRACETOOLS_DISABLED
106-
if (shared_ptr_callback_) {
107-
TRACEPOINT(
108-
rclcpp_callback_register,
109-
static_cast<const void *>(this),
110-
tracetools::get_symbol(shared_ptr_callback_));
111-
} else if (shared_ptr_with_request_header_callback_) {
112-
TRACEPOINT(
113-
rclcpp_callback_register,
114-
static_cast<const void *>(this),
115-
tracetools::get_symbol(shared_ptr_with_request_header_callback_));
116-
}
192+
std::visit(
193+
[this](auto && arg) {
194+
TRACEPOINT(
195+
rclcpp_callback_register,
196+
static_cast<const void *>(this),
197+
tracetools::get_symbol(arg));
198+
}, callback_);
117199
#endif // TRACETOOLS_DISABLED
118200
}
201+
202+
private:
203+
using SharedPtrCallback = std::function<
204+
void (
205+
std::shared_ptr<typename ServiceT::Request>,
206+
std::shared_ptr<typename ServiceT::Response>
207+
)>;
208+
using SharedPtrWithRequestHeaderCallback = std::function<
209+
void (
210+
std::shared_ptr<rmw_request_id_t>,
211+
std::shared_ptr<typename ServiceT::Request>,
212+
std::shared_ptr<typename ServiceT::Response>
213+
)>;
214+
using SharedPtrDeferResponseCallback = std::function<
215+
void (
216+
std::shared_ptr<rmw_request_id_t>,
217+
std::shared_ptr<typename ServiceT::Request>
218+
)>;
219+
using SharedPtrDeferResponseCallbackWithServiceHandle = std::function<
220+
void (
221+
std::shared_ptr<rclcpp::Service<ServiceT>>,
222+
std::shared_ptr<rmw_request_id_t>,
223+
std::shared_ptr<typename ServiceT::Request>
224+
)>;
225+
226+
std::variant<
227+
std::monostate,
228+
SharedPtrCallback,
229+
SharedPtrWithRequestHeaderCallback,
230+
SharedPtrDeferResponseCallback,
231+
SharedPtrDeferResponseCallbackWithServiceHandle> callback_;
119232
};
120233

121234
} // namespace rclcpp

0 commit comments

Comments
 (0)