Kaynağa Gözat

Re-enable sensor hooks in RobotImporter Gem (#920)

Signed-off-by: Jan Hanca <[email protected]>
Jan Hanca 1 ay önce
ebeveyn
işleme
c3f0adfc12
31 değiştirilmiş dosya ile 409 ekleme ve 168 silme
  1. 2 0
      Gems/ROS2/Code/Source/Frame/ROS2FrameSystemBus.h
  2. 1 0
      Gems/ROS2/Code/ros2_editor_shared_api_files.cmake
  3. 0 2
      Gems/ROS2/Code/ros2_editor_shared_files.cmake
  4. 3 1
      Gems/ROS2RobotImporter/Code/CMakeLists.txt
  5. 33 16
      Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/Hooks/ROS2CameraSensorHook.cpp
  6. 21 17
      Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/Hooks/ROS2GNSSSensorHook.cpp
  7. 22 17
      Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/Hooks/ROS2ImuSensorHook.cpp
  8. 24 22
      Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/Hooks/ROS2LidarSensorHook.cpp
  9. 11 9
      Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/ROS2SDFormatHooksUtils.cpp
  10. 8 9
      Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/ROS2SDFormatHooksUtils.h
  11. 7 9
      Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/ROS2SensorHooks.h
  12. 4 4
      Gems/ROS2RobotImporter/Code/Source/Tools/ROS2RobotImporterEditorSystemComponent.cpp
  13. 4 4
      Gems/ROS2RobotImporter/Code/ros2robotimporter_editor_private_files.cmake
  14. 3 2
      Gems/ROS2RobotImporter/gem.json
  15. 1 0
      Gems/ROS2Sensors/Code/CMakeLists.txt
  16. 11 0
      Gems/ROS2Sensors/Code/Include/ROS2Sensors/Camera/CameraSensorConfiguration.h
  17. 3 3
      Gems/ROS2Sensors/Code/Include/ROS2Sensors/Lidar/LidarSensorConfiguration.h
  18. 98 0
      Gems/ROS2Sensors/Code/Include/ROS2Sensors/ROS2SensorsEditorBus.h
  19. 4 0
      Gems/ROS2Sensors/Code/Include/ROS2Sensors/ROS2SensorsTypeIds.h
  20. 0 21
      Gems/ROS2Sensors/Code/Source/Camera/CameraConstants.h
  21. 0 1
      Gems/ROS2Sensors/Code/Source/Camera/CameraPublishers.cpp
  22. 0 1
      Gems/ROS2Sensors/Code/Source/Camera/ROS2CameraSensorEditorComponent.cpp
  23. 2 1
      Gems/ROS2Sensors/Code/Source/Camera/ROS2CameraSensorEditorComponent.h
  24. 0 14
      Gems/ROS2Sensors/Code/Source/Lidar/LidarRegistrarSystemComponent.cpp
  25. 0 6
      Gems/ROS2Sensors/Code/Source/Lidar/LidarRegistrarSystemComponent.h
  26. 18 2
      Gems/ROS2Sensors/Code/Source/Lidar/LidarSensorConfiguration.cpp
  27. 57 3
      Gems/ROS2Sensors/Code/Source/Tools/ROS2SensorsEditorSystemComponent.cpp
  28. 69 1
      Gems/ROS2Sensors/Code/Source/Tools/ROS2SensorsEditorSystemComponent.h
  29. 1 0
      Gems/ROS2Sensors/Code/ros2sensors_editor_api_files.cmake
  30. 2 0
      Gems/ROS2Sensors/Code/ros2sensors_lidar_shared_files.cmake
  31. 0 3
      Gems/ROS2Sensors/Code/ros2sensors_private_files.cmake

+ 2 - 0
Gems/ROS2/Code/Source/Frame/ROS2FrameSystemBus.h

@@ -7,6 +7,8 @@
  */
 #pragma once
 
+#include <AzCore/Component/EntityId.h>
+#include <AzCore/EBus/EBus.h>
 #include <AzCore/EBus/Policies.h>
 #include <AzCore/Interface/Interface.h>
 #include <AzCore/RTTI/RTTIMacros.h>

+ 1 - 0
Gems/ROS2/Code/ros2_editor_shared_api_files.cmake

@@ -5,4 +5,5 @@
 
 set(FILES
     Source/Frame/ROS2FrameEditorComponent.cpp
+    Source/ROS2GemUtilities.cpp
 )

+ 0 - 2
Gems/ROS2/Code/ros2_editor_shared_files.cmake

@@ -4,7 +4,5 @@
 # SPDX-License-Identifier: Apache-2.0 OR MIT
 
 set(FILES
-    Source/Frame/ROS2FrameEditorComponent.cpp
     Source/Tools/ROS2EditorModule.cpp
-    Source/ROS2GemUtilities.cpp
 )

+ 3 - 1
Gems/ROS2RobotImporter/Code/CMakeLists.txt

@@ -58,6 +58,7 @@ ly_add_target(
             AZ::AzCore
             AZ::AzFramework
             Gem::ROS2.Static
+            Gem::ROS2Sensors.Lidar.Static
 )
 
 # Here add ${gem_name} target, it depends on the Private Object library and Public API interface
@@ -146,8 +147,9 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
                 AZ::AzToolsFramework
                 Gem::CommonFeaturesAtom.Editor.Static
                 Gem::PhysX5.Editor.Static
-                Gem::ROS2.Editor.Static
                 Gem::ROS2.Static
+                Gem::ROS2.Editor.Static
+                Gem::ROS2Sensors.Editor.API
                 ${gem_name}.Private.Object
             PRIVATE
                 AZ::AssetBuilderSDK

+ 33 - 16
Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/Hooks/ROS2CameraSensorHook.cpp

@@ -6,9 +6,9 @@
  *
  */
 
-#include <Camera/CameraConstants.h>
-#include <Camera/ROS2CameraSensorEditorComponent.h>
 #include <ROS2/Frame/ROS2FrameEditorComponent.h>
+#include <ROS2Sensors/Camera/CameraSensorConfiguration.h>
+#include <ROS2Sensors/ROS2SensorsEditorBus.h>
 #include <RobotImporter/SDFormat/ROS2SDFormatHooksUtils.h>
 #include <RobotImporter/SDFormat/ROS2SensorHooks.h>
 
@@ -47,7 +47,8 @@ namespace ROS2RobotImporter::SDFormat
                 return AZ::Failure(AZStd::string("Failed to read parsed SDFormat data of %s camera sensor", sdfSensor.Name().c_str()));
             }
 
-            CameraSensorConfiguration cameraConfiguration;
+            // Get camera sensor configuration
+            ROS2Sensors::CameraSensorConfiguration cameraConfiguration;
             cameraConfiguration.m_depthCamera = cameraSensor->HasDepthCamera();
             cameraConfiguration.m_colorCamera = (sdfSensor.Type() != sdf::SensorType::DEPTH_CAMERA) ? true : false;
             cameraConfiguration.m_width = cameraSensor->ImageWidth();
@@ -72,8 +73,10 @@ namespace ROS2RobotImporter::SDFormat
             const auto cameraPluginParams = HooksUtils::GetPluginParams(sdfSensor.Plugins());
             const auto element = sdfSensor.Element();
 
