Przeglądaj źródła

Split ROS2CameraSensorComponent to Game and Editor component. (#103)

* Split ROS2CameraSensorComponent to Game and Editor component.

The ROS2CameraSensorEditorComponent has Editor-only features:
 - visualization of frustrum.

Signed-off-by: Michał Pełka <[email protected]>

* Adjust to review

Signed-off-by: Michał Pełka <[email protected]>

* Adjusted to review

Signed-off-by: Michał Pełka <[email protected]>

---------

Signed-off-by: Michał Pełka <[email protected]>
Michał Pełka 2 lat temu
rodzic
commit
322698dc99

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

@@ -113,7 +113,6 @@ if(PAL_TRAIT_BUILD_HOST_TOOLS)
         NAME ${gem_name}.Editor GEM_MODULE
         NAMESPACE Gem
         FILES_CMAKE
-            ros2_editor_files.cmake
             ros2_editor_shared_files.cmake
         PLATFORM_INCLUDE_FILES
             ${CMAKE_CURRENT_LIST_DIR}/Platform/Common/${PAL_TRAIT_COMPILER_ID}/ros2_static_editor_${PAL_TRAIT_COMPILER_ID_LOWERCASE}.cmake

+ 32 - 58
Gems/ROS2/Code/Source/Camera/ROS2CameraSensorComponent.cpp

@@ -21,42 +21,20 @@
 
 namespace ROS2
 {
-    namespace Internal
+    ROS2CameraSensorComponent::ROS2CameraSensorComponent(
+        const SensorConfiguration& sensorConfiguration,
+        float verticalFieldOfViewDeg,
+        int width,
+        int height,
+        bool colorCamera,
+        bool depthCamera)
+        : m_verticalFieldOfViewDeg(verticalFieldOfViewDeg)
+        , m_width(width)
+        , m_height(height)
+        , m_colorCamera(colorCamera)
+        , m_depthCamera(depthCamera)
     {
-        const char* kImageMessageType = "sensor_msgs::msg::Image";
-        const char* kDepthImageConfig = "Depth Image";
-        const char* kColorImageConfig = "Color Image";
-        const char* kInfoConfig = "Camera Info";
-        const char* kCameraInfoMessageType = "sensor_msgs::msg::CameraInfo";
-
-        AZStd::pair<AZStd::string, TopicConfiguration> MakeTopicConfigurationPair(
-            const AZStd::string& topic, const AZStd::string& messageType, const AZStd::string& configName)
-        {
-            TopicConfiguration config;
-            config.m_topic = topic;
-            config.m_type = messageType;
-            return AZStd::make_pair(configName, config);
-        }
-
-        AZStd::string GetCameraNameFromFrame(const AZ::Entity* entity)
-        {
-            const auto* component = Utils::GetGameOrEditorComponent<ROS2FrameComponent>(entity);
-            AZStd::string cameraName = component->GetFrameID();
-            AZStd::replace(cameraName.begin(), cameraName.end(), '/', '_');
-            return cameraName;
-        }
-
-    } // namespace Internal
-
-    ROS2CameraSensorComponent::ROS2CameraSensorComponent()
-    {
-        m_sensorConfiguration.m_frequency = 10;
-        m_sensorConfiguration.m_publishersConfigurations.insert(
-            Internal::MakeTopicConfigurationPair("camera_image_color", Internal::kImageMessageType, Internal::kColorImageConfig));
-        m_sensorConfiguration.m_publishersConfigurations.insert(
-            Internal::MakeTopicConfigurationPair("camera_image_depth", Internal::kImageMessageType, Internal::kDepthImageConfig));
-        m_sensorConfiguration.m_publishersConfigurations.insert(
-            Internal::MakeTopicConfigurationPair("camera_info", Internal::kCameraInfoMessageType, Internal::kInfoConfig));
+        m_sensorConfiguration = sensorConfiguration;
     }
 
     void ROS2CameraSensorComponent::Reflect(AZ::ReflectContext* context)
@@ -66,29 +44,11 @@ namespace ROS2
         {
             serialize->Class<ROS2CameraSensorComponent, ROS2SensorComponent>()
                 ->Version(3)
-                ->Field("VerticalFieldOfViewDeg", &ROS2CameraSensorComponent::m_VerticalFieldOfViewDeg)
+                ->Field("VerticalFieldOfViewDeg", &ROS2CameraSensorComponent::m_verticalFieldOfViewDeg)
                 ->Field("Width", &ROS2CameraSensorComponent::m_width)
                 ->Field("Height", &ROS2CameraSensorComponent::m_height)
                 ->Field("Depth", &ROS2CameraSensorComponent::m_depthCamera)
                 ->Field("Color", &ROS2CameraSensorComponent::m_colorCamera);
-
-            AZ::EditContext* ec = serialize->GetEditContext();
-            if (ec)
-            {
-                ec->Class<ROS2CameraSensorComponent>("ROS2 Camera Sensor", "[Camera component]")
-                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
-                    ->Attribute(AZ::Edit::Attributes::Category, "ROS2")
-                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
-                    ->DataElement(
-                        AZ::Edit::UIHandlers::Default,
-                        &ROS2CameraSensorComponent::m_VerticalFieldOfViewDeg,
-                        "Vertical field of view",
-                        "Camera's vertical (y axis) field of view in degrees.")
-                    ->DataElement(AZ::Edit::UIHandlers::Default, &ROS2CameraSensorComponent::m_width, "Image width", "Image width")
-                    ->DataElement(AZ::Edit::UIHandlers::Default, &ROS2CameraSensorComponent::m_height, "Image height", "Image height")
-                    ->DataElement(AZ::Edit::UIHandlers::Default, &ROS2CameraSensorComponent::m_colorCamera, "Color Camera", "Color Camera")
-                    ->DataElement(AZ::Edit::UIHandlers::Default, &ROS2CameraSensorComponent::m_depthCamera, "Depth Camera", "Depth Camera");
-            }
         }
     }
 
@@ -98,7 +58,7 @@ namespace ROS2
 
         auto ros2Node = ROS2Interface::Get()->GetNode();
 
-        const auto cameraInfoPublisherConfig = m_sensorConfiguration.m_publishersConfigurations[Internal::kInfoConfig];
+        const auto cameraInfoPublisherConfig = m_sensorConfiguration.m_publishersConfigurations[CameraConstants::InfoConfig];
         AZStd::string cameraInfoFullTopic = ROS2Names::GetNamespacedName(GetNamespace(), cameraInfoPublisherConfig.m_topic);
         AZ_TracePrintf("ROS2", "Creating publisher for camera info on topic %s\n", cameraInfoFullTopic.data());
 
@@ -106,11 +66,11 @@ namespace ROS2
             ros2Node->create_publisher<sensor_msgs::msg::CameraInfo>(cameraInfoFullTopic.data(), cameraInfoPublisherConfig.GetQoS());
 
         const CameraSensorDescription description{
-            Internal::GetCameraNameFromFrame(GetEntity()), m_VerticalFieldOfViewDeg, m_width, m_height
+            GetCameraNameFromFrame(GetEntity()), m_verticalFieldOfViewDeg, m_width, m_height
         };
         if (m_colorCamera)
         {
-            const auto cameraImagePublisherConfig = m_sensorConfiguration.m_publishersConfigurations[Internal::kColorImageConfig];
+            const auto cameraImagePublisherConfig = m_sensorConfiguration.m_publishersConfigurations[CameraConstants::ColorImageConfig];
             AZStd::string cameraImageFullTopic = ROS2Names::GetNamespacedName(GetNamespace(), cameraImagePublisherConfig.m_topic);
             auto publisher =
                 ros2Node->create_publisher<sensor_msgs::msg::Image>(cameraImageFullTopic.data(), cameraImagePublisherConfig.GetQoS());
@@ -118,7 +78,7 @@ namespace ROS2
         }
         if (m_depthCamera)
         {
-            const auto cameraImagePublisherConfig = m_sensorConfiguration.m_publishersConfigurations[Internal::kDepthImageConfig];
+            const auto cameraImagePublisherConfig = m_sensorConfiguration.m_publishersConfigurations[CameraConstants::DepthImageConfig];
             AZStd::string cameraImageFullTopic = ROS2Names::GetNamespacedName(GetNamespace(), cameraImagePublisherConfig.m_topic);
             auto publisher =
                 ros2Node->create_publisher<sensor_msgs::msg::Image>(cameraImageFullTopic.data(), cameraImagePublisherConfig.GetQoS());
@@ -163,4 +123,18 @@ namespace ROS2
             sensor->RequestMessagePublication(publisher, transform, ros_header);
         }
     }
