ROS2ServiceBase.h 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #pragma once
  9. #include <AzCore/std/containers/unordered_set.h>
  10. #include <AzCore/std/optional.h>
  11. #include <Interfaces/IROS2HandlerBase.h>
  12. #include <Utils/RegistryUtils.h>
  13. #include <rclcpp/rclcpp.hpp>
  14. #include <rclcpp/service.hpp>
  15. #include <simulation_interfaces/msg/simulator_features.hpp>
  16. namespace ROS2SimulationInterfaces
  17. {
  18. //! Base for each ROS 2 service handler, forces declaration of features provided by the handler
  19. //! combined information along all ROS 2 handlers gives information about simulation features
  20. //! @see https://github.com/ros-simulation/simulation_interfaces/blob/main/msg/SimulatorFeatures.msg
  21. using SimulationFeatures = simulation_interfaces::msg::SimulatorFeatures;
  22. template<typename RosServiceType>
  23. class ROS2ServiceBase : public virtual IROS2HandlerBase
  24. {
  25. public:
  26. using Request = typename RosServiceType::Request;
  27. using Response = typename RosServiceType::Response;
  28. using ServiceHandle = std::shared_ptr<rclcpp::Service<RosServiceType>>;
  29. virtual ~ROS2ServiceBase() = default;
  30. void Initialize(rclcpp::Node::SharedPtr& node) override
  31. {
  32. CreateService(node);
  33. }
  34. void SendResponse(Response response)
  35. {
  36. AZ_Assert(m_serviceHandle, "Failed to get m_serviceHandle");
  37. AZ_Assert(m_lastRequestHeader, "Failed to get last request header ptr");
  38. m_serviceHandle->send_response(*m_lastRequestHeader, response);
  39. }
  40. protected:
  41. //! This function is called when a service request is received.
  42. virtual AZStd::optional<Response> HandleServiceRequest(const std::shared_ptr<rmw_request_id_t> header, const Request& request) = 0;
  43. //! return features id defined by the handler, ids must follow the definition inside standard:
  44. //! @see https://github.com/ros-simulation/simulation_interfaces/blob/main/msg/SimulatorFeatures.msg
  45. AZStd::unordered_set<AZ::u8> GetProvidedFeatures() override
  46. {
  47. return {};
  48. };
  49. private:
  50. void CreateService(rclcpp::Node::SharedPtr& node)
  51. {
  52. // get the service name from the type name
  53. AZStd::string serviceName = RegistryUtilities::GetName(GetTypeName());
  54. if (serviceName.empty())
  55. {
  56. // if the service name is empty, use the default name
  57. serviceName = GetDefaultName();
  58. }
  59. const std::string serviceNameStr{ serviceName.c_str(), serviceName.size() };
  60. m_serviceHandle = node->create_service<RosServiceType>(
  61. serviceNameStr,
  62. [this](
  63. const ServiceHandle service_handle,
  64. const std::shared_ptr<rmw_request_id_t> header,
  65. const std::shared_ptr<Request> request)
  66. {
  67. m_lastRequestHeader = header;
  68. auto response = HandleServiceRequest(header, *request);
  69. // if no response passed it means, that handleServiceRequest will send response in defined callback after time consuming
  70. // task, header needs to be cached
  71. if (response.has_value())
  72. {
  73. service_handle->send_response(*header, response.value());
  74. }
  75. });
  76. }
  77. std::shared_ptr<rmw_request_id_t> m_lastRequestHeader = nullptr;
  78. ServiceHandle m_serviceHandle;
  79. };
  80. } // namespace ROS2SimulationInterfaces