-            SensorConfiguration sensorConfiguration;
-            sensorConfiguration.m_frequency = HooksUtils::GetFrequency(cameraPluginParams);
+            // Get base sensor configuration
+            ROS2::SensorConfiguration sensorConfiguration;
+            element->Get<bool>("visualize", sensorConfiguration.m_visualize, false);
+            element->Get<float>("update_rate", sensorConfiguration.m_frequency, 10.0f);
 
             if (sdfSensor.Type() != sdf::SensorType::DEPTH_CAMERA)
             { // COLOR_CAMERA and RGBD_CAMERA
@@ -84,9 +87,15 @@ namespace ROS2RobotImporter::SDFormat
                 const AZStd::string colorInfo = HooksUtils::ValueOfAny(cameraPluginParams, rawInfoParamNames, "camera_color_info");
 
                 HooksUtils::AddTopicConfiguration(
-                    sensorConfiguration, imageColor, CameraConstants::ImageMessageType, CameraConstants::ColorImageConfig);
+                    sensorConfiguration,
+                    imageColor,
+                    ROS2Sensors::CameraConstants::ImageMessageType,
+                    ROS2Sensors::CameraConstants::ColorImageConfig);
                 HooksUtils::AddTopicConfiguration(
-                    sensorConfiguration, colorInfo, CameraConstants::CameraInfoMessageType, CameraConstants::ColorInfoConfig);
+                    sensorConfiguration,
+                    colorInfo,
+                    ROS2Sensors::CameraConstants::CameraInfoMessageType,
+                    ROS2Sensors::CameraConstants::ColorInfoConfig);
             }
             if (sdfSensor.Type() != sdf::SensorType::CAMERA)
             { // DEPTH_CAMERA and RGBD_CAMERA
@@ -97,11 +106,16 @@ namespace ROS2RobotImporter::SDFormat
                 const AZStd::string depthInfo = HooksUtils::ValueOfAny(cameraPluginParams, depthInfoParamNames, "depth_camera_info");
 
                 HooksUtils::AddTopicConfiguration(
-                    sensorConfiguration, imageDepth, CameraConstants::ImageMessageType, CameraConstants::DepthImageConfig);
+                    sensorConfiguration,
+                    imageDepth,
+                    ROS2Sensors::CameraConstants::ImageMessageType,
+                    ROS2Sensors::CameraConstants::DepthImageConfig);
                 HooksUtils::AddTopicConfiguration(
-                    sensorConfiguration, depthInfo, CameraConstants::CameraInfoMessageType, CameraConstants::DepthInfoConfig);
+                    sensorConfiguration,
+                    depthInfo,
+                    ROS2Sensors::CameraConstants::CameraInfoMessageType,
+                    ROS2Sensors::CameraConstants::DepthInfoConfig);
             }
-            element->Get<bool>("visualize", sensorConfiguration.m_visualize, false);
 
             // Get frame configuration
             const auto frameConfiguration = HooksUtils::GetFrameConfiguration(cameraPluginParams);
@@ -110,14 +124,17 @@ namespace ROS2RobotImporter::SDFormat
             HooksUtils::CreateComponent<ROS2::ROS2FrameEditorComponent>(entity, frameConfiguration);
 
             // Create Camera component
-            if (HooksUtils::CreateComponent<ROS2Sensors::ROS2CameraSensorEditorComponent>(entity, sensorConfiguration, cameraConfiguration))
-            {
-                return AZ::Success();
-            }
-            else
+            auto interface = ROS2Sensors::ROS2SensorsEditorInterface::Get();
+            AZ_Warning("ROS2RobotImporter", interface, "ROS2SensorsInterface is not available. Cannot create Camera sensor component.");
+            if (interface)
             {
-                return AZ::Failure(AZStd::string("Failed to create ROS 2 Camera Sensor component"));
+                if (auto* sensor = interface->CreateROS2CameraSensorComponent(entity, sensorConfiguration, cameraConfiguration))
+                {
+                    return AZ::Success();
+                }
             }
+
+            return AZ::Failure(AZStd::string("Failed to create ROS 2 Camera Sensor component"));
         };
 
         return importerHook;

+ 21 - 17
Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/Hooks/ROS2GNSSSensorHook.cpp

@@ -6,8 +6,11 @@
  *
  */
 
-#include <GNSS/ROS2GNSSSensorComponent.h>
+#include <AzCore/Math/Uuid.h>
 #include <ROS2/Frame/ROS2FrameEditorComponent.h>
+#include <ROS2/Sensor/Events/TickBasedSource.h>
+#include <ROS2/Sensor/ROS2SensorComponentBase.h>
+#include <ROS2Sensors/ROS2SensorsEditorBus.h>
 #include <RobotImporter/SDFormat/ROS2SDFormatHooksUtils.h>
 #include <RobotImporter/SDFormat/ROS2SensorHooks.h>
 
@@ -22,9 +25,8 @@ namespace ROS2RobotImporter::SDFormat
         importerHook.m_sensorTypes = AZStd::unordered_set<sdf::SensorType>{ sdf::SensorType::NAVSAT };
         importerHook.m_supportedSensorParams = AZStd::unordered_set<AZStd::string>{ ">pose", ">update_rate", ">topic", ">visualize" };
         importerHook.m_pluginNames = AZStd::unordered_set<AZStd::string>{ "libgazebo_ros_gps_sensor.so" };
-        importerHook.m_supportedPluginParams =
-            AZStd::unordered_set<AZStd::string>{ ">ros>remapping", ">ros>argument",   ">ros>frame_name", ">ros>namespace",
-                                                 ">frameName",     ">robotNamespace", ">updateRate" };
+        importerHook.m_supportedPluginParams = AZStd::unordered_set<AZStd::string>{ ">ros>remapping", ">ros>argument", ">ros>frame_name",
+                                                                                    ">ros>namespace", ">frameName",    ">robotNamespace" };
         importerHook.m_sdfSensorToComponentCallback = [](AZ::Entity& entity,
                                                          const sdf::Sensor& sdfSensor) -> SensorImporterHook::ConvertSensorOutcome
         {
@@ -36,14 +38,12 @@ namespace ROS2RobotImporter::SDFormat
             const auto gnssPluginParams = HooksUtils::GetPluginParams(sdfSensor.Plugins());
             const auto element = sdfSensor.Element();
 
-            SensorConfiguration sensorConfiguration;
-            sensorConfiguration.m_frequency = HooksUtils::GetFrequency(gnssPluginParams);
-            const AZStd::string messageType = "sensor_msgs::msg::NavSatFix";
-
-            // setting gnss topic
-            const AZStd::string messageTopic = HooksUtils::GetTopicName(gnssPluginParams, element, "gnss");
+            // Get base sensor configuration
+            ROS2::SensorConfiguration sensorConfiguration;
             element->Get<bool>("visualize", sensorConfiguration.m_visualize, false);
-
+            element->Get<float>("update_rate", sensorConfiguration.m_frequency, 10.0f);
+            const AZStd::string messageTopic = HooksUtils::GetTopicName(gnssPluginParams, element, "gnss");
+            const AZStd::string messageType = "sensor_msgs::msg::NavSatFix";
             HooksUtils::AddTopicConfiguration(sensorConfiguration, messageTopic, messageType, messageType);
 
             // Get frame configuration
@@ -52,14 +52,18 @@ namespace ROS2RobotImporter::SDFormat
             // Create required components
             HooksUtils::CreateComponent<ROS2::ROS2FrameEditorComponent>(entity, frameConfiguration);
 
-            if (HooksUtils::CreateComponent<ROS2Sensors::ROS2GNSSSensorComponent>(entity, sensorConfiguration))
-            {
-                return AZ::Success();
-            }
-            else
+            // Create GNSS component
+            auto interface = ROS2Sensors::ROS2SensorsEditorInterface::Get();
+            AZ_Warning("ROS2RobotImporter", interface, "ROS2SensorsInterface is not available. Cannot create GNSS sensor component.");
+            if (interface)
             {
-                return AZ::Failure(AZStd::string("Failed to create ROS 2 GNSS Sensor component"));
+                if (auto* sensor = interface->CreateROS2GnssSensorComponent(entity, sensorConfiguration))
+                {
+                    return AZ::Success();
+                }
             }
+
+            return AZ::Failure(AZStd::string("Failed to create ROS 2 Imu Sensor component"));
         };
 
         return importerHook;

