ROS2Lidar2DSensorComponent.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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 ROS2Sensors
  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. ROS2::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 ROS2::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 = ROS2::ROS2Interface::Get()->GetNode();
  65. AZ_Assert(m_sensorConfiguration.m_publishersConfigurations.size() == 1, "Invalid configuration of publishers for lidar sensor");
  66. const ROS2::TopicConfiguration& publisherConfig = m_sensorConfiguration.m_publishersConfigurations[LaserScanType];
  67. AZStd::string fullTopic = ROS2::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. LidarConfigurationRequestBus::Handler::BusConnect(GetEntityId());
  84. }
  85. void ROS2Lidar2DSensorComponent::Deactivate()
  86. {
  87. LidarConfigurationRequestBus::Handler::BusDisconnect(GetEntityId());
  88. StopSensor();
  89. m_laserScanPublisher.reset();
  90. m_lidarCore.Deinit();
  91. ROS2SensorComponentBase::Deactivate();
  92. }
  93. void ROS2Lidar2DSensorComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  94. {
  95. required.push_back(AZ_CRC_CE("ROS2Frame"));
  96. }
  97. void ROS2Lidar2DSensorComponent::FrequencyTick()
  98. {
  99. AZStd::optional<RaycastResults> results = m_lidarCore.PerformRaycast();
  100. if (!results.has_value() || !m_sensorConfiguration.m_publishingEnabled)
  101. {
  102. return;
  103. }
  104. PublishRaycastResults(results.value());
  105. }
  106. void ROS2Lidar2DSensorComponent::PublishRaycastResults(const RaycastResults& results)
  107. {
  108. const bool isIntensityEnabled = m_lidarCore.m_lidarConfiguration.m_lidarSystemFeatures & LidarSystemFeatures::Intensity;
  109. auto* ros2Frame = GetEntity()->FindComponent<ROS2::ROS2FrameComponent>();
  110. auto message = sensor_msgs::msg::LaserScan();
  111. message.header.frame_id = ros2Frame->GetFrameID().data();
  112. message.header.stamp = ROS2::ROS2Interface::Get()->GetROSTimestamp();
  113. message.angle_min = AZ::DegToRad(m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minHAngle);
  114. message.angle_max = AZ::DegToRad(m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxHAngle);
  115. message.angle_increment = (message.angle_max - message.angle_min) /
  116. aznumeric_cast<float>(m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_numberOfIncrements);
  117. message.range_min = m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minRange;
  118. message.range_max = m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxRange;
  119. message.scan_time = 1.f / m_sensorConfiguration.m_frequency;
  120. message.time_increment = 0.0f;
  121. const auto rangeField = results.GetConstFieldSpan<RaycastResultFlags::Range>().value();
  122. message.ranges.assign(rangeField.begin(), rangeField.end());
  123. if (isIntensityEnabled)
  124. {
  125. const auto intensityField = results.GetConstFieldSpan<RaycastResultFlags::Intensity>().value();
  126. message.intensities.assign(intensityField.begin(), intensityField.end());
  127. }
  128. m_laserScanPublisher->publish(message);
  129. }
  130. void ROS2Lidar2DSensorComponent::SetConfiguration(const LidarSensorConfiguration& configuration)
  131. {
  132. m_lidarCore.Deinit();
  133. m_lidarCore.m_lidarConfiguration = configuration;
  134. m_lidarCore.Init(GetEntityId());
  135. }
  136. const LidarSensorConfiguration ROS2Lidar2DSensorComponent::GetConfiguration()
  137. {
  138. return m_lidarCore.m_lidarConfiguration;
  139. }
  140. AZStd::string ROS2Lidar2DSensorComponent::GetModelName()
  141. {
  142. return m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_name;
  143. }
  144. void ROS2Lidar2DSensorComponent::SetModelName(const AZStd::string& name)
  145. {
  146. m_lidarCore.Deinit();
  147. m_lidarCore.m_lidarConfiguration.m_lidarModelName = name;
  148. m_lidarCore.m_lidarConfiguration.FetchLidarModelConfiguration();
  149. // Unknown lidar models are set to custom lidar model with a given name
  150. m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_name = name;
  151. m_lidarCore.Init(GetEntityId());
  152. }
  153. bool ROS2Lidar2DSensorComponent::IsSegmentationEnabled()
  154. {
  155. return m_lidarCore.m_lidarConfiguration.m_isSegmentationEnabled;
  156. }
  157. void ROS2Lidar2DSensorComponent::SetSegmentationEnabled(bool enabled)
  158. {
  159. m_lidarCore.Deinit();
  160. m_lidarCore.m_lidarConfiguration.m_isSegmentationEnabled = enabled;
  161. m_lidarCore.Init(GetEntityId());
  162. }
  163. bool ROS2Lidar2DSensorComponent::IsAddPointsAtMaxEnabled()
  164. {
  165. return m_lidarCore.m_lidarConfiguration.m_addPointsAtMax;
  166. }
  167. void ROS2Lidar2DSensorComponent::SetAddPointsAtMaxEnabled(bool addPoints)
  168. {
  169. m_lidarCore.Deinit();
  170. m_lidarCore.m_lidarConfiguration.m_addPointsAtMax = addPoints;
  171. m_lidarCore.Init(GetEntityId());
  172. }
  173. bool ROS2Lidar2DSensorComponent::Is2D()
  174. {
  175. return m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_is2D;
  176. }
  177. float ROS2Lidar2DSensorComponent::GetMinHAngle()
  178. {
  179. return m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minHAngle;
  180. }
  181. void ROS2Lidar2DSensorComponent::SetMinHAngle(float angle)
  182. {
  183. if (angle < -180.0f || angle > 180.0f)
  184. {
  185. AZ_Error("ROS2Lidar2DSensorComponent", false, "Min horizontal angle must be between -180 and 180 degrees.");
  186. return;
  187. }
  188. m_lidarCore.Deinit();
  189. m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minHAngle = angle;
  190. m_lidarCore.Init(GetEntityId());
  191. }
  192. float ROS2Lidar2DSensorComponent::GetMaxHAngle()
  193. {
  194. return m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxHAngle;
  195. }
  196. void ROS2Lidar2DSensorComponent::SetMaxHAngle(float angle)
  197. {
  198. if (angle < -180.0f || angle > 180.0f)
  199. {
  200. AZ_Error("ROS2Lidar2DSensorComponent", false, "Max horizontal angle must be between -180 and 180 degrees.");
  201. return;
  202. }
  203. m_lidarCore.Deinit();
  204. m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxHAngle = angle;
  205. m_lidarCore.Init(GetEntityId());
  206. }
  207. unsigned int ROS2Lidar2DSensorComponent::GetNumberOfIncrements()
  208. {
  209. return m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_numberOfIncrements;
  210. }
  211. void ROS2Lidar2DSensorComponent::SetNumberOfIncrements(unsigned int increments)
  212. {
  213. m_lidarCore.Deinit();
  214. m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_numberOfIncrements = increments;
  215. m_lidarCore.Init(GetEntityId());
  216. }
  217. float ROS2Lidar2DSensorComponent::GetMinRange()
  218. {
  219. return m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minRange;
  220. }
  221. void ROS2Lidar2DSensorComponent::SetMinRange(float range)
  222. {
  223. const float maxRange = m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxRange;
  224. if (range < 0.0f || range > maxRange)
  225. {
  226. AZ_Error("ROS2Lidar2DSensorComponent", false, "Min range cannot be less than 0 or greater than max range (%f).", maxRange);
  227. return;
  228. }
  229. m_lidarCore.Deinit();
  230. m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minRange = range;
  231. m_lidarCore.Init(GetEntityId());
  232. }
  233. float ROS2Lidar2DSensorComponent::GetMaxRange()
  234. {
  235. return m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxRange;
  236. }
  237. void ROS2Lidar2DSensorComponent::SetMaxRange(float range)
  238. {
  239. const float minRange = m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_minRange;
  240. if (range < minRange)
  241. {
  242. AZ_Error("ROS2Lidar2DSensorComponent", false, "Max range cannot be less than min range (%f).", minRange);
  243. return;
  244. }
  245. m_lidarCore.Deinit();
  246. m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_maxRange = range;
  247. m_lidarCore.Init(GetEntityId());
  248. }
  249. const LidarTemplate::NoiseParameters& ROS2Lidar2DSensorComponent::GetNoiseParameters()
  250. {
  251. return m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_noiseParameters;
  252. }
  253. void ROS2Lidar2DSensorComponent::SetNoiseParameters(const LidarTemplate::NoiseParameters& params)
  254. {
  255. if (params.m_angularNoiseStdDev < 0.0f || params.m_angularNoiseStdDev > 180.0f || params.m_distanceNoiseStdDevBase < 0.0f ||
  256. params.m_distanceNoiseStdDevRisePerMeter < 0.0f)
  257. {
  258. AZ_Error("ROS2Lidar2DSensorComponent", false, "Invalid noise parameters provided.");
  259. return;
  260. }
  261. m_lidarCore.Deinit();
  262. m_lidarCore.m_lidarConfiguration.m_lidarParameters.m_noiseParameters = params;
  263. m_lidarCore.Init(GetEntityId());
  264. }
  265. } // namespace ROS2Sensors