2
0

ROS2Lidar2DSensorComponent.cpp 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <Atom/RPI.Public/AuxGeom/AuxGeomFeatureProcessorInterface.h>
  9. #include <Atom/RPI.Public/Scene.h>
  10. #include <AzFramework/Physics/PhysicsSystem.h>
  11. #include <Lidar/LidarRegistrarSystemComponent.h>
  12. #include <Lidar/ROS2Lidar2DSensorComponent.h>
  13. #include <ROS2/Frame/ROS2FrameComponent.h>
  14. #include <ROS2/Utilities/ROS2Names.h>
  15. namespace ROS2
  16. {
  17. namespace
  18. {
  19. const char* LaserScanType = "sensor_msgs::msg::LaserScan";
  20. }
  21. void ROS2Lidar2DSensorComponent::Reflect(AZ::ReflectContext* context)
  22. {
  23. if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  24. {
  25. serializeContext->Class<ROS2Lidar2DSensorComponent, SensorBaseType>()->Version(3)->Field(
  26. "lidarCore", &ROS2Lidar2DSensorComponent::m_lidarCore);
  27. if (auto* editContext = serializeContext->GetEditContext())
  28. {
  29. editContext->Class<ROS2Lidar2DSensorComponent>("ROS2 Lidar 2D Sensor", "Lidar 2D sensor component")
  30. ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
  31. ->Attribute(AZ::Edit::Attributes::Category, "ROS2")
  32. ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC_CE("Game"))
  33. ->Attribute(AZ::Edit::Attributes::Icon, "Editor/Icons/Components/ROS2Lidar2DSensor.svg")
  34. ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Editor/Icons/Components/Viewport/ROS2Lidar2DSensor.svg")
  35. ->DataElement(
  36. AZ::Edit::UIHandlers::ComboBox,
  37. &ROS2Lidar2DSensorComponent::m_lidarCore,
  38. "Lidar configuration",
  39. "Lidar configuration")
  40. ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly);
  41. }
  42. }
  43. }
  44. ROS2Lidar2DSensorComponent::ROS2Lidar2DSensorComponent()
  45. : m_lidarCore(LidarTemplateUtils::Get2DModels())
  46. {
  47. TopicConfiguration ls;
  48. AZStd::string type = LaserScanType;
  49. ls.m_type = type;
  50. ls.m_topic = "scan";
  51. m_sensorConfiguration.m_frequency = 10.f;
  52. m_sensorConfiguration.m_publishersConfigurations.insert(AZStd::make_pair(type, ls));
  53. }
  54. ROS2Lidar2DSensorComponent::ROS2Lidar2DSensorComponent(
  55. const SensorConfiguration& sensorConfiguration, const LidarSensorConfiguration& lidarConfiguration)
  56. : m_lidarCore(lidarConfiguration)
  57. {
  58. m_sensorConfiguration = sensorConfiguration;
  59. }
  60. void ROS2Lidar2DSensorComponent::Activate()
  61. {
  62. ROS2SensorComponentBase::Activate();
  63. m_lidarCore.Init(GetEntityId());
  64. auto ros2Node = ROS2Interface::Get()->GetNode();
  65. AZ_Assert(m_sensorConfiguration.m_publishersConfigurations.size() == 1, "Invalid configuration of publishers for lidar sensor");
  66. const TopicConfiguration& publisherConfig = m_sensorConfiguration.m_publishersConfigurations[LaserScanType];
  67. AZStd::string fullTopic = ROS2Names::GetNamespacedName(GetNamespace(), publisherConfig.m_topic);
  68. m_laserScanPublisher = ros2Node->create_publisher<sensor_msgs::msg::LaserScan>(fullTopic.data(), publisherConfig.GetQoS());
  69. StartSensor(
  70. m_sensorConfiguration.m_frequency,
  71. [this]([[maybe_unused]] auto&&... args)
  72. {
  73. FrequencyTick();
  74. },
  75. [this]([[maybe_unused]] auto&&... args)
  76. {
  77. if (!m_sensorConfiguration.m_visualize)
  78. {
  79. return;
  80. }
  81. m_lidarCore.VisualizeResults();
  82. });
  83. }
  84. void ROS2Lidar2DSensorComponent::Deactivate()
  85. {
  86. StopSensor();
  87. m_laserScanPublisher.reset();
  88. m_lidarCore.Deinit();
  89. ROS2SensorComponentBase::Deactivate();
  90. }
  91. void ROS2Lidar2DSensorComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  92. {
  93. required.push_back(AZ_CRC_CE("ROS2Frame"));
  94. }
  95. void ROS2Lidar2DSensorComponent::FrequencyTick()
  96. {
  97. AZStd::optional<RaycastResults> results = m_lidarCore.PerformRaycast();
  98. if (!results.has_value() || !m_sensorConfiguration.m_publishingEnabled)
  99. {
  100. return;
  101. }
  102. PublishRaycastResults(results.value());
  103. }
  104. void ROS2Lidar2DSensorComponent::PublishRaycastResults(const RaycastResults& results)
  105. {
  106. const bool isIntensityEnabled = m_lidarCore.m_lidarConfiguration.m_lidarSystemFeatures & LidarSystemFeatures::Intensity;
  107. auto* ros2Frame = GetEntity()->FindComponent<ROS2FrameComponent>();
  108. auto message = sensor_msgs::msg::LaserScan();
  109. message.header.frame_id = ros2Frame->GetFrameID().data();
  110. message.header.stamp = ROS2Interface::Get()->GetROSTimestamp();
  111. message.angle_min = AZ::DegToRad(m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minHAngle);
  112. message.angle_max = AZ::DegToRad(m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxHAngle);
  113. message.angle_increment = (message.angle_max - message.angle_min) /
  114. aznumeric_cast<float>(m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_numberOfIncrements);
  115. message.range_min = m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minRange;
  116. message.range_max = m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxRange;
  117. message.scan_time = 1.f / m_sensorConfiguration.m_frequency;
  118. message.time_increment = 0.0f;
  119. const auto rangeField = results.GetConstFieldSpan<RaycastResultFlags::Range>().value();
  120. message.ranges.assign(rangeField.begin(), rangeField.end());
  121. if (isIntensityEnabled)
  122. {
  123. const auto intensityField = results.GetConstFieldSpan<RaycastResultFlags::Intensity>().value();
  124. message.intensities.assign(intensityField.begin(), intensityField.end());
  125. }
  126. m_laserScanPublisher->publish(message);
  127. }
  128. } // namespace ROS2