+ 22 - 17
Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/Hooks/ROS2ImuSensorHook.cpp

@@ -6,8 +6,12 @@
  *
  */
 
-#include <Imu/ROS2ImuSensorComponent.h>
+#include <AzCore/Math/Uuid.h>
 #include <ROS2/Frame/ROS2FrameEditorComponent.h>
+#include <ROS2/Sensor/Events/PhysicsBasedSource.h>
+#include <ROS2/Sensor/ROS2SensorComponentBase.h>
+#include <ROS2Sensors/Imu/ImuSensorConfiguration.h>
+#include <ROS2Sensors/ROS2SensorsEditorBus.h>
 #include <RobotImporter/SDFormat/ROS2SDFormatHooksUtils.h>
 #include <RobotImporter/SDFormat/ROS2SensorHooks.h>
 #include <Source/EditorArticulationLinkComponent.h>
@@ -39,8 +43,8 @@ namespace ROS2RobotImporter::SDFormat
                                                                                     ">visualize" };
         importerHook.m_pluginNames = AZStd::unordered_set<AZStd::string>{ "libgazebo_ros_imu_sensor.so" };
         importerHook.m_supportedPluginParams =
-            AZStd::unordered_set<AZStd::string>{ ">topicName",     ">ros>remapping", ">ros>argument",   ">ros>frame_name",
-                                                 ">ros>namespace", ">frameName",     ">robotNamespace", ">updateRate" };
+            AZStd::unordered_set<AZStd::string>{ ">topicName",     ">ros>remapping", ">ros>argument",  ">ros>frame_name",
+                                                 ">ros>namespace", ">frameName",     ">robotNamespace" };
         importerHook.m_sdfSensorToComponentCallback = [](AZ::Entity& entity,
                                                          const sdf::Sensor& sdfSensor) -> SensorImporterHook::ConvertSensorOutcome
         {
@@ -50,7 +54,7 @@ namespace ROS2RobotImporter::SDFormat
                 return AZ::Failure(AZStd::string("Failed to read parsed SDFormat data of %s imu sensor", sdfSensor.Name().c_str()));
             }
 
-            ImuSensorConfiguration imuConfiguration;
+            ROS2Sensors::ImuSensorConfiguration imuConfiguration;
             const auto& angVelXNoise = imuSensor->AngularVelocityXNoise();
             const auto& angVelYNoise = imuSensor->AngularVelocityYNoise();
             const auto& angVelZNoise = imuSensor->AngularVelocityZNoise();
@@ -84,14 +88,12 @@ namespace ROS2RobotImporter::SDFormat
             const auto imuPluginParams = HooksUtils::GetPluginParams(sdfSensor.Plugins());
             const auto element = sdfSensor.Element();
 
-            SensorConfiguration sensorConfiguration;
-            sensorConfiguration.m_frequency = HooksUtils::GetFrequency(imuPluginParams);
-            const AZStd::string messageType = "sensor_msgs::msg::Imu";
-
-            // setting imu topic
-            const AZStd::string messageTopic = HooksUtils::GetTopicName(imuPluginParams, element, "imu");
+            // Get base sensor configuration
+            ROS2::SensorConfiguration sensorConfiguration;
             element->Get<bool>("visualize", sensorConfiguration.m_visualize, false);
-
+            element->Get<float>("update_rate", sensorConfiguration.m_frequency, 10.0f);
+            const AZStd::string messageTopic = HooksUtils::GetTopicName(imuPluginParams, element, "imu");
+            const AZStd::string messageType = "sensor_msgs::msg::Imu";
             HooksUtils::AddTopicConfiguration(sensorConfiguration, messageTopic, messageType, messageType);
 
             // Get frame configuration
@@ -102,14 +104,17 @@ namespace ROS2RobotImporter::SDFormat
             HooksUtils::CreateComponent<PhysX::EditorArticulationLinkComponent>(entity);
 
             // Create Imu component
-            if (HooksUtils::CreateComponent<ROS2Sensors::ROS2ImuSensorComponent>(entity, sensorConfiguration, imuConfiguration))
+            auto interface = ROS2Sensors::ROS2SensorsEditorInterface::Get();
+            AZ_Warning("ROS2RobotImporter", interface, "ROS2SensorsInterface is not available. Cannot create Imu sensor component.");
+            if (interface)
             {
-                return AZ::Success();
-            }
-            else
-            {
-                return AZ::Failure(AZStd::string("Failed to create ROS 2 Imu Sensor component"));
+                if (auto* sensor = interface->CreateROS2ImuSensorComponent(entity, sensorConfiguration, imuConfiguration))
+                {
+                    return AZ::Success();
+                }
             }
+
+            return AZ::Failure(AZStd::string("Failed to create ROS 2 Imu Sensor component"));
         };
 
         return importerHook;

+ 24 - 22
Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/Hooks/ROS2LidarSensorHook.cpp

@@ -6,9 +6,10 @@
  *
  */
 
-#include <Lidar/ROS2Lidar2DSensorComponent.h>
-#include <Lidar/ROS2LidarSensorComponent.h>
 #include <ROS2/Frame/ROS2FrameEditorComponent.h>
+#include <ROS2Sensors/Lidar/LidarSensorConfiguration.h>
+#include <ROS2Sensors/Lidar/LidarTemplateUtils.h>
+#include <ROS2Sensors/ROS2SensorsEditorBus.h>
 #include <RobotImporter/SDFormat/ROS2SDFormatHooksUtils.h>
 #include <RobotImporter/SDFormat/ROS2SensorHooks.h>
 
@@ -60,19 +61,18 @@ namespace ROS2RobotImporter::SDFormat
             const auto lidarPluginParams = HooksUtils::GetPluginParams(sdfSensor.Plugins());
             const auto element = sdfSensor.Element();
 
-            SensorConfiguration sensorConfiguration;
-            sensorConfiguration.m_frequency = HooksUtils::GetFrequency(lidarPluginParams);
+            // Get base sensor configuration
+            ROS2::SensorConfiguration sensorConfiguration;
+            element->Get<bool>("visualize", sensorConfiguration.m_visualize, false);
+            element->Get<float>("update_rate", sensorConfiguration.m_frequency, 10.0f);
             const bool is2DLidar = (lidarSensor->VerticalScanSamples() == 1);
             const AZStd::string messageType = is2DLidar ? "sensor_msgs::msg::LaserScan" : "sensor_msgs::msg::PointCloud2";
-
-            // setting lidar topic
             const AZStd::string messageTopic = HooksUtils::GetTopicName(lidarPluginParams, element, (is2DLidar ? "scan" : "pc"));
-            element->Get<bool>("visualize", sensorConfiguration.m_visualize, false);
-
             HooksUtils::AddTopicConfiguration(sensorConfiguration, messageTopic, messageType, messageType);
 
-            LidarSensorConfiguration lidarConfiguration{ is2DLidar ? LidarTemplateUtils::Get2DModels()
-                                                                   : LidarTemplateUtils::Get3DModels() };
+            // Get Lidar sensor configuration
+            ROS2Sensors::LidarSensorConfiguration lidarConfiguration{ is2DLidar ? ROS2Sensors::LidarTemplateUtils::Get2DModels()
+                                                                                : ROS2Sensors::LidarTemplateUtils::Get3DModels() };
             lidarConfiguration.m_lidarParameters.m_name = AZStd::string(sdfSensor.Name().c_str());
             lidarConfiguration.m_lidarParameters.m_minHAngle = lidarSensor->HorizontalScanMinAngle().Degree();
             lidarConfiguration.m_lidarParameters.m_maxHAngle = lidarSensor->HorizontalScanMaxAngle().Degree();
