ros2_control - humble
Loading...
Searching...
No Matches
mujoco_system_interface.hpp
1
20#pragma once
21
22#include <condition_variable>
23#include <memory>
24#include <mutex>
25#include <string>
26#include <thread>
27#include <vector>
28
29#include <hardware_interface/version.h>
30#include <atomic>
31#include <hardware_interface/handle.hpp>
32#include <hardware_interface/hardware_info.hpp>
33#include <hardware_interface/system_interface.hpp>
34#include <hardware_interface/types/hardware_interface_return_values.hpp>
35#include <mujoco_ros2_control_msgs/srv/reset_world.hpp>
36#include <mujoco_ros2_control_msgs/srv/set_pause.hpp>
37#include <mujoco_ros2_control_msgs/srv/step_simulation.hpp>
38#include <nav_msgs/msg/odometry.hpp>
39#include <rclcpp/macros.hpp>
40#include <rclcpp/rclcpp.hpp>
41#include <rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp>
42#include <rclcpp_lifecycle/state.hpp>
43#include <realtime_tools/realtime_publisher.hpp>
44#include <rosgraph_msgs/msg/clock.hpp>
45#include <sensor_msgs/msg/joint_state.hpp>
46
47#include <mujoco/mujoco.h>
48
49// Pull in the Simulate class and PhysicsThread/RenderLoop declarations:
50#include "glfw_adapter.h" // for mj::GlfwAdapter
51#include "simulate.h" // must be on your include path, handled by CMake
52
53#include "mujoco_ros2_control/data.hpp"
54#include "mujoco_ros2_control/mujoco_cameras.hpp"
55#include "mujoco_ros2_control/mujoco_lidar.hpp"
56
57#include <pluginlib/class_list_macros.hpp>
58#include <pluginlib/class_loader.hpp>
59#include "mujoco_ros2_control_plugins/mujoco_ros2_control_plugins_base.hpp"
60#include "transmission_interface/transmission.hpp"
61#include "transmission_interface/transmission_interface_exception.hpp"
62#include "transmission_interface/transmission_loader.hpp"
63
64#define ROS_DISTRO_HUMBLE (HARDWARE_INTERFACE_VERSION_MAJOR < 3)
65
66// defining these for Humble, because they are defined elsewhere in future versions, and we use them in this file
67#if ROS_DISTRO_HUMBLE
69{
71constexpr char HW_IF_TORQUE[] = "torque";
73constexpr char HW_IF_FORCE[] = "force";
74} // namespace hardware_interface
75#endif
76
77namespace mujoco_ros2_control
78{
80{
81public:
90 ~MujocoSystemInterface() override;
91
92 hardware_interface::CallbackReturn
93// Jazzy introduces a new HarwareComponentInterfaceParams object which doesn't exist in humble. This adds
94// compatibility by switching to the old interface, which behaves similarly
95#if ROS_DISTRO_HUMBLE
96 on_init(const hardware_interface::HardwareInfo& info) override;
97#else
98 on_init(const hardware_interface::HardwareComponentInterfaceParams& params) override;
99#endif
100 std::vector<hardware_interface::StateInterface> export_state_interfaces() override;
101 std::vector<hardware_interface::CommandInterface> export_command_interfaces() override;
102
103 hardware_interface::CallbackReturn on_activate(const rclcpp_lifecycle::State& previous_state) override;
104 hardware_interface::CallbackReturn on_deactivate(const rclcpp_lifecycle::State& previous_state) override;
105
106 hardware_interface::return_type perform_command_mode_switch(const std::vector<std::string>& start_interfaces,
107 const std::vector<std::string>& stop_interfaces) override;
108
109 hardware_interface::return_type read(const rclcpp::Time& time, const rclcpp::Duration& period) override;
110 hardware_interface::return_type write(const rclcpp::Time& time, const rclcpp::Duration& period) override;
111
112// In humble this method doesn't exist, so we just add it back in with the implementation
113#if ROS_DISTRO_HUMBLE
114 const hardware_interface::HardwareInfo& get_hardware_info() const
115 {
116 return info_;
117 }
118#endif
126
140 void get_model(mjModel*& dest);
141
148 void get_data(mjData*& dest);
149
156 void set_data(mjData* mj_data);
157
158protected:
159 rclcpp::Logger get_logger() const;
160
161private:
168 bool register_mujoco_actuators();
169
177 void register_urdf_joints(const hardware_interface::HardwareInfo& info);
178
186 bool register_transmissions(const hardware_interface::HardwareInfo& info);
187
188 bool initialize_initial_positions(const hardware_interface::HardwareInfo& info);
189
198 bool apply_keyframe(const std::string& keyframe_name);
199
250 void register_sensors(const hardware_interface::HardwareInfo& info);
251
258 bool set_override_start_positions(const std::string& override_start_position_file);
259
263 void set_initial_pose();
264
275 void reset_simulation_state(bool fill_initial_state);
276
283 void reset_world_callback(const std::shared_ptr<mujoco_ros2_control_msgs::srv::ResetWorld::Request> request,
284 std::shared_ptr<mujoco_ros2_control_msgs::srv::ResetWorld::Response> response);
285
286 void set_pause_callback(const std::shared_ptr<mujoco_ros2_control_msgs::srv::SetPause::Request> request,
287 std::shared_ptr<mujoco_ros2_control_msgs::srv::SetPause::Response> response);
288
289 void step_simulation_callback(const std::shared_ptr<mujoco_ros2_control_msgs::srv::StepSimulation::Request> request,
290 std::shared_ptr<mujoco_ros2_control_msgs::srv::StepSimulation::Response> response);
291
295 void PhysicsLoop();
296
302 void publish_clock();
303
309 void update_sim_display();
310
312
315 rclcpp::Node::SharedPtr get_node() const;
316
318
324 void load_mujoco_plugins();
325
326 // System information
327 std::string model_path_;
328
329 // MuJoCo data pointers
330 mjModel* mj_model_{ nullptr };
331 mjData* mj_data_{ nullptr };
332
333 // Data container for control data
334 mjData* mj_data_control_{ nullptr };
335
336 // For rendering
337 mjvCamera cam_;
338 mjvOption opt_;
339 mjvPerturb pert_;
340
341 // Logger
342 rclcpp::Logger logger_ = rclcpp::get_logger("MujocoSystemInterface");
343
344 // Speed scaling parameter. if set to >0 then we ignore the value set in the simulate app and instead
345 // attempt to loop at whatever this is set to. If this is <0, then we use the value from the app.
346 double sim_speed_factor_;
347
348 // True when running without a display (no GLFW window)
349 bool headless_{ false };
350
351 // Primary simulate object
352 std::unique_ptr<mujoco::Simulate> sim_;
353
354 // Threads for rendering physics, the UI simulation, and the ROS node
355 std::thread physics_thread_;
356 std::thread ui_thread_;
357
358 // Provides access to ROS interfaces for elements that require it
359 std::shared_ptr<rclcpp::Node> mujoco_node_;
360 std::unique_ptr<rclcpp::executors::MultiThreadedExecutor> executor_;
361 std::thread executor_thread_;
362
363 // Primary clock publisher for the world
364 std::shared_ptr<rclcpp::Publisher<rosgraph_msgs::msg::Clock>> clock_publisher_;
366
367 // Actuators state publisher
368 std::shared_ptr<rclcpp::Publisher<sensor_msgs::msg::JointState>> actuator_state_publisher_ = nullptr;
370 nullptr;
371 sensor_msgs::msg::JointState actuator_state_msg_;
372
373 // Floating base state publisher
374 std::shared_ptr<rclcpp::Publisher<nav_msgs::msg::Odometry>> floating_base_publisher_ = nullptr;
375 realtime_tools::RealtimePublisher<nav_msgs::msg::Odometry>::SharedPtr floating_base_realtime_publisher_ = nullptr;
376 nav_msgs::msg::Odometry floating_base_msg_;
377
378 // Free joint data
379 int free_joint_id_ = -1;
380 int free_joint_qpos_adr_ = -1;
381 int free_joint_qvel_adr_ = -1;
382
383 // Containers for RGB-D cameras
384 std::unique_ptr<MujocoCameras> cameras_;
385
386 // Containers for LIDAR sensors
387 std::unique_ptr<MujocoLidar> lidar_sensors_;
388
389 // Mutex used inside simulate.h for protecting model/data, we keep a reference
390 // here to protect access to shared data.
391 // TODO: It would be far better to put all relevant data into a single container with accessors
392 // in a common location rather than passing around the raw pointer to the mutex, but it would
393 // require more work to pull it out of simulate.h.
394 std::recursive_mutex* sim_mutex_{ nullptr };
395
396 // Data containers for the HW interface
397 std::unordered_map<std::string, hardware_interface::ComponentInfo> joint_hw_info_;
398 std::unordered_map<std::string, hardware_interface::ComponentInfo> sensors_hw_info_;
399
400 // Data containers for the MuJoCo Actuators
401 std::vector<MuJoCoActuatorData> mujoco_actuator_data_;
402
403 // Data containers for the URDF joints
404 std::vector<URDFJointData> urdf_joint_data_;
405
406 // Transmission instances
407 std::unique_ptr<pluginlib::ClassLoader<transmission_interface::TransmissionLoader>> transmission_loader_ = nullptr;
408 std::vector<std::shared_ptr<transmission_interface::Transmission>> transmission_instances_;
409
410 // Plugin loader and instances
411 std::unique_ptr<pluginlib::ClassLoader<mujoco_ros2_control_plugins::MuJoCoROS2ControlPluginBase>> plugin_loader_ =
412 nullptr;
413 std::vector<std::shared_ptr<mujoco_ros2_control_plugins::MuJoCoROS2ControlPluginBase>> plugin_instances_;
414
415 std::vector<FTSensorData> ft_sensor_data_;
416 std::vector<IMUSensorData> imu_sensor_data_;
417
418 bool override_mujoco_actuator_positions_{ false };
419 bool override_urdf_joint_positions_{ false };
420
421 // Reset world service
422 rclcpp::CallbackGroup::SharedPtr reset_world_cb_group_;
423 rclcpp::Service<mujoco_ros2_control_msgs::srv::ResetWorld>::SharedPtr reset_world_service_;
424
425 // Set pause service
426 rclcpp::CallbackGroup::SharedPtr set_pause_cb_group_;
427 rclcpp::Service<mujoco_ros2_control_msgs::srv::SetPause>::SharedPtr set_pause_service_;
428
429 // Step simulation service
430 rclcpp::CallbackGroup::SharedPtr step_simulation_cb_group_;
431 rclcpp::Service<mujoco_ros2_control_msgs::srv::StepSimulation>::SharedPtr step_simulation_service_;
432
433 // Pending steps to execute while paused, and synchronization for blocking callers
434 std::atomic<uint32_t> pending_steps_{ 0 };
435 std::atomic<bool> step_diverged_{ false };
436 std::atomic<bool> steps_interrupted_{ false };
437 std::atomic<bool> keyboard_step_requested_{ false };
438 std::atomic<uint64_t> step_count_{ 0 };
439 std::mutex steps_cv_mutex_;
440 std::condition_variable steps_cv_;
441
442 // Storage for initial state (used for reset_world)
443 std::vector<mjtNum> initial_qpos_;
444 std::vector<mjtNum> initial_qvel_;
445 std::vector<mjtNum> initial_ctrl_;
446 std::string initial_keyframe_ = "";
447};
448
449} // namespace mujoco_ros2_control
Virtual Class to implement when integrating a complex system into ros2_control.
Definition system_interface.hpp:85
Definition mujoco_system_interface.hpp:80
void get_model(mjModel *&dest)
Returns a copy of the MuJoCo model.
Definition mujoco_system_interface.cpp:3143
void set_data(mjData *mj_data)
Sets the MuJoCo data to the provided value.
Definition mujoco_system_interface.cpp:3159
MujocoSystemInterface()
ros2_control SystemInterface to wrap Mujocos Simulate application.
void joint_command_to_actuator_command()
Converts joint commands to actuator commands.
Definition mujoco_system_interface.cpp:1671
void actuator_state_to_joint_state()
Converts actuator states to joint states.
Definition mujoco_system_interface.cpp:1642
std::vector< hardware_interface::StateInterface > export_state_interfaces() override
Exports all state interfaces for this hardware interface.
Definition mujoco_system_interface.cpp:1160
std::vector< hardware_interface::CommandInterface > export_command_interfaces() override
Exports all command interfaces for this hardware interface.
Definition mujoco_system_interface.cpp:1309
hardware_interface::return_type write(const rclcpp::Time &time, const rclcpp::Duration &period) override
Write the current command values to the actuator.
Definition mujoco_system_interface.cpp:1579
hardware_interface::return_type read(const rclcpp::Time &time, const rclcpp::Duration &period) override
Read the current state values from the actuator.
Definition mujoco_system_interface.cpp:1480
hardware_interface::CallbackReturn on_init(const hardware_interface::HardwareInfo &info) override
Initialization of the hardware interface from data parsed from the robot's URDF.
Definition mujoco_system_interface.cpp:743
hardware_interface::return_type perform_command_mode_switch(const std::vector< std::string > &start_interfaces, const std::vector< std::string > &stop_interfaces) override
Definition mujoco_system_interface.cpp:1366
void get_data(mjData *&dest)
Returns a copy of the current MuJoCo data.
Definition mujoco_system_interface.cpp:3149
Definition realtime_publisher.hpp:54
Definition mujoco_system_interface.hpp:69
constexpr char HW_IF_TORQUE[]
Constant defining torque interface name.
Definition mujoco_system_interface.hpp:71
constexpr char HW_IF_FORCE[]
Constant defining force interface name.
Definition mujoco_system_interface.hpp:73
Definition data.hpp:31
This structure stores information about hardware defined in a robot's URDF.
Definition hardware_info.hpp:106