3 #include <mujoco/mujoco.h>
5 #include <builtin_interfaces/msg/time.hpp>
14 mjp_defaultPlugin(&plugin);
16 plugin.name =
"MujocoRosUtils::ClockPublisher";
17 plugin.capabilityflags |= mjPLUGIN_PASSIVE;
19 const char * attributes[] = {
"topic_name",
"publish_rate",
"use_sim_time"};
21 plugin.nattribute =
sizeof(attributes) /
sizeof(attributes[0]);
22 plugin.attributes = attributes;
24 plugin.nstate = +[](
const mjModel *,
28 plugin.nsensordata = +[](
const mjModel *,
33 plugin.needstage = mjSTAGE_POS;
35 plugin.init = +[](
const mjModel * m, mjData * d,
int plugin_id)
42 d->plugin_data[plugin_id] =
reinterpret_cast<uintptr_t
>(plugin_instance);
46 plugin.destroy = +[](mjData * d,
int plugin_id)
48 delete reinterpret_cast<ClockPublisher *
>(d->plugin_data[plugin_id]);
49 d->plugin_data[plugin_id] = 0;
52 plugin.
reset = +[](
const mjModel * m,
double *,
53 void * plugin_data,
int plugin_id)
55 auto * plugin_instance =
reinterpret_cast<class
ClockPublisher *
>(plugin_data);
56 plugin_instance->
reset(m, plugin_id);
59 plugin.compute = +[](
const mjModel * m, mjData * d,
int plugin_id,
int
62 auto * plugin_instance =
reinterpret_cast<class
ClockPublisher *
>(d->plugin_data[plugin_id]);
63 plugin_instance->
compute(m, d, plugin_id);
66 mjp_registerPlugin(&plugin);
72 const char * topic_name_char = mj_getPluginConfig(m, plugin_id,
"topic_name");
73 std::string topic_name =
"";
74 if(strlen(topic_name_char) > 0)
76 topic_name = std::string(topic_name_char);
80 const char * publish_rate_char = mj_getPluginConfig(m, plugin_id,
"publish_rate");
81 mjtNum publish_rate = 100.0;
82 if(strlen(publish_rate_char) > 0)
84 publish_rate = strtod(publish_rate_char,
nullptr);
88 mju_error(
"[ClockPublisher] `publish_rate` must be positive.");
93 const char * use_sim_time_char = mj_getPluginConfig(m, plugin_id,
"use_sim_time");
94 bool use_sim_time =
true;
95 if(strlen(use_sim_time_char) > 0)
97 if(!(strcmp(use_sim_time_char,
"true") == 0 || strcmp(use_sim_time_char,
"false") == 0))
99 mju_error(
"[ClockPublisher] `use_sim_time` must be `true` or `false`.");
102 use_sim_time = (strcmp(use_sim_time_char,
"true") == 0);
105 if(m->body_plugin[0] != plugin_id)
107 mju_error(
"[ClockPublisher] This plugin must be registered in worldbody.");
111 std::cout <<
"[ClockPublisher] Create." << std::endl;
113 return new ClockPublisher(m, d, topic_name, publish_rate, use_sim_time);
118 const std::string & topic_name,
121 : topic_name_(topic_name), publish_skip_(std::max(static_cast<int>(1.0 / (publish_rate * m->opt.timestep)), 1)),
122 use_sim_time_(use_sim_time)
130 char ** argv =
nullptr;
133 rclcpp::init(argc, argv);
135 rclcpp::NodeOptions node_options;
137 nh_ = rclcpp::Node::make_shared(
"mujoco_ros", node_options);
138 pub_ =
nh_->create_publisher<rosgraph_msgs::msg::Clock>(topic_name, 1);
159 rosgraph_msgs::msg::Clock msg;
160 builtin_interfaces::msg::Time time;
161 time.sec =
static_cast<int32_t
>(d->time);
162 time.nanosec =
static_cast<uint32_t
>((d->time - time.sec) * 1e9);
Plugin to publish clock topic.
void reset(const mjModel *m, int plugin_id)
Reset.
std::string topic_name_
Topic name of clock.
rclcpp::Node::SharedPtr nh_
ROS node handle.
int publish_skip_
Iteration interval to skip ROS publish.
static void RegisterPlugin()
Register plugin.
ClockPublisher(ClockPublisher &&)=default
Copy constructor.
void compute(const mjModel *m, mjData *d, int plugin_id)
Compute.
rclcpp::Publisher< rosgraph_msgs::msg::Clock >::SharedPtr pub_
ROS publisher for clock.
static ClockPublisher * Create(const mjModel *m, mjData *d, int plugin_id)
Create an instance.
int sim_cnt_
Iteration count of simulation.