@@ -83,10 +83,11 @@ namespace ROS2RobotImporter::SDFormat
             lidarConfiguration.m_lidarParameters.m_minRange = lidarSensor->RangeMin();
             lidarConfiguration.m_lidarParameters.m_maxRange = lidarSensor->RangeMax();
 
-            const auto lidarSystems = LidarRegistrarInterface::Get()->GetRegisteredLidarSystems();
-            if (!lidarSystems.empty())
+            auto* lidarRegistrar = ROS2Sensors::LidarRegistrarInterface::Get();
+            if (lidarRegistrar)
             {
-                const AZStd::string query = (sdfSensor.Type() == sdf::SensorType::GPU_LIDAR ? "RobotecGPULidar" : LidarSystem::SystemName);
+                const auto lidarSystems = lidarRegistrar->GetRegisteredLidarSystems();
+                const AZStd::string query = (sdfSensor.Type() == sdf::SensorType::GPU_LIDAR ? "RobotecGPULidar" : "Scene Queries");
                 if (const auto it = AZStd::find(lidarSystems.begin(), lidarSystems.end(), query); it != lidarSystems.end())
                 {
                     lidarConfiguration.m_lidarSystem = *it;
@@ -109,17 +110,18 @@ namespace ROS2RobotImporter::SDFormat
             HooksUtils::CreateComponent<ROS2::ROS2FrameEditorComponent>(entity, frameConfiguration);
 
             // Create Lidar component
-            const auto lidarComponent = is2DLidar
-                ? HooksUtils::CreateComponent<ROS2Sensors::ROS2Lidar2DSensorComponent>(entity, sensorConfiguration, lidarConfiguration)
-                : HooksUtils::CreateComponent<ROS2Sensors::ROS2LidarSensorComponent>(entity, sensorConfiguration, lidarConfiguration);
-            if (lidarComponent)
+            auto interface = ROS2Sensors::ROS2SensorsEditorInterface::Get();
+            AZ_Warning("ROS2RobotImporter", interface, "ROS2SensorsInterface is not available. Cannot create Lidar sensor component.");
+            if (interface)
             {
-                return AZ::Success();
-            }
-            else
-            {
-                return AZ::Failure(AZStd::string("Failed to create ROS 2 Lidar Sensor component"));
+                if (auto* sensor = is2DLidar ? interface->CreateROS2Lidar2DSensorComponent(entity, sensorConfiguration, lidarConfiguration)
+                                             : interface->CreateROS2LidarSensorComponent(entity, sensorConfiguration, lidarConfiguration))
+                {
+                    return AZ::Success();
+                }
             }
+
+            return AZ::Failure(AZStd::string("Failed to create ROS 2 Imu Sensor component"));
         };
 
         return importerHook;

+ 11 - 9
Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/ROS2SDFormatHooksUtils.cpp

@@ -20,15 +20,17 @@
 
 namespace ROS2RobotImporter::SDFormat
 {
-    // temporarily disable import hooks for sensors and models for https://github.com/o3de/sig-simulation/pull/96
-    // void HooksUtils::AddTopicConfiguration(
-    //     SensorConfiguration& sensorConfig, const AZStd::string& topic, const AZStd::string& messageType, const AZStd::string& configName)
-    // {
-    //     TopicConfiguration config;
-    //     config.m_topic = topic;
-    //     config.m_type = messageType;
-    //     sensorConfig.m_publishersConfigurations.insert(AZStd::make_pair(configName, config));
-    // }
+    void HooksUtils::AddTopicConfiguration(
+        ROS2::SensorConfiguration& sensorConfig,
+        const AZStd::string& topic,
+        const AZStd::string& messageType,
+        const AZStd::string& configName)
+    {
+        ROS2::TopicConfiguration config;
+        config.m_topic = topic;
+        config.m_type = messageType;
+        sensorConfig.m_publishersConfigurations.insert(AZStd::make_pair(configName, config));
+    }
 
     AZ::EntityId HooksUtils::GetJointEntityId(
         const std::string& jointName, const sdf::Model& sdfModel, const CreatedEntitiesMap& createdEntities)

+ 8 - 9
Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/ROS2SDFormatHooksUtils.h

@@ -16,9 +16,10 @@
 #include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
 #include <AzToolsFramework/ToolsComponents/GenericComponentWrapper.h>
 #include <ROS2/Frame/ROS2FrameEditorComponent.h>
+#include <ROS2/Sensor/Events/PhysicsBasedSource.h>
+#include <ROS2/Sensor/Events/TickBasedSource.h>
+#include <ROS2/Sensor/SensorConfiguration.h>
 #include <ROS2RobotImporter/SDFormatModelPluginImporterHook.h>
-// temporarily disable import hooks for sensors and models for https://github.com/o3de/sig-simulation/pull/96
-// #include <ROS2/Sensor/SensorConfiguration.h>
 #include <Source/EditorArticulationLinkComponent.h>
 #include <Source/EditorHingeJointComponent.h>
 
@@ -34,13 +35,11 @@ namespace ROS2RobotImporter::SDFormat
         //! @param topic ROS 2 topic name
         //! @param messageType ROS 2 message type
         //! @param configName name under which topic configuration is stored in sensor's configuration
-
-        // temporarily disable import hooks for sensors and models for https://github.com/o3de/sig-simulation/pull/96
-        // void AddTopicConfiguration(
-        //     SensorConfiguration& sensorConfig,
-        //     const AZStd::string& topic,
-        //     const AZStd::string& messageType,
-        //     const AZStd::string& configName);
+        void AddTopicConfiguration(
+            ROS2::SensorConfiguration& sensorConfig,
+            const AZStd::string& topic,
+            const AZStd::string& messageType,
+            const AZStd::string& configName);
 
         //! Find O3DE entity id of the SDFormat joint based on its name and a map of all created entities.
         //! @param jointName name of the joint in query

+ 7 - 9
Gems/ROS2RobotImporter/Code/Source/RobotImporter/SDFormat/ROS2SensorHooks.h

@@ -14,19 +14,17 @@ namespace ROS2RobotImporter::SDFormat
 {
     namespace ROS2SensorHooks
     {
-        // temporarily disable import hooks for sensors and models for https://github.com/o3de/sig-simulation/pull/96
-
         //! Retrieve a sensor importer hook which is used to map SDFormat sensor of type camera, depth or rgbd into O3DE
-        // //! ROS2CameraSensorComponent
-        // SensorImporterHook ROS2CameraSensor();
+        //! ROS2CameraSensorComponent
+        SensorImporterHook ROS2CameraSensor();
 
-        // //! Retrieve a sensor importer hook which is used to map SDFormat sensor of type navsat into O3DE ROS2GNSSSensorComponent
-        // SensorImporterHook ROS2GNSSSensor();
+        //! Retrieve a sensor importer hook which is used to map SDFormat sensor of type navsat into O3DE ROS2GNSSSensorComponent
+        SensorImporterHook ROS2GNSSSensor();
 
-        // //! Retrieve a sensor importer hook which is used to map SDFormat sensor of type imu into O3DE ROS2ImuSensorComponent
-        // SensorImporterHook ROS2ImuSensor();
+        //! Retrieve a sensor importer hook which is used to map SDFormat sensor of type imu into O3DE ROS2ImuSensorComponent
+        SensorImporterHook ROS2ImuSensor();
 
         // //! Retrieve a sensor importer hook which is used to map SDFormat sensor of type lidar into O3DE ROS2LidarSensorComponent
-        // SensorImporterHook ROS2LidarSensor();
+        SensorImporterHook ROS2LidarSensor();
     } // namespace ROS2SensorHooks
 } // namespace ROS2RobotImporter::SDFormat

+ 4 - 4
Gems/ROS2RobotImporter/Code/Source/Tools/ROS2RobotImporterEditorSystemComponent.cpp

@@ -68,10 +68,10 @@ namespace ROS2RobotImporter
 
         // Register default sensor and plugin hooks
         // temporarily disable import hooks for sensors and models for https://github.com/o3de/sig-simulation/pull/96
-        // m_sensorHooks.emplace_back(SDFormat::ROS2SensorHooks::ROS2CameraSensor());
-        // m_sensorHooks.emplace_back(SDFormat::ROS2SensorHooks::ROS2GNSSSensor());
-        // m_sensorHooks.emplace_back(SDFormat::ROS2SensorHooks::ROS2ImuSensor());
-        // m_sensorHooks.emplace_back(SDFormat::ROS2SensorHooks::ROS2LidarSensor());
+        m_sensorHooks.emplace_back(SDFormat::ROS2SensorHooks::ROS2CameraSensor());
+        m_sensorHooks.emplace_back(SDFormat::ROS2SensorHooks::ROS2GNSSSensor());
+        m_sensorHooks.emplace_back(SDFormat::ROS2SensorHooks::ROS2ImuSensor());
+        m_sensorHooks.emplace_back(SDFormat::ROS2SensorHooks::ROS2LidarSensor());
         // m_modelPluginHooks.emplace_back(SDFormat::ROS2ModelPluginHooks::ROS2AckermannModel());
         // m_modelPluginHooks.emplace_back(SDFormat::ROS2ModelPluginHooks::ROS2SkidSteeringModel());
         // m_modelPluginHooks.emplace_back(SDFormat::ROS2ModelPluginHooks::ROS2JointStatePublisherModel());

+ 4 - 4
Gems/ROS2RobotImporter/Code/ros2robotimporter_editor_private_files.cmake

@@ -31,10 +31,10 @@ set(FILES
     Source/RobotImporter/RobotImporterWidget.h
     # temporarily disable import hooks for sensors and models for https://github.com/o3de/sig-simulation/pull/96
     # Source/RobotImporter/SDFormat/Hooks/ROS2AckermannModelHook.cpp
-    # Source/RobotImporter/SDFormat/Hooks/ROS2CameraSensorHook.cpp
-    # Source/RobotImporter/SDFormat/Hooks/ROS2GNSSSensorHook.cpp
-    # Source/RobotImporter/SDFormat/Hooks/ROS2ImuSensorHook.cpp
-    # Source/RobotImporter/SDFormat/Hooks/ROS2LidarSensorHook.cpp
+    Source/RobotImporter/SDFormat/Hooks/ROS2CameraSensorHook.cpp
+    Source/RobotImporter/SDFormat/Hooks/ROS2GNSSSensorHook.cpp
+    Source/RobotImporter/SDFormat/Hooks/ROS2ImuSensorHook.cpp
+    Source/RobotImporter/SDFormat/Hooks/ROS2LidarSensorHook.cpp
     # Source/RobotImporter/SDFormat/Hooks/ROS2SkidSteeringModelHook.cpp
     # Source/RobotImporter/SDFormat/Hooks/ROS2JointPoseTrajectoryModelHook.cpp
     # Source/RobotImporter/SDFormat/Hooks/ROS2JointStatePublisherModelHook.cpp

+ 3 - 2
Gems/ROS2RobotImporter/gem.json

@@ -18,10 +18,11 @@
         "Linux"
     ],
     "icon_path": "preview.png",
-    "requirements": "Requires ROS 2 installation (supported distributions: Humble, Jazzy). Source your workspace before building the Gem",
+    "requirements": "Requires ROS 2 Gem, ROS2Sensors Gem and ROS2Controllers Gem.",
     "documentation_url": "Link to any documentation of your Gem",
     "dependencies": [
-        "ROS2>=3.3.0"
+        "ROS2>=3.3.0",
+        "ROS2Sensors"
     ],
     "repo_uri": "https://github.com/o3de/o3de-extras/",
     "source_control_uri": "https://github.com/o3de/o3de-extras/development/Gems/ROS2RobotImporter",

+ 1 - 0
Gems/ROS2Sensors/Code/CMakeLists.txt

@@ -57,6 +57,7 @@ ly_add_target(
     BUILD_DEPENDENCIES
         INTERFACE
            AZ::AzCore
+           Gem::ROS2.API
 )
 
 # The ${gem_name}.Private.Object target is an internal target

+ 11 - 0
Gems/ROS2Sensors/Code/Include/ROS2Sensors/Camera/CameraSensorConfiguration.h

@@ -14,6 +14,17 @@
 
 namespace ROS2Sensors
 {
+    //! Constants used in camera sensor configuration and ROS2 messages.
+    namespace CameraConstants
+    {
+        inline constexpr char ImageMessageType[] = "sensor_msgs::msg::Image";
+        inline constexpr char DepthImageConfig[] = "Depth Image";
+        inline constexpr char ColorImageConfig[] = "Color Image";
+        inline constexpr char DepthInfoConfig[] = "Depth Camera Info";
+        inline constexpr char ColorInfoConfig[] = "Color Camera Info";
+        inline constexpr char CameraInfoMessageType[] = "sensor_msgs::msg::CameraInfo";
+    } // namespace CameraConstants
+
     //! A structure capturing configuration of a single camera sensor with up to two image sources (color and depth).
     struct CameraSensorConfiguration
     {

+ 3 - 3
Gems/ROS2Sensors/Code/Include/ROS2Sensors/Lidar/LidarSensorConfiguration.h

@@ -11,7 +11,7 @@
 #include <AzCore/RTTI/RTTI.h>
 #include <AzCore/Serialization/SerializeContext.h>
 #include <AzCore/std/string/string.h>
-#include <Lidar/LidarRegistrarSystemComponent.h>
+#include <ROS2Sensors/Lidar/LidarRegistrarBus.h>
 #include <ROS2Sensors/Lidar/LidarTemplate.h>
 #include <ROS2Sensors/Lidar/LidarTemplateUtils.h>
 #include <ROS2Sensors/ROS2SensorsTypeIds.h>
@@ -55,6 +55,8 @@ namespace ROS2Sensors
 
         AZ::Crc32 OnLidarModelSelected();
         AZ::Crc32 OnLidarImplementationSelected();
+        void UpdateShowNoise();
+        AZStd::string GetDefaultLidarSystem();
 
         //! Get all models this configuration can be set to (for example all 2D lidar models).
         AZStd::vector<AZStd::string> GetAvailableModels() const;
@@ -62,7 +64,5 @@ namespace ROS2Sensors
         AZStd::vector<AZStd::string> FetchLidarSystemList();
 
         AZStd::vector<LidarTemplate::LidarModel> m_availableModels;
-
-        void UpdateShowNoise();
     };
 } // namespace ROS2Sensors

+ 98 - 0
Gems/ROS2Sensors/Code/Include/ROS2Sensors/ROS2SensorsEditorBus.h

@@ -0,0 +1,98 @@
+/*
+ * 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 <ROS2/Sensor/SensorConfiguration.h>
+#include <ROS2Sensors/Camera/CameraSensorConfiguration.h>
+#include <ROS2Sensors/Imu/ImuSensorConfiguration.h>
+#include <ROS2Sensors/Lidar/LidarSensorConfiguration.h>
+#include <ROS2Sensors/ROS2SensorsTypeIds.h>
+
+#include <AzCore/Component/Component.h>
+#include <AzCore/EBus/EBus.h>
+#include <AzCore/Interface/Interface.h>
+
+namespace ROS2Sensors
+{
+    //! Interface for creating ROS2 sensor components.
+    //! This interface provides methods to create various types of ROS2 sensor components, such as GNSS, Camera, IMU, Lidar, and Odometry
+    //! sensors. It is intended to be used by external tools that create entities, e.g., when importing robots from SDF, URDF, or OpenUSD.
+    class ROS2SensorsEditorRequests
+    {
+    public:
+        AZ_RTTI(ROS2SensorsEditorRequests, ROS2SensorsEditorRequestsTypeId);
+        virtual ~ROS2SensorsEditorRequests() = default;
+
+        //! Create a new ROS2 GNSS sensor component.
+        //! @param entity The entity to which the sensor component will be added.
+        //! @param sensorConfiguration The general configuration for the sensor.
+        //! @param gnssConfiguration The specific configuration parameters for the GNSS sensor.
+        //! @return A pointer to the newly created AZ::Component representing the GNSS sensor (or nullptr if failed).
+        virtual AZ::Component* CreateROS2GnssSensorComponent(AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration) = 0;
+
+        //! Create a new ROS2 Camera sensor component.
+        //! @param entity The entity to which the sensor component will be added.
+        //! @param sensorConfiguration The general configuration for the sensor.
+        //! @param cameraConfiguration The specific configuration parameters for the Camera sensor.
+        //! @return A pointer to the newly created AZ::Component representing the Camera sensor (or nullptr if failed).
+        virtual AZ::Component* CreateROS2CameraSensorComponent(
+            AZ::Entity& entity,
+            const ROS2::SensorConfiguration& sensorConfiguration,
+            const CameraSensorConfiguration& cameraConfiguration) = 0;
+
+        //! Create a new ROS2 IMU sensor component.
+        //! @param entity The entity to which the sensor component will be added.
+        //! @param sensorConfiguration The general configuration for the sensor.
+        //! @param imuConfiguration The specific configuration parameters for the IMU sensor.
+        //! @return A pointer to the newly created AZ::Component representing the IMU sensor (or nullptr if failed).
+        virtual AZ::Component* CreateROS2ImuSensorComponent(
+            AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration, const ImuSensorConfiguration& imuConfiguration) = 0;
+
+        //! Create a new ROS2 Lidar sensor component.
+        //! @param entity The entity to which the sensor component will be added.
+        //! @param sensorConfiguration The general configuration for the sensor.
+        //! @param lidarConfiguration The specific configuration parameters for the Lidar sensor.
+        //! @return A pointer to the newly created AZ::Component representing the Lidar sensor (or nullptr if failed).
+        virtual AZ::Component* CreateROS2LidarSensorComponent(
+            AZ::Entity& entity,
+            const ROS2::SensorConfiguration& sensorConfiguration,
+            const LidarSensorConfiguration& lidarConfiguration) = 0;
+
+        //! Create a new ROS2 2D Lidar sensor component.
+        //! @param entity The entity to which the sensor component will be added.
+        //! @param sensorConfiguration The general configuration for the sensor.
+        //! @param lidar2DConfiguration The specific configuration parameters for the 2D Lidar sensor.
+        //! @return A pointer to the newly created AZ::Component representing the 2D Lidar sensor (or nullptr if failed).
+        virtual AZ::Component* CreateROS2Lidar2DSensorComponent(
+            AZ::Entity& entity,
+            const ROS2::SensorConfiguration& sensorConfiguration,
+            const LidarSensorConfiguration& lidar2DConfiguration) = 0;
+
+        //! Create a new ROS2 Odometry sensor component.
+        //! @param entity The entity to which the sensor component will be added.
+        //! @param sensorConfiguration The general configuration for the sensor.
+        //! @return A pointer to the newly created AZ::Component representing the Odometry sensor (or nullptr if failed).
+        virtual AZ::Component* CreateROS2OdometrySensorComponent(
+            AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration) = 0;
+    };
+
+    class ROS2SensorsEditorBusTraits : public AZ::EBusTraits
+    {
+    public:
+        //////////////////////////////////////////////////////////////////////////
+        // EBusTraits overrides
+        static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+        static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
+        //////////////////////////////////////////////////////////////////////////
+    };
+
+    using ROS2SensorsEditorRequestBus = AZ::EBus<ROS2SensorsEditorRequests, ROS2SensorsEditorBusTraits>;
+    using ROS2SensorsEditorInterface = AZ::Interface<ROS2SensorsEditorRequests>;
+
+} // namespace ROS2Sensors

+ 4 - 0
Gems/ROS2Sensors/Code/Include/ROS2Sensors/ROS2SensorsTypeIds.h

@@ -21,6 +21,9 @@ namespace ROS2Sensors
     // so they use the Same TypeId
     inline constexpr const char* ROS2SensorsEditorModuleTypeId = ROS2SensorsModuleTypeId;
 
+    // Editor Interface TypeIds
+    inline constexpr const char* ROS2SensorsEditorRequestsTypeId = "{ACFDC553-B7E3-475C-91A3-26AB01C012AF}";
+
     // System Sensor Components TypeIds
     inline constexpr const char* ROS2SystemCameraComponentTypeId = "{B4665D39-78FD-40DE-8518-2F6BD345A831}";
     inline constexpr const char* ROS2EditorCameraSystemComponentTypeId = "{407F51C0-92C9-11EE-B9D1-0242AC120002}";
@@ -43,6 +46,7 @@ namespace ROS2Sensors
 
     // Sensor Components TypeIds
     inline constexpr const char* ROS2CameraSensorComponentTypeId = "{3C6B8AE6-9721-4639-B8F9-D8D28FD7A071}";
+    inline constexpr const char* ROS2CameraSensorEditorComponentTypeId = "{3C2A86B2-AD58-4BF1-A5EF-71E0F94A2B42}";
     inline constexpr const char* ROS2ContactSensorComponentTypeId = "{91272E66-C9F1-4AA2-A9D5-98EAA4EF4E9A}";
     inline constexpr const char* ROS2GNSSSensorComponentTypeId = "{55B4A299-7FA3-496A-88F0-764C75B0E9A7}";
     inline constexpr const char* ROS2ImuSensorComponentTypeId = "{502A955E-7742-4E23-AD77-5E4063739DCA}";

+ 0 - 21
Gems/ROS2Sensors/Code/Source/Camera/CameraConstants.h

@@ -1,21 +0,0 @@
-/*
- * 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
-
-namespace ROS2Sensors
-{
-    namespace CameraConstants
-    {
-        inline constexpr char ImageMessageType[] = "sensor_msgs::msg::Image";
-        inline constexpr char DepthImageConfig[] = "Depth Image";
-        inline constexpr char ColorImageConfig[] = "Color Image";
-        inline constexpr char DepthInfoConfig[] = "Depth Camera Info";
-        inline constexpr char ColorInfoConfig[] = "Color Camera Info";
-        inline constexpr char CameraInfoMessageType[] = "sensor_msgs::msg::CameraInfo";
-    } // namespace CameraConstants
-} // namespace ROS2Sensors

+ 0 - 1
Gems/ROS2Sensors/Code/Source/Camera/CameraPublishers.cpp

@@ -7,7 +7,6 @@
  */
 
 #include "CameraPublishers.h"
-#include "CameraConstants.h"
 #include "CameraSensor.h"
 #include <ROS2/Communication/TopicConfiguration.h>
 #include <ROS2/ROS2Bus.h>

+ 0 - 1
Gems/ROS2Sensors/Code/Source/Camera/ROS2CameraSensorEditorComponent.cpp

@@ -7,7 +7,6 @@
  */
 
 #include "ROS2CameraSensorEditorComponent.h"
-#include "CameraConstants.h"
 #include "CameraUtilities.h"
 #include "ROS2CameraSensorComponent.h"
 #include <AzCore/Component/TransformBus.h>

+ 2 - 1
Gems/ROS2Sensors/Code/Source/Camera/ROS2CameraSensorEditorComponent.h

@@ -17,6 +17,7 @@
 #include <ROS2/Sensor/SensorConfiguration.h>
 #include <ROS2Sensors/Camera/CameraConfigurationRequestBus.h>
 #include <ROS2Sensors/Camera/CameraSensorConfiguration.h>
+#include <ROS2Sensors/ROS2SensorsTypeIds.h>
 
 namespace ROS2Sensors
 {
@@ -33,7 +34,7 @@ namespace ROS2Sensors
         ROS2CameraSensorEditorComponent(
             const ROS2::SensorConfiguration& sensorConfiguration, const CameraSensorConfiguration& cameraConfiguration);
         ~ROS2CameraSensorEditorComponent() override = default;
-        AZ_EDITOR_COMPONENT(ROS2CameraSensorEditorComponent, "{3C2A86B2-AD58-4BF1-A5EF-71E0F94A2B42}");
+        AZ_EDITOR_COMPONENT(ROS2CameraSensorEditorComponent, ROS2CameraSensorEditorComponentTypeId);
         static void Reflect(AZ::ReflectContext* context);
         static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
         static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);

+ 0 - 14
Gems/ROS2Sensors/Code/Source/Lidar/LidarRegistrarSystemComponent.cpp

@@ -111,18 +111,4 @@ namespace ROS2Sensors
 
         return nullptr;
     }
-
-    AZStd::string Details::GetDefaultLidarSystem()
-    {
-        const auto& lidarInterface = LidarRegistrarInterface::Get();
-        AZ_Assert(lidarInterface, "LidarRegistrarInterface is not registered.");
-        const auto& lidarSystemList = lidarInterface->GetRegisteredLidarSystems();
-        if (lidarSystemList.empty())
-        {
-            AZ_Warning("ROS2LidarSensorComponent", false, "No LIDAR system for the sensor to use.");
-            return {};
-        }
-        return lidarSystemList.front();
-    }
-
 } // namespace ROS2Sensors