+
+    AZStd::string ROS2CameraSensorComponent::GetCameraNameFromFrame(const AZ::Entity* entity) const
+    {
+        const auto* component = Utils::GetGameOrEditorComponent<ROS2FrameComponent>(entity);
+        AZ_Assert(component, "Entity %s has no ROS2CameraSensorComponent", entity->GetName().c_str());
+        if (component)
+        {
+            AZStd::string cameraName = component->GetFrameID();
+            AZStd::replace(cameraName.begin(), cameraName.end(), '/', '_');
+            return cameraName;
+        }
+        return AZStd::string{};
+
+    }
 } // namespace ROS2

+ 26 - 3
Gems/ROS2/Code/Source/Camera/ROS2CameraSensorComponent.h

@@ -22,6 +22,15 @@
 
 namespace ROS2
 {
+    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 InfoConfig[] = "Camera Info";
+        inline constexpr char CameraInfoMessageType[] = "sensor_msgs::msg::CameraInfo";
+    } // namespace CameraConstants
+
     //! ROS2 Camera sensor component class
     //! Allows turning an entity into a camera sensor
     //! Can be parametrized with following values:
@@ -32,7 +41,16 @@ namespace ROS2
     class ROS2CameraSensorComponent : public ROS2SensorComponent
     {
     public:
-        ROS2CameraSensorComponent();
+        ROS2CameraSensorComponent() = default;
+
+        ROS2CameraSensorComponent(
+            const SensorConfiguration& sensorConfiguration,
+            float verticalFieldOfViewDeg,
+            int width,
+            int height,
+            bool colorCamera,
+            bool depthCamera);
+
         ~ROS2CameraSensorComponent() override = default;
         AZ_COMPONENT(ROS2CameraSensorComponent, "{3C6B8AE6-9721-4639-B8F9-D8D28FD7A071}", ROS2SensorComponent);
         static void Reflect(AZ::ReflectContext* context);
@@ -50,7 +68,7 @@ namespace ROS2
         //! Type that combines pointer to ROS2 publisher and CameraSensor
         using PublisherSensorPtrPair = AZStd::pair<ImagePublisherPtrType, AZStd::shared_ptr<CameraSensor>>;
 
-        //! Helper to construct a PublisherSensorPtrPair with a pointer to ROS2 publisher and intrinsic calibration
+        //! Helper to construct a PublisherSensorPtrPair with a pointer to ROS2 publisher and intrinsic calibration.
         //! @tparam CameraType type of camera sensor (eg 'CameraColorSensor')
         //! @param publisher pointer to ROS2 image publisher
         //! @param description CameraSensorDescription with intrinsic calibration
@@ -61,7 +79,12 @@ namespace ROS2
             return { publisher, AZStd::make_shared<CameraType>(description) };
         }
 
