CameraSensor.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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 "CameraSensor.h"
  9. #include <AzCore/Math/MatrixUtils.h>
  10. #include <Atom/RPI.Public/Base.h>
  11. #include <Atom/RPI.Public/Pass/Specific/RenderToTexturePass.h>
  12. #include <Atom/RPI.Public/RPISystemInterface.h>
  13. #include <Atom/RPI.Public/RenderPipeline.h>
  14. #include <Atom/RPI.Public/Scene.h>
  15. #include <AzFramework/Components/TransformComponent.h>
  16. #include <AzFramework/Scene/SceneSystemInterface.h>
  17. #include <Atom/RPI.Public/FeatureProcessorFactory.h>
  18. #include <Atom/RPI.Public/Pass/PassSystemInterface.h>
  19. #include <PostProcess/PostProcessFeatureProcessor.h>
  20. #include <Atom/RPI.Public/Pass/PassFactory.h>
  21. namespace ROS2
  22. {
  23. namespace Internal
  24. {
  25. /// @FormatMappings - contains the mapping from RHI to ROS image encodings. List of supported
  26. /// ROS image encodings lives in `sensor_msgs/image_encodings.hpp`
  27. /// We are not including `image_encodings.hpp` since it uses exceptions.
  28. AZStd::unordered_map<AZ::RHI::Format, const char*> FormatMappings{
  29. { AZ::RHI::Format::R8G8B8A8_UNORM, "rgba8" }, { AZ::RHI::Format::R16G16B16A16_UNORM, "rgba16" },
  30. { AZ::RHI::Format::R32G32B32A32_FLOAT, "32FC4" }, // Unsuported by RVIZ2
  31. { AZ::RHI::Format::R8_UNORM, "mono8" }, { AZ::RHI::Format::R16_UNORM, "mono16" },
  32. { AZ::RHI::Format::R32_FLOAT, "32FC1" },
  33. };
  34. /// @BitDepth - contains the mapping from RHI to size used in `step` size computation.
  35. /// It is some equivalent to `bitDepth()` function from `sensor_msgs/image_encodings.hpp`
  36. AZStd::unordered_map<AZ::RHI::Format, int> BitDepth{
  37. { AZ::RHI::Format::R8G8B8A8_UNORM, 4 * sizeof(uint8_t) },
  38. { AZ::RHI::Format::R16G16B16A16_UNORM, 4 * sizeof(uint16_t) },
  39. { AZ::RHI::Format::R32G32B32A32_FLOAT, 4 * sizeof(float) }, // Unsuported by RVIZ2
  40. { AZ::RHI::Format::R8_UNORM, sizeof(uint8_t) },
  41. { AZ::RHI::Format::R16_UNORM, sizeof(uint16_t) },
  42. { AZ::RHI::Format::R32_FLOAT, sizeof(float) },
  43. };
  44. } // namespace Internal
  45. CameraSensorDescription::CameraSensorDescription(const AZStd::string& cameraName, float verticalFov, int width, int height)
  46. : m_verticalFieldOfViewDeg(verticalFov)
  47. , m_width(width)
  48. , m_height(height)
  49. , m_cameraName(cameraName)
  50. , m_aspectRatio(static_cast<float>(width) / static_cast<float>(height))
  51. , m_viewToClipMatrix(MakeViewToClipMatrix())
  52. , m_cameraIntrinsics(MakeCameraIntrinsics())
  53. {
  54. ValidateParameters();
  55. }
  56. AZ::Matrix4x4 CameraSensorDescription::MakeViewToClipMatrix() const
  57. {
  58. const float nearDist = 0.1f, farDist = 100.0f;
  59. AZ::Matrix4x4 localViewToClipMatrix;
  60. AZ::MakePerspectiveFovMatrixRH(
  61. localViewToClipMatrix, AZ::DegToRad(m_verticalFieldOfViewDeg), m_aspectRatio, nearDist, farDist, true);
  62. return localViewToClipMatrix;
  63. }
  64. void CameraSensorDescription::ValidateParameters() const
  65. {
  66. AZ_Assert(
  67. m_verticalFieldOfViewDeg > 0.0f && m_verticalFieldOfViewDeg < 180.0f,
  68. "Vertical fov should be in range 0.0 < FoV < 180.0 degrees");
  69. AZ_Assert(!m_cameraName.empty(), "Camera name cannot be empty");
  70. }
  71. AZStd::array<double, 9> CameraSensorDescription::MakeCameraIntrinsics() const
  72. {
  73. // Intrinsic camera matrix of the camera image is being created here
  74. // It is based on other parameters available in the structure - they must be initialized before this function is called
  75. // Matrix is row-major and has the following form:
  76. // [fx 0 cx]
  77. // [ 0 fy cy]
  78. // [ 0 0 1]
  79. // Projects 3D points in the camera coordinate frame to 2D pixel
  80. // coordinates using the focal lengths (fx, fy) and principal point
  81. // (cx, cy).
  82. const auto w = static_cast<double>(m_width);
  83. const auto h = static_cast<double>(m_height);
  84. const double verticalFieldOfView = AZ::DegToRad(m_verticalFieldOfViewDeg);
  85. const double horizontalFoV = 2.0 * AZStd::atan(AZStd::tan(verticalFieldOfView / 2.0) * m_aspectRatio);
  86. const double focalLengthX = w / (2.0 * AZStd::tan(horizontalFoV / 2.0));
  87. const double focalLengthY = h / (2.0 * AZStd::tan(verticalFieldOfView / 2.0));
  88. return { focalLengthX, 0.0, w / 2.0, 0.0, focalLengthY, h / 2.0, 0.0, 0.0, 1.0 };
  89. }
  90. CameraSensor::CameraSensor(const CameraSensorDescription& cameraSensorDescription)
  91. : m_cameraSensorDescription(cameraSensorDescription)
  92. {
  93. }
  94. void CameraSensor::SetupPasses()
  95. {
  96. AZ_TracePrintf("CameraSensor", "Initializing pipeline for %s\n", m_cameraSensorDescription.m_cameraName.c_str());
  97. const AZ::Name viewName = AZ::Name("MainCamera");
  98. m_view = AZ::RPI::View::CreateView(viewName, AZ::RPI::View::UsageCamera);
  99. m_view->SetViewToClipMatrix(m_cameraSensorDescription.m_viewToClipMatrix);
  100. m_scene = AZ::RPI::RPISystemInterface::Get()->GetSceneByName(AZ::Name("Main"));
  101. const AZStd::string pipelineName = m_cameraSensorDescription.m_cameraName + "Pipeline" + GetPipelineTypeName();
  102. AZ::RPI::RenderPipelineDescriptor pipelineDesc;
  103. pipelineDesc.m_mainViewTagName = "MainCamera";
  104. pipelineDesc.m_name = pipelineName;
  105. pipelineDesc.m_rootPassTemplate = GetPipelineTemplateName();
  106. pipelineDesc.m_renderSettings.m_multisampleState = AZ::RPI::RPISystemInterface::Get()->GetApplicationMultisampleState();
  107. m_pipeline = AZ::RPI::RenderPipeline::CreateRenderPipeline(pipelineDesc);
  108. m_pipeline->RemoveFromRenderTick();
  109. if (auto renderToTexturePass = azrtti_cast<AZ::RPI::RenderToTexturePass*>(m_pipeline->GetRootPass().get()))
  110. {
  111. renderToTexturePass->ResizeOutput(m_cameraSensorDescription.m_width, m_cameraSensorDescription.m_height);
  112. }
  113. m_scene->AddRenderPipeline(m_pipeline);
  114. m_passHierarchy.push_back(pipelineName);
  115. m_passHierarchy.push_back("CopyToSwapChain");
  116. m_pipeline->SetDefaultView(m_view);
  117. const AZ::RPI::ViewPtr targetView = m_scene->GetDefaultRenderPipeline()->GetDefaultView();
  118. if (auto* fp = m_scene->GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessor>())
  119. {
  120. fp->SetViewAlias(m_view, targetView);
  121. }
  122. }
  123. CameraSensor::~CameraSensor()
  124. {
  125. if (m_scene)
  126. {
  127. if (auto* fp = m_scene->GetFeatureProcessor<AZ::Render::PostProcessFeatureProcessor>())
  128. {
  129. fp->RemoveViewAlias(m_view);
  130. }
  131. m_scene->RemoveRenderPipeline(m_pipeline->GetId());
  132. m_scene = nullptr;
  133. }
  134. m_passHierarchy.clear();
  135. m_pipeline.reset();
  136. m_view.reset();
  137. }
  138. void CameraSensor::RequestFrame(
  139. const AZ::Transform& cameraPose, AZStd::function<void(const AZ::RPI::AttachmentReadback::ReadbackResult& result)> callback)
  140. {
  141. const AZ::Transform inverse = (cameraPose * AtomToRos).GetInverse();
  142. m_view->SetWorldToViewMatrix(AZ::Matrix4x4::CreateFromQuaternionAndTranslation(inverse.GetRotation(), inverse.GetTranslation()));
  143. AZ::Render::FrameCaptureId captureId = AZ::Render::InvalidFrameCaptureId;
  144. m_pipeline->AddToRenderTickOnce();
  145. AZ::Render::FrameCaptureRequestBus::BroadcastResult(
  146. captureId,
  147. &AZ::Render::FrameCaptureRequestBus::Events::CapturePassAttachmentWithCallback,
  148. m_passHierarchy,
  149. AZStd::string("Output"),
  150. callback,
  151. AZ::RPI::PassAttachmentReadbackOption::Output);
  152. }
  153. const CameraSensorDescription& CameraSensor::GetCameraSensorDescription() const
  154. {
  155. return m_cameraSensorDescription;
  156. }
  157. void CameraSensor::RequestMessagePublication(
  158. std::shared_ptr<rclcpp::Publisher<sensor_msgs::msg::Image>> publisher,
  159. const AZ::Transform& cameraPose,
  160. const std_msgs::msg::Header& header)
  161. {
  162. RequestFrame(
  163. cameraPose,
  164. [header, publisher](const AZ::RPI::AttachmentReadback::ReadbackResult& result)
  165. {
  166. const AZ::RHI::ImageDescriptor& descriptor = result.m_imageDescriptor;
  167. const auto format = descriptor.m_format;
  168. AZ_Assert(Internal::FormatMappings.contains(format), "Unknown format in result %u", static_cast<uint32_t>(format));
  169. sensor_msgs::msg::Image message;
  170. message.encoding = Internal::FormatMappings.at(format);
  171. message.width = descriptor.m_size.m_width;
  172. message.height = descriptor.m_size.m_height;
  173. message.step = message.width * Internal::BitDepth.at(format);
  174. message.data = std::vector<uint8_t>(result.m_dataBuffer->data(), result.m_dataBuffer->data() + result.m_dataBuffer->size());
  175. message.header = header;
  176. publisher->publish(message);
  177. });
  178. }
  179. CameraDepthSensor::CameraDepthSensor(const CameraSensorDescription& cameraSensorDescription)
  180. : CameraSensor(cameraSensorDescription)
  181. {
  182. SetupPasses();
  183. }
  184. AZStd::string CameraDepthSensor::GetPipelineTemplateName() const
  185. {
  186. return "PipelineRenderToTextureROSDepth";
  187. };
  188. AZStd::string CameraDepthSensor::GetPipelineTypeName() const
  189. {
  190. return "Depth";
  191. };
  192. CameraColorSensor::CameraColorSensor(const CameraSensorDescription& cameraSensorDescription)
  193. : CameraSensor(cameraSensorDescription)
  194. {
  195. SetupPasses();
  196. }
  197. AZStd::string CameraColorSensor::GetPipelineTemplateName() const
  198. {
  199. return "PipelineRenderToTextureROSColor";
  200. };
  201. AZStd::string CameraColorSensor::GetPipelineTypeName() const
  202. {
  203. return "Color";
  204. };
  205. } // namespace ROS2