+ 0 - 6
Gems/ROS2Sensors/Code/Source/Lidar/LidarRegistrarSystemComponent.h

@@ -46,10 +46,4 @@ namespace ROS2Sensors
         LidarSystem m_physxLidarSystem;
         AZStd::unordered_map<AZ::Crc32, LidarSystemMetaData> m_registeredLidarSystems;
     };
-
-    namespace Details
-    {
-        AZStd::string GetDefaultLidarSystem();
-    } // namespace Details
-
 } // namespace ROS2Sensors

+ 18 - 2
Gems/ROS2Sensors/Code/Source/Lidar/LidarSensorConfiguration.cpp

@@ -6,7 +6,6 @@
  *
  */
 
-#include "Lidar/LidarRegistrarSystemComponent.h"
 #include <AzCore/Serialization/EditContext.h>
 #include <AzCore/Serialization/EditContextConstants.inl>
 #include <ROS2Sensors/Lidar/LidarSensorConfiguration.h>
@@ -94,7 +93,7 @@ namespace ROS2Sensors
     {
         if (m_lidarSystem.empty())
         {
-            m_lidarSystem = Details::GetDefaultLidarSystem();
+            m_lidarSystem = GetDefaultLidarSystem();
         }
         const auto* lidarMetaData = LidarRegistrarInterface::Get()->GetLidarSystemMetaData(m_lidarSystem);
         AZ_Warning("LidarSensorConfiguration", lidarMetaData, "No metadata for \"%s\"", m_lidarSystem.c_str());
@@ -186,4 +185,21 @@ namespace ROS2Sensors
     {
         m_lidarParameters.m_showNoiseConfig = m_lidarSystemFeatures & LidarSystemFeatures::Noise;
     }
+
+    AZStd::string LidarSensorConfiguration::GetDefaultLidarSystem()
+    {
+        const auto* lidarInterface = LidarRegistrarInterface::Get();
+        AZ_Assert(lidarInterface, "LidarRegistrarInterface is not registered.");
+        if (lidarInterface)
+        {
+            const auto& lidarSystemList = lidarInterface->GetRegisteredLidarSystems();
+            if (!lidarSystemList.empty())
+            {
+                return lidarSystemList.front();
+            }
+        }
+
+        AZ_Warning("ROS2LidarSensorComponent", false, "No LIDAR system for the sensor to use.");
+        return {};
+    }
 } // namespace ROS2Sensors