-        float m_VerticalFieldOfViewDeg = 90.0f;
+        //! Retrieve camera name from ROS2FrameComponent's FrameID.
+        //! @param entity pointer entity that has ROS2FrameComponent
+        //! @returns FrameID from ROS2FrameComponent
+        AZStd::string GetCameraNameFromFrame(const AZ::Entity* entity) const;
+
+        float m_verticalFieldOfViewDeg = 90.0f;
         int m_width = 640;
         int m_height = 480;
         bool m_colorCamera = true;

+ 186 - 0
Gems/ROS2/Code/Source/Camera/ROS2CameraSensorEditorComponent.cpp

@@ -0,0 +1,186 @@
+/*
+ * 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
+ *
+ */
+
+#include "ROS2CameraSensorEditorComponent.h"
+#include "ROS2CameraSensorComponent.h"
+#include <AzCore/Component/TransformBus.h>
+#include <ROS2/Frame/ROS2FrameComponent.h>
+
+namespace ROS2
+{
+    ROS2CameraSensorEditorComponent::ROS2CameraSensorEditorComponent()
+    {
+        m_sensorConfiguration.m_frequency = 10;
+        m_sensorConfiguration.m_publishersConfigurations.insert(
+            MakeTopicConfigurationPair("camera_image_color", CameraConstants::ImageMessageType, CameraConstants::ColorImageConfig));
+        m_sensorConfiguration.m_publishersConfigurations.insert(
+            MakeTopicConfigurationPair("camera_image_depth", CameraConstants::ImageMessageType, CameraConstants::DepthImageConfig));
+        m_sensorConfiguration.m_publishersConfigurations.insert(
+            MakeTopicConfigurationPair("camera_info", CameraConstants::CameraInfoMessageType, CameraConstants::InfoConfig));
+    }
+
+    void ROS2CameraSensorEditorComponent::Reflect(AZ::ReflectContext* context)
+    {
+        if (auto* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serialize->Class<ROS2CameraSensorEditorComponent, AzToolsFramework::Components::EditorComponentBase>()
+                ->Version(4)
+                ->Field("VerticalFieldOfViewDeg", &ROS2CameraSensorEditorComponent::m_VerticalFieldOfViewDeg)
+                ->Field("Width", &ROS2CameraSensorEditorComponent::m_width)
+                ->Field("Height", &ROS2CameraSensorEditorComponent::m_height)
+                ->Field("Depth", &ROS2CameraSensorEditorComponent::m_depthCamera)
+                ->Field("Color", &ROS2CameraSensorEditorComponent::m_colorCamera)
+                ->Field("SensorConfig", &ROS2CameraSensorEditorComponent::m_sensorConfiguration);
+
+            if (AZ::EditContext* editContext = serialize->GetEditContext())
+            {
+                editContext->Class<ROS2CameraSensorEditorComponent>("ROS2 Camera Sensor", "[Camera component]")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
+                    ->Attribute(AZ::Edit::Attributes::Category, "ROS2")
+                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
+                    ->DataElement(
+                        AZ::Edit::UIHandlers::Default,
+                        &ROS2CameraSensorEditorComponent::m_sensorConfiguration,
+                        "Sensor configuration",
+                        "Sensor configuration")
+                    ->DataElement(
+                        AZ::Edit::UIHandlers::Default,
+                        &ROS2CameraSensorEditorComponent::m_VerticalFieldOfViewDeg,
+                        "Vertical field of view",
+                        "Camera's vertical (y axis) field of view in degrees.")
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &ROS2CameraSensorEditorComponent::m_width, "Image width", "Image width")
+                    ->DataElement(AZ::Edit::UIHandlers::Default, &ROS2CameraSensorEditorComponent::m_height, "Image height", "Image height")
+                    ->DataElement(
+                        AZ::Edit::UIHandlers::Default, &ROS2CameraSensorEditorComponent::m_colorCamera, "Color Camera", "Color Camera")
+                    ->DataElement(
+                        AZ::Edit::UIHandlers::Default, &ROS2CameraSensorEditorComponent::m_depthCamera, "Depth Camera", "Depth Camera");
+            }
+        }
+    }
+
+    void ROS2CameraSensorEditorComponent::Activate()
+    {
+        AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(this->GetEntityId());
+        AzToolsFramework::Components::EditorComponentBase::Activate();
+    }
+
+    void ROS2CameraSensorEditorComponent::Deactivate()
+    {
+        AzToolsFramework::Components::EditorComponentBase::Deactivate();
+        AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect();
+    }
+
+    void ROS2CameraSensorEditorComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
+    {
+        required.push_back(AZ_CRC("ROS2Frame"));
+    }
+
+    void ROS2CameraSensorEditorComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
+    {
+        incompatible.push_back(AZ_CRC_CE("ROS2SensorCamera"));
+    }
+
+    void ROS2CameraSensorEditorComponent::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& required)
+    {
+        required.push_back(AZ_CRC_CE("ROS2SensorCamera"));
+    }
+
+    void ROS2CameraSensorEditorComponent::BuildGameEntity(AZ::Entity* gameEntity)
+    {
+        gameEntity->CreateComponent<ROS2::ROS2CameraSensorComponent>(
+            m_sensorConfiguration, m_VerticalFieldOfViewDeg, m_width, m_height, m_colorCamera, m_depthCamera);
+    }
+
+    void ROS2CameraSensorEditorComponent::DisplayEntityViewport(
+        [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay)
+    {
+        if (!m_sensorConfiguration.m_visualise)
+        {
+            return;
+        }
+        const AZ::u32 stateBefore = debugDisplay.GetState();
+        AZ::Transform transform = GetEntity()->GetTransform()->GetWorldTM();
+
+        // dimension of drawing
+        const float arrowRise = 1.1f;
+        const float arrowSize = 0.5f;
+        const float frustumScale = 0.1f;
+
+        transform.SetUniformScale(frustumScale);
+        debugDisplay.DepthTestOff();
+        const float ver = 0.5f * AZStd::tan((AZ::DegToRad(m_VerticalFieldOfViewDeg * 0.5f)));
+        const float hor = m_height * ver / m_width;
+
+        // frustum drawing
+        const AZ::Vector3 p1(-ver, -hor, 1.f);
+        const AZ::Vector3 p2(ver, -hor, 1.f);
+        const AZ::Vector3 p3(ver, hor, 1.f);
+        const AZ::Vector3 p4(-ver, hor, 1.f);
+        const AZ::Vector3 p0(0, 0, 0);
+        const AZ::Vector3 py(0.1, 0, 0);
+
+        const auto pt1 = transform.TransformPoint(p1);
+        const auto pt2 = transform.TransformPoint(p2);
+        const auto pt3 = transform.TransformPoint(p3);
+        const auto pt4 = transform.TransformPoint(p4);
+        const auto pt0 = transform.TransformPoint(p0);
+        const auto ptz = transform.TransformPoint(AZ::Vector3::CreateAxisZ(0.2f));
+        const auto pty = transform.TransformPoint(AZ::Vector3::CreateAxisY(0.2f));
+        const auto ptx = transform.TransformPoint(AZ::Vector3::CreateAxisX(0.2f));
+
+        debugDisplay.SetColor(AZ::Color(0.f, 1.f, 1.f, 1.f));
+        debugDisplay.SetLineWidth(1);
+        debugDisplay.DrawLine(pt1, pt2);
+        debugDisplay.DrawLine(pt2, pt3);
+        debugDisplay.DrawLine(pt3, pt4);
+        debugDisplay.DrawLine(pt4, pt1);
+        debugDisplay.DrawLine(pt1, pt0);
+        debugDisplay.DrawLine(pt2, pt0);
+        debugDisplay.DrawLine(pt3, pt0);
+        debugDisplay.DrawLine(pt4, pt0);
+
+        // up-arrow drawing
+        const AZ::Vector3 pa1(-arrowSize * ver, -arrowRise * hor, 1.f);
+        const AZ::Vector3 pa2(arrowSize * ver, -arrowRise * hor, 1.f);
+        const AZ::Vector3 pa3(0, (-arrowRise - arrowSize) * hor, 1.f);
+        const auto pat1 = transform.TransformPoint(pa1);
+        const auto pat2 = transform.TransformPoint(pa2);
+        const auto pat3 = transform.TransformPoint(pa3);
+
+        debugDisplay.SetColor(AZ::Color(0.f, 0.6f, 1.f, 1.f));
+        debugDisplay.SetLineWidth(1);
+        debugDisplay.DrawLine(pat1, pat2);
+        debugDisplay.DrawLine(pat2, pat3);
+        debugDisplay.DrawLine(pat3, pat1);
+
+        // coordinate system drawing
+        debugDisplay.SetColor(AZ::Color(1.f, 0.f, 0.f, 1.f));
+        debugDisplay.SetLineWidth(2);
+        debugDisplay.DrawLine(ptx, pt0);
+
+        debugDisplay.SetColor(AZ::Color(0.f, 1.f, 0.f, 1.f));
+        debugDisplay.SetLineWidth(2);
+        debugDisplay.DrawLine(pty, pt0);
+
+        debugDisplay.SetColor(AZ::Color(0.f, 0.f, 1.f, 1.f));
+        debugDisplay.SetLineWidth(2);
+        debugDisplay.DrawLine(ptz, pt0);
+
+        debugDisplay.SetState(stateBefore);
+    }
+
+    AZStd::pair<AZStd::string, TopicConfiguration> ROS2CameraSensorEditorComponent::MakeTopicConfigurationPair(
+        const AZStd::string& topic, const AZStd::string& messageType, const AZStd::string& configName) const
+    {
+        TopicConfiguration config;
+        config.m_topic = topic;
+        config.m_type = messageType;
+        return AZStd::make_pair(configName, config);
+    }
+
+} // namespace ROS2

