3 #include <geometry_msgs/PoseStamped.h>
4 #include <geometry_msgs/TransformStamped.h>
5 #include <geometry_msgs/TwistStamped.h>
7 #include <mujoco/mujoco.h>
17 mjp_defaultPlugin(&plugin);
19 plugin.name =
"MujocoRosUtils::PosePublisher";
20 plugin.capabilityflags |= mjPLUGIN_SENSOR;
22 const char * attributes[] = {
"frame_id",
"pose_topic_name",
"vel_topic_name",
23 "publish_rate",
"output_tf",
"tf_child_frame_id"};
25 plugin.nattribute =
sizeof(attributes) /
sizeof(attributes[0]);
26 plugin.attributes = attributes;
28 plugin.nstate = +[](
const mjModel *,
32 plugin.nsensordata = +[](
const mjModel *,
37 plugin.needstage = mjSTAGE_VEL;
39 plugin.init = +[](
const mjModel * m, mjData * d,
int plugin_id)
46 d->plugin_data[plugin_id] =
reinterpret_cast<uintptr_t
>(plugin_instance);
50 plugin.destroy = +[](mjData * d,
int plugin_id)
52 delete reinterpret_cast<PosePublisher *
>(d->plugin_data[plugin_id]);
53 d->plugin_data[plugin_id] = 0;
56 plugin.
reset = +[](
const mjModel * m,
double *,
57 void * plugin_data,
int plugin_id)
59 auto * plugin_instance =
reinterpret_cast<class
PosePublisher *
>(plugin_data);
60 plugin_instance->
reset(m, plugin_id);
63 plugin.compute = +[](
const mjModel * m, mjData * d,
int plugin_id,
int
66 auto * plugin_instance =
reinterpret_cast<class
PosePublisher *
>(d->plugin_data[plugin_id]);
67 plugin_instance->
compute(m, d, plugin_id);
70 mjp_registerPlugin(&plugin);
76 const char * frame_id_char = mj_getPluginConfig(m, plugin_id,
"frame_id");
77 std::string frame_id =
"";
78 if(strlen(frame_id_char) > 0)
80 frame_id = std::string(frame_id_char);
84 const char * pose_topic_name_char = mj_getPluginConfig(m, plugin_id,
"pose_topic_name");
85 std::string pose_topic_name =
"";
86 if(strlen(pose_topic_name_char) > 0)
88 pose_topic_name = std::string(pose_topic_name_char);
92 const char * vel_topic_name_char = mj_getPluginConfig(m, plugin_id,
"vel_topic_name");
93 std::string vel_topic_name =
"";
94 if(strlen(vel_topic_name_char) > 0)
96 vel_topic_name = std::string(vel_topic_name_char);
100 const char * publish_rate_char = mj_getPluginConfig(m, plugin_id,
"publish_rate");
101 mjtNum publish_rate = 30.0;
102 if(strlen(publish_rate_char) > 0)
104 publish_rate = strtod(publish_rate_char,
nullptr);
106 if(publish_rate <= 0)
108 mju_error(
"[PosePublisher] `publish_rate` must be positive.");
113 const char * output_tf_char = mj_getPluginConfig(m, plugin_id,
"output_tf");
114 bool output_tf =
false;
115 if(strlen(output_tf_char) > 0)
117 if(!(strcmp(output_tf_char,
"true") == 0 || strcmp(output_tf_char,
"false") == 0))
119 mju_error(
"[PosePublisher] `output_tf` must be `true` or `false`.");
122 output_tf = (strcmp(output_tf_char,
"true") == 0);
126 const char * tf_child_frame_id_char = mj_getPluginConfig(m, plugin_id,
"tf_child_frame_id");
127 std::string tf_child_frame_id =
"";
128 if(strlen(tf_child_frame_id_char) > 0)
130 tf_child_frame_id = std::string(tf_child_frame_id_char);
135 for(; sensor_id < m->nsensor; sensor_id++)
137 if(m->sensor_type[sensor_id] == mjSENS_PLUGIN && m->sensor_plugin[sensor_id] == plugin_id)
142 if(sensor_id == m->nsensor)
144 mju_error(
"[PosePublisher] Plugin not found in sensors.");
147 if(m->sensor_objtype[sensor_id] != mjOBJ_XBODY)
149 mju_error(
"[PosePublisher] Plugin must be attached to a xbody.");
153 std::cout <<
"[PosePublisher] Create." << std::endl;
155 return new PosePublisher(m, d, sensor_id, frame_id, pose_topic_name, vel_topic_name, publish_rate, output_tf,
162 const std::string & frame_id,
163 const std::string & pose_topic_name,
164 const std::string & vel_topic_name,
167 const std::string & tf_child_frame_id)
168 : sensor_id_(sensor_id), body_id_(m->sensor_objid[sensor_id]), frame_id_(frame_id), pose_topic_name_(pose_topic_name),
169 vel_topic_name_(vel_topic_name), publish_skip_(std::max(static_cast<int>(1.0 / (publish_rate * m->opt.timestep)), 1)),
170 output_tf_(output_tf), tf_child_frame_id_(tf_child_frame_id)
172 std::string body_name = std::string(mj_id2name(m, mjOBJ_XBODY,
body_id_));
191 char ** argv =
nullptr;
192 if(!ros::isInitialized())
194 ros::init(argc, argv,
"mujoco_ros", ros::init_options::NoSigintHandler);
197 nh_ = std::make_shared<ros::NodeHandle>();
200 tf_br_ = std::make_shared<tf2_ros::TransformBroadcaster>();
224 ros::Time stamp_now = ros::Time::now();
228 geometry_msgs::TransformStamped msg;
229 msg.header.stamp = stamp_now;
232 msg.transform.translation.x = d->xpos[3 *
body_id_ + 0];
233 msg.transform.translation.y = d->xpos[3 *
body_id_ + 1];
234 msg.transform.translation.z = d->xpos[3 *
body_id_ + 2];
235 msg.transform.rotation.w = d->xquat[4 *
body_id_ + 0];
236 msg.transform.rotation.x = d->xquat[4 *
body_id_ + 1];
237 msg.transform.rotation.y = d->xquat[4 *
body_id_ + 2];
238 msg.transform.rotation.z = d->xquat[4 *
body_id_ + 3];
239 tf_br_->sendTransform(msg);
243 geometry_msgs::PoseStamped pose_msg;
244 pose_msg.header.stamp = stamp_now;
246 pose_msg.pose.position.x = d->xpos[3 *
body_id_ + 0];
247 pose_msg.pose.position.y = d->xpos[3 *
body_id_ + 1];
248 pose_msg.pose.position.z = d->xpos[3 *
body_id_ + 2];
249 pose_msg.pose.orientation.w = d->xquat[4 *
body_id_ + 0];
250 pose_msg.pose.orientation.x = d->xquat[4 *
body_id_ + 1];
251 pose_msg.pose.orientation.y = d->xquat[4 *
body_id_ + 2];
252 pose_msg.pose.orientation.z = d->xquat[4 *
body_id_ + 3];
255 geometry_msgs::TwistStamped vel_msg;
257 mj_objectVelocity(m, d, mjOBJ_XBODY,
body_id_, vel, 0);
258 vel_msg.header.stamp = stamp_now;
260 vel_msg.twist.linear.x = vel[3];
261 vel_msg.twist.linear.y = vel[4];
262 vel_msg.twist.linear.z = vel[5];
263 vel_msg.twist.angular.x = vel[0];
264 vel_msg.twist.angular.y = vel[1];
265 vel_msg.twist.angular.z = vel[2];