+ 57 - 3
Gems/ROS2Sensors/Code/Source/Tools/ROS2SensorsEditorSystemComponent.cpp

@@ -8,9 +8,14 @@
 
 #include "ROS2SensorsEditorSystemComponent.h"
 #include <AzCore/Serialization/SerializeContext.h>
-
 #include <ROS2Sensors/ROS2SensorsTypeIds.h>
 
+#include <Camera/ROS2CameraSensorEditorComponent.h>
+#include <GNSS/ROS2GNSSSensorComponent.h>
+#include <Imu/ROS2ImuSensorComponent.h>
+#include <Lidar/ROS2Lidar2DSensorComponent.h>
+#include <Lidar/ROS2LidarSensorComponent.h>
+
 namespace ROS2Sensors
 {
     AZ_COMPONENT_IMPL(
@@ -24,9 +29,21 @@ namespace ROS2Sensors
         }
     }
 
-    ROS2SensorsEditorSystemComponent::ROS2SensorsEditorSystemComponent() = default;
+    ROS2SensorsEditorSystemComponent::ROS2SensorsEditorSystemComponent()
+    {
+        if (ROS2SensorsEditorInterface::Get() == nullptr)
+        {
+            ROS2SensorsEditorInterface::Register(this);
+        }
+    }
 
