-
Notifications
You must be signed in to change notification settings - Fork 72
EBus and ROS2 support for sensor configurations #894
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/rfc_96_split_ros2
Are you sure you want to change the base?
Changes from all commits
f4c64d1
5a2073b
e22b62f
3c4f79b
dcd0adb
3435dcf
1977710
0594cf2
cf70147
58eef9f
0b6463e
8e5016b
43dd331
3d8170a
1cdb174
46c2726
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,35 @@ | ||||||||||||||||
/* | ||||||||||||||||
* Copyright (c) Contributors to the Open 3D Engine Project. | ||||||||||||||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution. | ||||||||||||||||
* | ||||||||||||||||
* SPDX-License-Identifier: Apache-2.0 OR MIT | ||||||||||||||||
* | ||||||||||||||||
*/ | ||||||||||||||||
|
||||||||||||||||
#pragma once | ||||||||||||||||
|
||||||||||||||||
#include <AzCore/Component/ComponentBus.h> | ||||||||||||||||
#include <AzCore/Component/EntityId.h> | ||||||||||||||||
|
||||||||||||||||
namespace ROS2 { | ||||||||||||||||
template<typename Configuration> | ||||||||||||||||
Comment on lines
+14
to
+15
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider:
Suggested change
|
||||||||||||||||
class ConfigurationRequests : public AZ::ComponentBus | ||||||||||||||||
{ | ||||||||||||||||
public: | ||||||||||||||||
using BusIdType = AZ::EntityId; | ||||||||||||||||
static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById; | ||||||||||||||||
static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple; | ||||||||||||||||
|
||||||||||||||||
//! Returns the current configuration of the component. | ||||||||||||||||
virtual const Configuration GetConfiguration() const = 0; | ||||||||||||||||
|
||||||||||||||||
//! Sets the configuration of the component. | ||||||||||||||||
//! Each component should handle the configuration change without fully reinitializing the ROS2 publisher. | ||||||||||||||||
//! This will allow to change the configuration of the component at runtime. | ||||||||||||||||
//! @param configuration The new configuration to set. | ||||||||||||||||
virtual void SetConfiguration(const Configuration configuration) = 0; | ||||||||||||||||
}; | ||||||||||||||||
|
||||||||||||||||
template<typename Configuration> | ||||||||||||||||
using ConfigurationBus = AZ::EBus<ConfigurationRequests<Configuration>>; | ||||||||||||||||
} | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,30 @@ | ||||||
/* | ||||||
* Copyright (c) Contributors to the Open 3D Engine Project. | ||||||
* For complete copyright and license terms please see the LICENSE at the root of this distribution. | ||||||
* | ||||||
* SPDX-License-Identifier: Apache-2.0 OR MIT | ||||||
* | ||||||
*/ | ||||||
|
||||||
#pragma once | ||||||
|
||||||
#include <AzCore/RTTI/RTTI.h> | ||||||
#include <AzCore/Serialization/SerializeContext.h> | ||||||
#include <ROS2Sensors/Odometry/ROS2OdometryCovariance.h> | ||||||
|
||||||
namespace ROS2 { | ||||||
|
||||||
//! A structure capturing configuration of a wheel odometry sensor. | ||||||
struct ROS2WheelOdometryConfiguration | ||||||
{ | ||||||
AZ_RTTI(ROS2WheelOdometryConfiguration, "{9dc58d89-e674-4d7f-9ea9-afe3ae7fd2eb}"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Move the UUID to the |
||||||
|
||||||
ROS2WheelOdometryConfiguration() = default; | ||||||
virtual ~ROS2WheelOdometryConfiguration() = default; | ||||||
|
||||||
static void Reflect(AZ::ReflectContext* context); | ||||||
|
||||||
ROS2OdometryCovariance m_poseCovariance; | ||||||
ROS2OdometryCovariance m_twistCovariance; | ||||||
}; | ||||||
} | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -10,12 +10,16 @@ | |||||
|
||||||
#include <AzCore/Component/Component.h> | ||||||
#include <AzCore/Serialization/EditContext.h> | ||||||
#include <AzCore/Serialization/Json/JsonSerializationResult.h> | ||||||
#include <ROS2/Frame/ROS2FrameComponent.h> | ||||||
#include <ROS2/ROS2GemUtilities.h> | ||||||
#include <ROS2/Sensor/Events/EventSourceAdapter.h> | ||||||
#include <ROS2Sensors/Configuration/ConfigurationBus.h> | ||||||
#include <ROS2Sensors/ROS2SensorsTypeIds.h> | ||||||
#include <ROS2Sensors/Sensor/SensorConfiguration.h> | ||||||
#include <ROS2Sensors/Sensor/SensorConfigurationRequestBus.h> | ||||||
#include <rapidjson/writer.h> | ||||||
#include <std_msgs/msg/string.hpp> | ||||||
|
||||||
namespace ROS2 | ||||||
{ | ||||||
|
@@ -30,29 +34,32 @@ namespace ROS2 | |||||
//! chosen event source implementation). | ||||||
//! @see ROS2::TickBasedSource | ||||||
//! @see ROS2::PhysicsBasedSource | ||||||
template<class EventSourceT> | ||||||
template<class EventSourceT, class ComponentConfigurationT> | ||||||
class ROS2SensorComponentBase | ||||||
: public AZ::Component | ||||||
, public SensorConfigurationRequestBus::Handler | ||||||
, public ConfigurationBus<ComponentConfigurationT>::Handler | ||||||
{ | ||||||
public: | ||||||
using SensorBaseType = ROS2SensorComponentBase<EventSourceT>; | ||||||
using SensorBaseType = ROS2SensorComponentBase<EventSourceT, ComponentConfigurationT>; | ||||||
|
||||||
AZ_COMPONENT_DECL((ROS2SensorComponentBase, AZ_CLASS)); | ||||||
AZ_COMPONENT_DECL((ROS2SensorComponentBase, AZ_CLASS, AZ_CLASS)); | ||||||
|
||||||
static void Reflect(AZ::ReflectContext* context) | ||||||
{ | ||||||
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context)) | ||||||
{ | ||||||
serializeContext->Class<ROS2SensorComponentBase<EventSourceT>, AZ::Component>()->Version(1)->Field( | ||||||
"SensorConfiguration", &ROS2SensorComponentBase<EventSourceT>::m_sensorConfiguration); | ||||||
serializeContext->Class<ROS2SensorComponentBase<EventSourceT, ComponentConfigurationT>, AZ::Component>()->Version(1)->Field( | ||||||
"SensorConfiguration", &ROS2SensorComponentBase<EventSourceT, ComponentConfigurationT>::m_sensorConfiguration); | ||||||
|
||||||
if (auto* editContext = serializeContext->GetEditContext()) | ||||||
{ | ||||||
editContext->Class<ROS2SensorComponentBase<EventSourceT>>("ROS2 Sensor Component Base", "Base component for sensors") | ||||||
editContext | ||||||
->Class<ROS2SensorComponentBase<EventSourceT, ComponentConfigurationT>>( | ||||||
"ROS2 Sensor Component Base", "Base component for sensors") | ||||||
->DataElement( | ||||||
AZ::Edit::UIHandlers::Default, | ||||||
&ROS2SensorComponentBase<EventSourceT>::m_sensorConfiguration, | ||||||
&ROS2SensorComponentBase<EventSourceT, ComponentConfigurationT>::m_sensorConfiguration, | ||||||
"Sensor configuration", | ||||||
"Sensor configuration"); | ||||||
} | ||||||
|
@@ -108,13 +115,82 @@ namespace ROS2 | |||||
{ | ||||||
AZ::EntityComponentIdPair entityComponentIdPair(GetEntityId(), GetId()); | ||||||
SensorConfigurationRequestBus::Handler::BusConnect(entityComponentIdPair); | ||||||
ConfigurationBus<ComponentConfigurationT>::Handler::BusConnect(GetEntityId()); | ||||||
|
||||||
if (m_sensorConfiguration.m_configurableFromROS2) | ||||||
{ | ||||||
AZStd::string ns = GetNamespace(); | ||||||
AZStd::string configurationName = ComponentConfigurationT::TYPEINFO_Name(); | ||||||
AZStd::string getTopic = ns + "/" + "Get" + configurationName; | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be done with services. |
||||||
AZStd::string setTopic = ns + "/" + "Set" + configurationName; | ||||||
m_configurationPublisher = ROS2Interface::Get()->GetNode()->create_publisher<std_msgs::msg::String>( | ||||||
getTopic.data(), rclcpp::QoS(1).transient_local()); | ||||||
m_configurationSubscriber = ROS2Interface::Get()->GetNode()->create_subscription<std_msgs::msg::String>( | ||||||
setTopic.data(), | ||||||
rclcpp::QoS(1).reliable(), | ||||||
[this](const std_msgs::msg::String::SharedPtr msg) | ||||||
{ | ||||||
ProcessConfigurationMsg(AZStd::string(msg->data.c_str())); | ||||||
}); | ||||||
|
||||||
PublishConfiguration(GetConfiguration()); | ||||||
} | ||||||
} | ||||||
|
||||||
void Deactivate() override | ||||||
{ | ||||||
m_configurationPublisher.reset(); | ||||||
m_configurationSubscriber.reset(); | ||||||
|
||||||
ConfigurationBus<ComponentConfigurationT>::Handler::BusDisconnect(); | ||||||
SensorConfigurationRequestBus::Handler::BusDisconnect(); | ||||||
} | ||||||
|
||||||
AZ::TypeId GetUnderlyingComponentType() const override | ||||||
{ | ||||||
return AZ::TypeId(ROS2Sensors::ROS2SensorComponentBaseTypeId); | ||||||
} | ||||||
|
||||||
const ComponentConfigurationT GetConfiguration() const override | ||||||
{ | ||||||
return GetComponentConfiguration(); | ||||||
} | ||||||
|
||||||
void ProcessConfigurationMsg(AZStd::string msg) | ||||||
{ | ||||||
rapidjson::Document document; | ||||||
document.Parse(msg.c_str()); | ||||||
if (document.HasParseError()) | ||||||
{ | ||||||
AZ_Error("ROS2Sensors", false, "Failed to parse configuration message"); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
return; | ||||||
} | ||||||
|
||||||
AZ::JsonDeserializerSettings deserializerSettings; | ||||||
|
||||||
ComponentConfigurationT configuration = GetConfiguration(); | ||||||
auto result = AZ::JsonSerialization::Load(configuration, document, deserializerSettings); | ||||||
auto processing = result.GetProcessing(); | ||||||
if (processing == AZ::JsonSerializationResult::Processing::Completed) | ||||||
{ | ||||||
SetConfiguration(configuration); | ||||||
} | ||||||
else | ||||||
{ | ||||||
AZ_Error("ROS2Sensors", false, "Failed to deserialize configuration message: %s", result.ToString("").c_str()); | ||||||
} | ||||||
} | ||||||
|
||||||
void SetConfiguration(const ComponentConfigurationT configuration) override | ||||||
{ | ||||||
SetComponentConfiguration(configuration); | ||||||
|
||||||
PublishConfiguration(configuration); | ||||||
} | ||||||
|
||||||
virtual const ComponentConfigurationT GetComponentConfiguration() const = 0; | ||||||
virtual void SetComponentConfiguration(const ComponentConfigurationT configuration) = 0; | ||||||
|
||||||
protected: | ||||||
//! Starts sensor with passed frequency and adapted event callback. Optionally, user can pass source event callback, that will be | ||||||
//! called with event source frequency. | ||||||
|
@@ -142,7 +218,7 @@ namespace ROS2 | |||||
m_eventSourceAdapter.Start(); | ||||||
} | ||||||
|
||||||
//! Stops sensor and disconnects event callbacks passed through RSO2::ROS2SensorComponentBase::StartSensor. | ||||||
//! Stops sensor and disconnects event callbacks passed through ROS2::ROS2SensorComponentBase::StartSensor. | ||||||
void StopSensor() | ||||||
{ | ||||||
m_eventSourceAdapter.Stop(); | ||||||
|
@@ -173,8 +249,29 @@ namespace ROS2 | |||||
|
||||||
//! Handler for adapted event. Requires manual assignment and connecting to adapted event in derived class. | ||||||
typename EventSourceT::AdaptedEventHandlerType m_adaptedEventHandler; | ||||||
|
||||||
rclcpp::Publisher<std_msgs::msg::String>::SharedPtr m_configurationPublisher; ///< Publisher for the sensor configuration. | ||||||
rclcpp::Subscription<std_msgs::msg::String>::SharedPtr m_configurationSubscriber; ///< Subscriber for the sensor configuration. | ||||||
|
||||||
private: | ||||||
void PublishConfiguration(const ComponentConfigurationT& configuration) | ||||||
{ | ||||||
if (m_configurationPublisher != nullptr) | ||||||
{ | ||||||
rapidjson::Document document(rapidjson::kObjectType); | ||||||
AZ::JsonSerializerSettings serializerSettings; | ||||||
serializerSettings.m_keepDefaults = true; | ||||||
AZ::JsonSerialization::Store(document, document.GetAllocator(), configuration, serializerSettings); | ||||||
rapidjson::StringBuffer buffer; | ||||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); | ||||||
document.Accept(writer); | ||||||
std_msgs::msg::String msg; | ||||||
msg.data = buffer.GetString(); | ||||||
m_configurationPublisher->publish(msg); | ||||||
} | ||||||
} | ||||||
}; | ||||||
|
||||||
AZ_COMPONENT_IMPL_INLINE( | ||||||
(ROS2SensorComponentBase, AZ_CLASS), "ROS2SensorComponentBase", "{2DF9A652-DF5D-43B1-932F-B6A838E36E97}", AZ::Component) | ||||||
(ROS2SensorComponentBase, AZ_CLASS, AZ_CLASS), "ROS2SensorComponentBase", ROS2Sensors::ROS2SensorComponentBaseTypeId, AZ::Component) | ||||||
} // namespace ROS2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI : this change is in the development.