Allow use of C message types
Nobody has claimed this yet.
- Dominant language
- C++
- Stars
- 805
- Forks
- 564
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 27
Description
Feature request
Feature description
Some interfaces with rcl internals, or other C-based implementations, are more easily accomplished by sticking with C message types - given that there is no universal conversion from C++-generated types to C-generated types, they are totally separate.
In one example case, rcl implements a service and provides a callback for it, but it is desirable to let rclcpp handle the executor/waitsets to take advantage of its threading/execution infrastructure. In that case, the RCL callback handler needs C message types to operate on.
I'll show the following example for Services, but there are similar difficulties using Publishers, etc that we could cover as part of this investigation.
The following
#include "std_srvs/srv/empty.h"
// ...
rclcpp::Service<std_srvs__srv__Empty> service;
fail to compile, for a couple of reasons:
rosidl_generator_cdoes not generate a toplevel entitystd_srvs__srv__Empty, instead just the_Requestand_Responsestructs - as well as a typesupport getter function for the Service type- Service looks for members as
::Request, etc.
Implementation considerations
Workaround example I am using for a C-based service (some error checking omitted for brevity)
// Helper wrapper for rclcpp::Service to access ::Request and ::Response types for allocation.
struct GetTypeDescriptionC
{
using Request = type_description_interfaces__srv__GetTypeDescription_Request;
using Response = type_description_interfaces__srv__GetTypeDescription_Response;
using Event = type_description_interfaces__srv__GetTypeDescription_Event;
};
} // namespace
// Helper function for C typesupport.
namespace rosidl_typesupport_cpp
{
template<>
rosidl_service_type_support_t const *
get_service_type_support_handle<GetTypeDescriptionC>()
{
return ROSIDL_GET_SRV_TYPE_SUPPORT(type_description_interfaces, srv, GetTypeDescription);
}
} // namespace rosidl_typesupport_cpp
void business(std::shared_ptr<rclcpp::Node> node)
{
auto rcl_node = node->get_node_base_interface()->get_rcl_node_handle();
rcl_node_type_description_service_init(rcl_node);
rcl_service_t * rcl_srv = nullptr;
rcl_node_get_type_description_service(rcl_node, &rcl_srv);
rclcpp::AnyServiceCallback<GetTypeDescriptionC> cb;
cb.set(
[node](
std::shared_ptr<rmw_request_id_t> header,
std::shared_ptr<GetTypeDescriptionC::Request> request,
std::shared_ptr<GetTypeDescriptionC::Response> response
) {
rcl_node_type_description_service_handle_request(
node->get_node_base_interface()->get_rcl_node_handle(),
header.get(),
request.get(),
response.get());
});
auto type_description_srv_ = std::make_shared<Service<GetTypeDescriptionC>>(
node->get_node_base_interface()->get_shared_rcl_node_handle(),
rcl_srv,
cb);
node->get_node_services_interface()->add_service(
std::dynamic_pointer_cast<ServiceBase>(type_description_srv_),
nullptr);
}
Maybe we want to call that "acceptable overhead" to create a C-based service? But I personally think that there could be a better way.
A followup note on this, there is no way to let rcl do its own take, because every code path in the default Executor does a take_request before ever invoking the user callback.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing rclcpp::Service, AnyServiceCallback, and the default Executor paths that call take_request before callbacks. Compare the C service Request, Response, and Event types with the ::Request and ::Response expectations described in the issue. Done means C-generated message types can be used through the relevant service and publisher APIs without the helper wrapper workaround, with the related execution paths covered.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100