-    ROS2SensorsEditorSystemComponent::~ROS2SensorsEditorSystemComponent() = default;
+    ROS2SensorsEditorSystemComponent::~ROS2SensorsEditorSystemComponent()
+    {
+        if (ROS2SensorsEditorInterface::Get() == this)
+        {
+            ROS2SensorsEditorInterface::Unregister(this);
+        }
+    }
 
     void ROS2SensorsEditorSystemComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
     {
@@ -54,12 +71,49 @@ namespace ROS2Sensors
     {
         ROS2SensorsSystemComponent::Activate();
         AzToolsFramework::EditorEvents::Bus::Handler::BusConnect();
+        ROS2SensorsEditorRequestBus::Handler::BusConnect();
     }
 
     void ROS2SensorsEditorSystemComponent::Deactivate()
     {
+        ROS2SensorsEditorRequestBus::Handler::BusDisconnect();
         AzToolsFramework::EditorEvents::Bus::Handler::BusDisconnect();
         ROS2SensorsSystemComponent::Deactivate();
     }
 
+    AZ::Component* ROS2SensorsEditorSystemComponent::CreateROS2GnssSensorComponent(
+        AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration)
+    {
+        return CreateComponent<ROS2GNSSSensorComponent>(entity, sensorConfiguration);
+    };
+
+    AZ::Component* ROS2SensorsEditorSystemComponent::CreateROS2CameraSensorComponent(
+        AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration, const CameraSensorConfiguration& cameraConfiguration)
+    {
+        return CreateComponent<ROS2CameraSensorEditorComponent>(entity, sensorConfiguration, cameraConfiguration);
+    };
+
+    AZ::Component* ROS2SensorsEditorSystemComponent::CreateROS2ImuSensorComponent(
+        AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration, const ImuSensorConfiguration& imuConfiguration)
+    {
+        return CreateComponent<ROS2ImuSensorComponent>(entity, sensorConfiguration, imuConfiguration);
+    };
+
+    AZ::Component* ROS2SensorsEditorSystemComponent::CreateROS2LidarSensorComponent(
+        AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration, const LidarSensorConfiguration& lidarConfiguration)
+    {
+        return CreateComponent<ROS2LidarSensorComponent>(entity, sensorConfiguration, lidarConfiguration);
+    };
+
+    AZ::Component* ROS2SensorsEditorSystemComponent::CreateROS2Lidar2DSensorComponent(
+        AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration, const LidarSensorConfiguration& lidar2DConfiguration)
+    {
+        return CreateComponent<ROS2Lidar2DSensorComponent>(entity, sensorConfiguration, lidar2DConfiguration);
+    };
+
+    AZ::Component* ROS2SensorsEditorSystemComponent::CreateROS2OdometrySensorComponent(
+        AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration)
+    {
+        return nullptr;
+    };
 } // namespace ROS2Sensors

