ros2_control - kilted
Loading...
Searching...
No Matches
camera_plugin.hpp
1
20#pragma once
21
22#include <algorithm>
23#include <atomic>
24#include <functional>
25#include <mutex>
26#include <queue>
27#include <string>
28#include <thread>
29#include <vector>
30
31#include "sensor_msgs/image_encodings.hpp"
32
33#include <dlfcn.h>
34
35#include "mujoco_ros2_control_plugins/mujoco_ros2_control_plugins_base.hpp"
36
37#include <EGL/egl.h>
38#include <EGL/eglext.h>
39#include <GLFW/glfw3.h>
40#include <mujoco/mujoco.h>
41
42#include <rclcpp/node.hpp>
43#include <rclcpp/publisher.hpp>
44#include <rclcpp/rclcpp.hpp>
45#include <sensor_msgs/msg/camera_info.hpp>
46#include <sensor_msgs/msg/image.hpp>
47#include <std_srvs/srv/trigger.hpp>
48
49#include <pluginlib/class_list_macros.hpp>
50
52{
53
57enum class CameraPolicy
58{
59 DISABLED = 0, // Publishing is disabled.
60 STREAMING, // Publishing is constant at the specified publish rate.
61 POLLED // Publishing happens only when triggered by a service.
62};
63
72{
73 CameraPolicy policy = CameraPolicy::STREAMING;
74
75 // Set by the trigger service for polled cameras to request a one-shot capture.
76 bool poll_requested{ false };
77
78 // Set when this camera is selected to render on the next pass and is waiting
79 // for the rendering thread to consume it, then clear it when rendering occurs.
80 bool render_pending{ false };
81
82 mjvCamera mjv_cam;
83 mjrRect viewport;
84
85 std::string name;
86 std::string frame_name;
87 std::string info_topic;
88 std::string image_topic;
89 std::string depth_topic;
90 std::string trigger_service_name;
91
92 uint32_t width;
93 uint32_t height;
94
95 std::vector<uint8_t> image_buffer;
96 std::vector<float> depth_buffer;
97
98 sensor_msgs::msg::Image image;
99 sensor_msgs::msg::Image depth_image;
100 sensor_msgs::msg::CameraInfo camera_info;
101
102 rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr image_pub;
103 rclcpp::Publisher<sensor_msgs::msg::Image>::SharedPtr depth_image_pub;
104 rclcpp::Publisher<sensor_msgs::msg::CameraInfo>::SharedPtr camera_info_pub;
105 rclcpp::Service<std_srvs::srv::Trigger>::SharedPtr trigger_service;
106};
107
141{
142public:
144 using GlfwInitFn = std::function<int()>;
145
146 CameraPlugin() = default;
147 ~CameraPlugin() override = default;
148
149 bool init(rclcpp::Node::SharedPtr node, const mjModel* model, mjData* data) override;
150
161 bool init(rclcpp::Node::SharedPtr node, const mjModel* model, mjData* data, GlfwInitFn glfw_init_fn);
162 void update_write(const mjModel* model, mjData* data) override;
163 void cleanup() override;
164
174 void trigger_update();
175
183 {
184 return publish_images_.load();
185 }
186
187private:
188 // ROS interfaces
189 rclcpp::Logger logger_{ rclcpp::get_logger("CameraPlugin") };
190
194 void close();
195
200 bool register_cameras();
201
205 void update_loop();
206
210 void update_cameras();
211
217 void render_and_publish_camera(CameraData& camera, const rclcpp::Time& stamp);
218
223 void handle_trigger(const std::shared_ptr<std_srvs::srv::Trigger::Request> /*request*/,
224 std::shared_ptr<std_srvs::srv::Trigger::Response> response, const int camera_idx);
225
226 rclcpp::Node::SharedPtr node_;
227
228 // Ensures locked access to simulation data for rendering.
229 std::recursive_mutex* sim_mutex_{ nullptr };
230
231 mjData* mj_data_;
232 const mjModel* mj_model_;
233 mjData* mj_camera_data_;
234
235 // Image publishing rate (applies to streaming cameras only)
236 double camera_publish_rate_{ 5.0 };
237 rclcpp::Time last_publish_time_{ 0, 0, RCL_ROS_TIME };
238
239 // Whether any streaming camera is registered. This lets the update loop skip the
240 // streaming time check entirely when only polled/disabled cameras exist.
241 bool has_streaming_cameras_{ false };
242
243 // Whether at least one polled camera has a pending trigger request.
244 std::atomic_bool poll_pending_{ false };
245
246 // Rendering options for the cameras, currently hard coded to defaults
247 mjvOption mjv_opt_;
248 mjvScene mjv_scn_;
249 mjrContext mjr_con_;
250
251 // Scene parameters to keep around to avoid recomputing
252 float camera_near_distance_;
253 float camera_depth_scale_;
254
255 // Containers for camera data and ROS constructs
256 std::vector<CameraData> cameras_;
257
258 // List of camera indices to render on a given pass.
259 // Reserved once to the camera count so we do not allocate.
260 std::vector<size_t> render_indices_;
261
262 // Camera processing thread and objects for syncing
263 std::thread rendering_thread_;
264 std::atomic_bool publish_images_{ false };
265 std::atomic_bool stop_requested_{ false };
266 std::mutex data_mutex_;
267 std::condition_variable data_cv_;
268 bool new_data_{ false };
269
270 // EGL context for headless rendering (used when GLFW is unavailable)
271 EGLDisplay egl_display_{ EGL_NO_DISPLAY };
272 EGLContext egl_context_{ EGL_NO_CONTEXT };
273 EGLSurface egl_surface_{ EGL_NO_SURFACE };
274 bool use_egl_{ false };
275
280 bool init_egl_context();
281
285 void cleanup_egl_context();
286};
287
288} // namespace mujoco_ros2_control_plugins
Plugin that publishes the mujoco camera data to ROS 2 topics.
Definition camera_plugin.hpp:141
void cleanup() override
Cleanup the plugin.
Definition camera_plugin.cpp:129
void trigger_update()
Synchronously run a single render/publish cycle in the calling thread.
Definition camera_plugin.cpp:134
bool is_rendering_available() const
Whether the rendering thread has successfully initialized its GL context.
Definition camera_plugin.hpp:182
std::function< int()> GlfwInitFn
Definition camera_plugin.hpp:144
void update_write(const mjModel *model, mjData *data) override
Called once per write() cycle, on the control thread, after the hardware interface has staged the con...
Definition camera_plugin.cpp:67
bool init(rclcpp::Node::SharedPtr node, const mjModel *model, mjData *data) override
Initialize the plugin.
Definition camera_plugin.cpp:25
Base class for MuJoCo ROS 2 control plugins.
Definition mujoco_ros2_control_plugins_base.hpp:52
Definition mujoco_ros2_control_plugins_base.hpp:22
CameraPolicy
Selects when a camera's images are rendered and published.
Definition camera_plugin.hpp:58
Per-camera bookkeeping: configuration, buffers, and ROS publishers/service for one MuJoCo camera.
Definition camera_plugin.hpp:72