LidarTemplateUtils.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  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 <AzCore/Math/Quaternion.h>
  9. #include <AzCore/Math/Transform.h>
  10. #include <ROS2Sensors/Lidar/LidarTemplateUtils.h>
  11. namespace ROS2Sensors
  12. {
  13. namespace
  14. {
  15. using Model = LidarTemplate::LidarModel;
  16. // clang-format off
  17. static const AZStd::map<Model, LidarTemplate> templates = { {
  18. Model::Custom3DLidar,
  19. {
  20. /*.m_model = */ Model::Custom3DLidar,
  21. /*.m_name = */ "CustomLidar",
  22. /*.m_is2D = */ false,
  23. /*.m_minHAngle = */ -180.0f,
  24. /*.m_maxHAngle = */ 180.0f,
  25. /*.m_minVAngle = */ -35.0f,
  26. /*.m_maxVAngle = */ 35.0f,
  27. /*.m_layers = */ 24,
  28. /*.m_numberOfIncrements = */ 924,
  29. /*.m_minRange = */ 0.0f,
  30. /*.m_maxRange = */ 100.0f,
  31. /*.m_noiseParameters = */
  32. {
  33. /*.m_angularNoiseStdDev = */ 0.0f,
  34. /*.m_distanceNoiseStdDevBase = */ 0.01f,
  35. /*.m_distanceNoiseStdDevRisePerMeter = */ 0.001f,
  36. },
  37. },
  38. },
  39. {
  40. Model::Ouster_OS0_64,
  41. {
  42. /*.m_model = */ Model::Ouster_OS0_64,
  43. /*.m_name = */ "Ouster OS0-64",
  44. /*.m_is2D = */ false,
  45. /*.m_minHAngle = */ -180.0f,
  46. /*.m_maxHAngle = */ 180.0f,
  47. /*.m_minVAngle = */ -45.0f,
  48. /*.m_maxVAngle = */ 45.0f,
  49. /*.m_layers = */ 64,
  50. /*.m_numberOfIncrements = */ 2048,
  51. /*.m_minRange = */ 0.0f,
  52. /*.m_maxRange = */ 47.5f,
  53. /*.m_noiseParameters = */
  54. {
  55. /*.m_angularNoiseStdDev = */ 0.0f,
  56. /*.m_distanceNoiseStdDevBase = */ 0.0f,
  57. /*.m_distanceNoiseStdDevRisePerMeter = */ 0.002f,
  58. },
  59. },
  60. },
  61. {
  62. Model::Ouster_OS1_64,
  63. {
  64. /*.m_model = */ Model::Ouster_OS1_64,
  65. /*.m_name = */ "Ouster OS1-64",
  66. /*.m_is2D = */ false,
  67. /*.m_minHAngle = */ -180.0f,
  68. /*.m_maxHAngle = */ 180.0f,
  69. /*.m_minVAngle = */ 22.5f,
  70. /*.m_maxVAngle = */ -22.5f,
  71. /*.m_layers = */ 64,
  72. /*.m_numberOfIncrements = */ 2048,
  73. /*.m_minRange = */ 0.0f,
  74. /*.m_maxRange = */ 120.0f,
  75. /*.m_noiseParameters = */
  76. {
  77. /*.m_angularNoiseStdDev = */ 0.0f,
  78. /*.m_distanceNoiseStdDevBase = */ 0.002f,
  79. /*.m_distanceNoiseStdDevRisePerMeter = */ 0.0008f,
  80. },
  81. },
  82. },
  83. {
  84. Model::Ouster_OS2_64,
  85. {
  86. /*.m_model = */ Model::Ouster_OS2_64,
  87. /*.m_name = */ "Ouster OS2-64",
  88. /*.m_is2D = */ false,
  89. /*.m_minHAngle = */ -180.0f,
  90. /*.m_maxHAngle = */ 180.0f,
  91. /*.m_minVAngle = */ 11.25f,
  92. /*.m_maxVAngle = */ -11.25f,
  93. /*.m_layers = */ 64,
  94. /*.m_numberOfIncrements = */ 2048,
  95. /*.m_minRange = */ 0.0f,
  96. /*.m_maxRange = */ 225.0f,
  97. /*.m_noiseParameters = */
  98. {
  99. /*.m_angularNoiseStdDev = */ 0.0f,
  100. /*.m_distanceNoiseStdDevBase = */ 0.006f,
  101. /*.m_distanceNoiseStdDevRisePerMeter = */ 0.001f,
  102. },
  103. },
  104. },
  105. {
  106. Model::Velodyne_Puck,
  107. {
  108. /*.m_model = */ Model::Velodyne_Puck,
  109. /*.m_name = */ "Velodyne Puck (VLP-16)",
  110. /*.m_is2D = */ false,
  111. /*.m_minHAngle = */ -180.0f,
  112. /*.m_maxHAngle = */ 180.0f,
  113. /*.m_minVAngle = */ 15.0f,
  114. /*.m_maxVAngle = */ -15.0f,
  115. /*.m_layers = */ 16,
  116. /*.m_numberOfIncrements = */ 1800, // For 0.2 angular resolution
  117. /*.m_minRange = */ 0.0f,
  118. /*.m_maxRange = */ 100.0f,
  119. /*.m_noiseParameters = */
  120. {
  121. /*.m_angularNoiseStdDev = */ 0.0f,
  122. /*.m_distanceNoiseStdDevBase = */ 0.03f,
  123. /*.m_distanceNoiseStdDevRisePerMeter = */ 0.001f,
  124. },
  125. },
  126. },
  127. {
  128. Model::Velodyne_HDL_32E,
  129. {
  130. /*.m_model = */ Model::Velodyne_HDL_32E,
  131. /*.m_name = */ "Velodyne HDL-32E",
  132. /*.m_is2D = */ false,
  133. /*.m_minHAngle = */ -180.0f,
  134. /*.m_maxHAngle = */ 180.0f,
  135. /*.m_minVAngle = */ 10.67f,
  136. /*.m_maxVAngle = */ -30.67f,
  137. /*.m_layers = */ 32,
  138. /*.m_numberOfIncrements = */ 1800, // For 0.2 angular resolution
  139. /*.m_minRange = */ 0.0f,
  140. /*.m_maxRange = */ 100.0f,
  141. /*.m_noiseParameters = */
  142. {
  143. /*.m_angularNoiseStdDev = */ 0.0f,
  144. /*.m_distanceNoiseStdDevBase = */ 0.02f,
  145. /*.m_distanceNoiseStdDevRisePerMeter = */ 0.001f,
  146. },
  147. },
  148. },
  149. {
  150. Model::Custom2DLidar,
  151. {
  152. /*.m_model = */ Model::Custom2DLidar,
  153. /*.m_name = */ "CustomLidar2D",
  154. /*.m_is2D = */ true,
  155. /*.m_minHAngle = */ -180.0f,
  156. /*.m_maxHAngle = */ 180.0f,
  157. /*.m_minVAngle = */ 0.f,
  158. /*.m_maxVAngle = */ 0.f,
  159. /*.m_layers = */ 1,
  160. /*.m_numberOfIncrements = */ 924,
  161. /*.m_minRange = */ 0.0f,
  162. /*.m_maxRange = */ 100.0f,
  163. /*.m_noiseParameters = */
  164. {
  165. /*.m_angularNoiseStdDev = */ 0.0f,
  166. /*.m_distanceNoiseStdDevBase = */ 0.02f,
  167. /*.m_distanceNoiseStdDevRisePerMeter = */ 0.001f,
  168. },
  169. },
  170. },
  171. {
  172. Model::Slamtec_RPLIDAR_S1,
  173. {
  174. /*.m_model = */ Model::Slamtec_RPLIDAR_S1,
  175. /*.m_name = */ "Slamtec RPLIDAR S1",
  176. /*.m_is2D = */ true,
  177. /*.m_minHAngle = */ -180.0f,
  178. /*.m_maxHAngle = */ 180.0f,
  179. /*.m_minVAngle = */ 0.f,
  180. /*.m_maxVAngle = */ 0.f,
  181. /*.m_layers = */ 1,
  182. /*.m_numberOfIncrements = */ 921,
  183. /*.m_minRange = */ 0.1f,
  184. /*.m_maxRange = */ 40.0f,
  185. /*.m_noiseParameters = */
  186. {
  187. /*.m_angularNoiseStdDev = */ 0.0f,
  188. /*.m_distanceNoiseStdDevBase = */ 0.02f,
  189. /*.m_distanceNoiseStdDevRisePerMeter = */ 0.001f,
  190. },
  191. },
  192. } };
  193. // clang-format on
  194. } // namespace
  195. LidarTemplate LidarTemplateUtils::GetTemplate(LidarTemplate::LidarModel model)
  196. {
  197. auto it = templates.find(model);
  198. if (it == templates.end())
  199. {
  200. return {};
  201. }
  202. return it->second;
  203. }
  204. AZStd::vector<LidarTemplate::LidarModel> LidarTemplateUtils::Get2DModels()
  205. {
  206. AZStd::vector<LidarTemplate::LidarModel> result;
  207. for (const auto& it : templates)
  208. {
  209. if (it.second.m_is2D)
  210. {
  211. result.push_back(it.first);
  212. }
  213. }
  214. return result;
  215. }
  216. AZStd::vector<LidarTemplate::LidarModel> LidarTemplateUtils::Get3DModels()
  217. {
  218. AZStd::vector<LidarTemplate::LidarModel> result;
  219. for (const auto& it : templates)
  220. {
  221. if (!it.second.m_is2D)
  222. {
  223. result.push_back(it.first);
  224. }
  225. }
  226. return result;
  227. }
  228. size_t LidarTemplateUtils::TotalPointCount(const LidarTemplate& t)
  229. {
  230. return t.m_layers * t.m_numberOfIncrements;
  231. }
  232. AZStd::vector<AZ::Vector3> LidarTemplateUtils::PopulateRayRotations(const LidarTemplate& lidarTemplate)
  233. {
  234. const float minVertAngle = AZ::DegToRad(lidarTemplate.m_minVAngle);
  235. const float maxVertAngle = AZ::DegToRad(lidarTemplate.m_maxVAngle);
  236. const float minHorAngle = AZ::DegToRad(lidarTemplate.m_minHAngle);
  237. const float maxHorAngle = AZ::DegToRad(lidarTemplate.m_maxHAngle);
  238. const float verticalStep = (maxVertAngle - minVertAngle) / static_cast<float>(lidarTemplate.m_layers);
  239. const float horizontalStep = (maxHorAngle - minHorAngle) / static_cast<float>(lidarTemplate.m_numberOfIncrements);
  240. AZStd::vector<AZ::Vector3> rotations;
  241. for (int incr = 0; incr < lidarTemplate.m_numberOfIncrements; incr++)
  242. {
  243. const float yaw = minHorAngle + incr * horizontalStep;
  244. for (int layer = 0; layer < lidarTemplate.m_layers; layer++)
  245. {
  246. const float pitch = minVertAngle + layer * verticalStep;
  247. rotations.emplace_back(0.0f, pitch, yaw);
  248. }
  249. }
  250. return rotations;
  251. }
  252. AZStd::vector<AZ::Vector3> LidarTemplateUtils::RotationsToDirections(
  253. const AZStd::vector<AZ::Quaternion>& rotations, const AZ::Transform& rootTransform)
  254. {
  255. AZStd::vector<AZ::Vector3> directions;
  256. directions.reserve(rotations.size());
  257. for (const auto& angle : rotations)
  258. {
  259. const AZ::Quaternion rotation = rootTransform.GetRotation() * angle;
  260. directions.emplace_back(rotation.TransformVector(AZ::Vector3::CreateAxisX()));
  261. }
  262. return directions;
  263. }
  264. } // namespace ROS2Sensors