+ 69 - 1
Gems/ROS2Sensors/Code/Source/Tools/ROS2SensorsEditorSystemComponent.h

@@ -8,9 +8,13 @@
 
 #pragma once
 
+#include <AzCore/Component/Component.h>
+#include <AzCore/Component/Entity.h>
 #include <AzToolsFramework/API/ToolsApplicationAPI.h>
-
+#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
+#include <AzToolsFramework/ToolsComponents/GenericComponentWrapper.h>
 #include <Clients/ROS2SensorsSystemComponent.h>
+#include <ROS2Sensors/ROS2SensorsEditorBus.h>
 
 namespace ROS2Sensors
 {
@@ -18,6 +22,7 @@ namespace ROS2Sensors
     class ROS2SensorsEditorSystemComponent
         : public ROS2SensorsSystemComponent
         , protected AzToolsFramework::EditorEvents::Bus::Handler
+        , protected ROS2SensorsEditorRequestBus::Handler
     {
         using BaseSystemComponent = ROS2SensorsSystemComponent;
 
@@ -29,6 +34,29 @@ namespace ROS2Sensors
         ROS2SensorsEditorSystemComponent();
         ~ROS2SensorsEditorSystemComponent();
 
+    protected:
+        ////////////////////////////////////////////////////////////////////////
+        // ROS2SensorsEditorRequestBus interface implementation
+        AZ::Component* CreateROS2GnssSensorComponent(AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration) override;
+        AZ::Component* CreateROS2CameraSensorComponent(
+            AZ::Entity& entity,
+            const ROS2::SensorConfiguration& sensorConfiguration,
+            const CameraSensorConfiguration& cameraConfiguration) override;
+        AZ::Component* CreateROS2ImuSensorComponent(
+            AZ::Entity& entity,
+            const ROS2::SensorConfiguration& sensorConfiguration,
+            const ImuSensorConfiguration& imuConfiguration) override;
+        AZ::Component* CreateROS2LidarSensorComponent(
+            AZ::Entity& entity,
+            const ROS2::SensorConfiguration& sensorConfiguration,
+            const LidarSensorConfiguration& lidarConfiguration) override;
+        AZ::Component* CreateROS2Lidar2DSensorComponent(
+            AZ::Entity& entity,
+            const ROS2::SensorConfiguration& sensorConfiguration,
+            const LidarSensorConfiguration& lidar2DConfiguration) override;
+        AZ::Component* CreateROS2OdometrySensorComponent(AZ::Entity& entity, const ROS2::SensorConfiguration& sensorConfiguration) override;
+        ////////////////////////////////////////////////////////////////////////
+
     private:
         static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided);
         static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
@@ -38,5 +66,45 @@ namespace ROS2Sensors
         // AZ::Component
         void Activate() override;
         void Deactivate() override;
+
+        //! Create a component and attach the component to the entity.
+        //! This method ensures that game components are wrapped into GenericComponentWrapper.
+        //! @param entity entity to which the new component is added
+        //! @param args constructor arguments used to create the new component
+        //! @return A pointer to the component. Returns a null pointer if the component could not be created.
+        template<class ComponentType, typename... Args>
+        AZ::Component* CreateComponent(AZ::Entity& entity, Args&&... args)
+        {
+            // Do not create a component if the same type is already added.
+            if (entity.FindComponent<ComponentType>())
+            {
+                return nullptr;
+            }
+
+            // Create component.
+            // If it's not an "editor component" then wrap it in a GenericComponentWrapper.
+            AZ::Component* component = nullptr;
+            if (AZ::GetRttiHelper<ComponentType>() &&
+                AZ::GetRttiHelper<ComponentType>()->IsTypeOf(AzToolsFramework::Components::EditorComponentBase::RTTI_Type()))
+            {
+                component = aznew ComponentType(AZStd::forward<Args>(args)...);
+            }
+            else
+            {
+                AZ::Component* gameComponent = aznew ComponentType(AZStd::forward<Args>(args)...);
+                component = aznew AzToolsFramework::Components::GenericComponentWrapper(gameComponent);
+            }
+
+            AZ_Assert(component, "Failed to create component: %s", AZ::AzTypeInfo<ComponentType>::Name());
+            if (component)
+            {
+                if (!entity.IsComponentReadyToAdd(component) || !entity.AddComponent(component))
+                {
+                    delete component;
+                    component = nullptr;
+                }
+            }
+            return component;
+        }
     };
 } // namespace ROS2Sensors

+ 1 - 0
Gems/ROS2Sensors/Code/ros2sensors_editor_api_files.cmake

@@ -7,4 +7,5 @@
 #
 
 set(FILES
+    Include/ROS2Sensors/ROS2SensorsEditorBus.h
 )

+ 2 - 0
Gems/ROS2Sensors/Code/ros2sensors_lidar_shared_files.cmake

@@ -7,6 +7,8 @@
 #
 
 set(FILES
+    Source/Lidar/LidarSensorConfiguration.cpp
+    Source/Lidar/LidarTemplateUtils.cpp
     Source/Lidar/RaycastResults.cpp
     Source/Lidar/SegmentationClassConfiguration.cpp
     Source/Lidar/SegmentationUtils.cpp

+ 0 - 3
Gems/ROS2Sensors/Code/ros2sensors_private_files.cmake

@@ -13,7 +13,6 @@ set(FILES
     Source/Clients/ROS2SensorsSystemComponent.h
     Source/Camera/PostProcessing/ROS2ImageEncodingConversionComponent.cpp
     Source/Camera/PostProcessing/ROS2ImageEncodingConversionComponent.h
-    Source/Camera/CameraConstants.h
     Source/Camera/CameraPublishers.cpp
     Source/Camera/CameraPublishers.h
     Source/Camera/CameraSensor.cpp
@@ -42,11 +41,9 @@ set(FILES
     Source/Lidar/LidarRaycaster.h
     Source/Lidar/LidarRegistrarSystemComponent.cpp
     Source/Lidar/LidarRegistrarSystemComponent.h
-    Source/Lidar/LidarSensorConfiguration.cpp
     Source/Lidar/LidarSystem.cpp
     Source/Lidar/LidarSystem.h
     Source/Lidar/LidarTemplate.cpp
-    Source/Lidar/LidarTemplateUtils.cpp
     Source/Lidar/PointCloudMessageBuilder.cpp
     Source/Lidar/PointCloudMessageBuilder.h
     Source/Lidar/ROS2Lidar2DSensorComponent.cpp