+ 58 - 0
Gems/ROS2/Code/Source/Camera/ROS2CameraSensorEditorComponent.h

@@ -0,0 +1,58 @@
+/*
+ * 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/Component.h>
+#include <ROS2/Frame/NamespaceConfiguration.h>
+#include <ROS2/Frame/ROS2Transform.h>
+#include <ROS2/Sensor/SensorConfiguration.h>
+
+#include <AzToolsFramework/API/ComponentEntitySelectionBus.h>
+#include <AzToolsFramework/ToolsComponents/EditorComponentBase.h>
+
+#include "CameraSensor.h"
+
+namespace ROS2
+{
+    //! ROS2 Camera Editor sensor component class
+    //! Allows turning an entity into a camera sensor in Editor
+    //! Component draws camera frustrum in the Editor
+    class ROS2CameraSensorEditorComponent
+        : public AzToolsFramework::Components::EditorComponentBase
+        , protected AzFramework::EntityDebugDisplayEventBus::Handler
+    {
+    public:
+        ROS2CameraSensorEditorComponent();
+        ~ROS2CameraSensorEditorComponent() override = default;
+        AZ_EDITOR_COMPONENT(ROS2CameraSensorEditorComponent, "{3C2A86B2-AD58-4BF1-A5EF-71E0F94A2B42}");
+        static void Reflect(AZ::ReflectContext* context);
+        static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
+        static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible);
+        static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& required);
+
+        static void GetPr(AZ::ComponentDescriptor::DependencyArrayType& required);
+        void Activate() override;
+        void Deactivate() override;
+
+        //! AzToolsFramework::Components::EditorComponentBase override
+        void BuildGameEntity(AZ::Entity* gameEntity) override;
+
+    private:
+        // EntityDebugDisplayEventBus::Handler overrides
+        void DisplayEntityViewport(const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) override;
+
+        AZStd::pair<AZStd::string, TopicConfiguration> MakeTopicConfigurationPair(
+            const AZStd::string& topic, const AZStd::string& messageType, const AZStd::string& configName) const;
+        SensorConfiguration m_sensorConfiguration;
+        float m_VerticalFieldOfViewDeg = 90.0f;
+        int m_width = 640;
+        int m_height = 480;
+        bool m_colorCamera = true;
+        bool m_depthCamera = true;
+    };
+} // namespace ROS2

+ 2 - 0
Gems/ROS2/Code/Source/ROS2EditorModule.cpp

@@ -8,6 +8,7 @@
 #include <Lidar/LidarRegistrarEditorSystemComponent.h>
 #include <ROS2EditorSystemComponent.h>
 #include <ROS2ModuleInterface.h>
+#include <Camera/ROS2CameraSensorEditorComponent.h>
 #include <RobotImporter/ROS2RobotImporterEditorSystemComponent.h>
 
 namespace ROS2
@@ -30,6 +31,7 @@ namespace ROS2
                     ROS2EditorSystemComponent::CreateDescriptor(),
                     LidarRegistrarEditorSystemComponent::CreateDescriptor(),
                     ROS2RobotImporterEditorSystemComponent::CreateDescriptor(),
+                    ROS2CameraSensorEditorComponent::CreateDescriptor(),
                 });
         }
 

+ 0 - 1
Gems/ROS2/Code/Source/ROS2ModuleInterface.h

@@ -61,7 +61,6 @@ namespace ROS2
                   AckermannControlComponent::CreateDescriptor(),
                   RigidBodyTwistControlComponent::CreateDescriptor(),
                   SkidSteeringControlComponent::CreateDescriptor(),
-                  ROS2CameraSensorComponent::CreateDescriptor(),
                   ROS2SpawnerComponent::CreateDescriptor(),
                   ROS2SpawnPointComponent::CreateDescriptor(),
                   VehicleDynamics::AckermannVehicleModelComponent::CreateDescriptor(),

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

@@ -6,6 +6,8 @@
 set(FILES
     ../Assets/Editor/Images/Icons/Resources.qrc
     ../Assets/Editor/Images/Icons/ROS_import_icon.svg
+    Source/Camera/ROS2CameraSensorEditorComponent.cpp
+    Source/Camera/ROS2CameraSensorEditorComponent.h
     Source/Lidar/LidarRegistrarEditorSystemComponent.cpp
     Source/Lidar/LidarRegistrarEditorSystemComponent.h
     Source/RobotImporter/Pages/CheckAssetPage.cpp

+ 79 - 1
Gems/RosRobotSample/Assets/ROSbot.prefab

@@ -51,6 +51,83 @@
         }
     },
     "Entities": {
+        "Entity_[454274520747]": {
+            "Id": "Entity_[454274520747]",
+            "Name": "Entity1",
+            "Components": {
+                "Component_[10139607700692707664]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 10139607700692707664
+                },
+                "Component_[1383110072770318712]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 1383110072770318712
+                },
+                "Component_[1459662396467092780]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 1459662396467092780,
+                    "Parent Entity": "Entity_[7507839849146]",
+                    "Transform Data": {
+                        "Translate": [
+                            0.0,
+                            0.0,
+                            0.1079680398106575
+                        ]
+                    }
+                },
+                "Component_[14778984575904365834]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 14778984575904365834
+                },
+                "Component_[16777570562481809460]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 16777570562481809460
+                },
+                "Component_[2002554278096027045]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 2002554278096027045
+                },
+                "Component_[5063108489464047545]": {
+                    "$type": "GenericComponentWrapper",
+                    "Id": 5063108489464047545,
+                    "m_template": {
+                        "$type": "ROS2FrameComponent"
+                    }
+                },
+                "Component_[525588079965327013]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 525588079965327013
+                },
+                "Component_[6441665647641943511]": {
+                    "$type": "ROS2CameraSensorEditorComponent",
+                    "Id": 6441665647641943511,
+                    "SensorConfig": {
+                        "Publishers": {
+                            "Camera Info": {
+                                "Type": "sensor_msgs::msg::CameraInfo",
+                                "Topic": "camera_info"
+                            },
+                            "Color Image": {
+                                "Type": "sensor_msgs::msg::Image",
+                                "Topic": "camera_image_color"
+                            },
+                            "Depth Image": {
+                                "Type": "sensor_msgs::msg::Image",
+                                "Topic": "camera_image_depth"
+                            }
+                        }
+                    }
+                },
+                "Component_[7827113227536758757]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 7827113227536758757
+                },
+                "Component_[9064086166682384563]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 9064086166682384563
+                }
+            }
+        },
         "Entity_[7477775078074]": {
             "Id": "Entity_[7477775078074]",
             "Name": "rl_wheel_link_visual",
@@ -870,7 +947,8 @@
                         "Entity_[7486365012666]",
                         "Entity_[7482070045370]",
                         "Entity_[7512134816442]",
-                        "Entity_[8141757523394]"
+                        "Entity_[8141757523394]",
+                        "Entity_[454274520747]"
                     ]
                 },
                 "Component_[6615492099568417181]": {