mujoco_ros_utils
PosePublisher.cpp
Go to the documentation of this file.
1 #include "PosePublisher.h"
2 
3 #include <geometry_msgs/PoseStamped.h>
4 #include <geometry_msgs/TransformStamped.h>
5 #include <geometry_msgs/TwistStamped.h>
6 
7 #include <mujoco/mujoco.h>
8 
9 #include <iostream>
10 
11 namespace MujocoRosUtils
12 {
13 
15 {
16  mjpPlugin plugin;
17  mjp_defaultPlugin(&plugin);
18 
19  plugin.name = "MujocoRosUtils::PosePublisher";
20  plugin.capabilityflags |= mjPLUGIN_SENSOR;
21 
22  const char * attributes[] = {"frame_id", "pose_topic_name", "vel_topic_name",
23  "publish_rate", "output_tf", "tf_child_frame_id"};
24 
25  plugin.nattribute = sizeof(attributes) / sizeof(attributes[0]);
26  plugin.attributes = attributes;
27 
28  plugin.nstate = +[](const mjModel *, // m
29  int // plugin_id
30  ) { return 0; };
31 
32  plugin.nsensordata = +[](const mjModel *, // m
33  int, // plugin_id
34  int // sensor_id
35  ) { return 0; };
36 
37  plugin.needstage = mjSTAGE_VEL;
38 
39  plugin.init = +[](const mjModel * m, mjData * d, int plugin_id)
40  {
41  auto * plugin_instance = PosePublisher::Create(m, d, plugin_id);
42  if(!plugin_instance)
43  {
44  return -1;
45  }
46  d->plugin_data[plugin_id] = reinterpret_cast<uintptr_t>(plugin_instance);
47  return 0;
48  };
49 
50  plugin.destroy = +[](mjData * d, int plugin_id)
51  {
52  delete reinterpret_cast<PosePublisher *>(d->plugin_data[plugin_id]);
53  d->plugin_data[plugin_id] = 0;
54  };
55 
56  plugin.reset = +[](const mjModel * m, double *, // plugin_state
57  void * plugin_data, int plugin_id)
58  {
59  auto * plugin_instance = reinterpret_cast<class PosePublisher *>(plugin_data);
60  plugin_instance->reset(m, plugin_id);
61  };
62 
63  plugin.compute = +[](const mjModel * m, mjData * d, int plugin_id, int // capability_bit
64  )
65  {
66  auto * plugin_instance = reinterpret_cast<class PosePublisher *>(d->plugin_data[plugin_id]);
67  plugin_instance->compute(m, d, plugin_id);
68  };
69 
70  mjp_registerPlugin(&plugin);
71 }
72 
73 PosePublisher * PosePublisher::Create(const mjModel * m, mjData * d, int plugin_id)
74 {
75  // frame_id
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)
79  {
80  frame_id = std::string(frame_id_char);
81  }
82 
83  // pose_topic_name
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)
87  {
88  pose_topic_name = std::string(pose_topic_name_char);
89  }
90 
91  // vel_topic_name
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)
95  {
96  vel_topic_name = std::string(vel_topic_name_char);
97  }
98 
99  // publish_rate
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)
103  {
104  publish_rate = strtod(publish_rate_char, nullptr);
105  }
106  if(publish_rate <= 0)
107  {
108  mju_error("[PosePublisher] `publish_rate` must be positive.");
109  return nullptr;
110  }
111 
112  // output_tf
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)
116  {
117  if(!(strcmp(output_tf_char, "true") == 0 || strcmp(output_tf_char, "false") == 0))
118  {
119  mju_error("[PosePublisher] `output_tf` must be `true` or `false`.");
120  return nullptr;
121  }
122  output_tf = (strcmp(output_tf_char, "true") == 0);
123  }
124 
125  // tf_child_frame_id
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)
129  {
130  tf_child_frame_id = std::string(tf_child_frame_id_char);
131  }
132 
133  // Set sensor_id
134  int sensor_id = 0;
135  for(; sensor_id < m->nsensor; sensor_id++)
136  {
137  if(m->sensor_type[sensor_id] == mjSENS_PLUGIN && m->sensor_plugin[sensor_id] == plugin_id)
138  {
139  break;
140  }
141  }
142  if(sensor_id == m->nsensor)
143  {
144  mju_error("[PosePublisher] Plugin not found in sensors.");
145  return nullptr;
146  }
147  if(m->sensor_objtype[sensor_id] != mjOBJ_XBODY)
148  {
149  mju_error("[PosePublisher] Plugin must be attached to a xbody.");
150  return nullptr;
151  }
152 
153  std::cout << "[PosePublisher] Create." << std::endl;
154 
155  return new PosePublisher(m, d, sensor_id, frame_id, pose_topic_name, vel_topic_name, publish_rate, output_tf,
156  tf_child_frame_id);
157 }
158 
160  mjData *, // d
161  int sensor_id,
162  const std::string & frame_id,
163  const std::string & pose_topic_name,
164  const std::string & vel_topic_name,
165  mjtNum publish_rate,
166  bool output_tf,
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)
171 {
172  std::string body_name = std::string(mj_id2name(m, mjOBJ_XBODY, body_id_));
173  if(frame_id_.empty())
174  {
175  frame_id_ = "map";
176  }
177  if(pose_topic_name_.empty())
178  {
179  pose_topic_name_ = "mujoco/" + body_name + "/pose";
180  }
181  if(vel_topic_name_.empty())
182  {
183  vel_topic_name_ = "mujoco/" + body_name + "/vel";
184  }
185  if(tf_child_frame_id_.empty())
186  {
187  tf_child_frame_id_ = body_name;
188  }
189 
190  int argc = 0;
191  char ** argv = nullptr;
192  if(!ros::isInitialized())
193  {
194  ros::init(argc, argv, "mujoco_ros", ros::init_options::NoSigintHandler);
195  }
196 
197  nh_ = std::make_shared<ros::NodeHandle>();
198  if(output_tf_)
199  {
200  tf_br_ = std::make_shared<tf2_ros::TransformBroadcaster>();
201  }
202  else
203  {
204  pose_pub_ = nh_->advertise<geometry_msgs::PoseStamped>(pose_topic_name_, 1);
205  vel_pub_ = nh_->advertise<geometry_msgs::TwistStamped>(vel_topic_name_, 1);
206  }
207 }
208 
209 void PosePublisher::reset(const mjModel *, // m
210  int // plugin_id
211 )
212 {
213 }
214 
215 void PosePublisher::compute(const mjModel * m, mjData * d, int // plugin_id
216 )
217 {
218  sim_cnt_++;
219  if(sim_cnt_ % publish_skip_ != 0)
220  {
221  return;
222  }
223 
224  ros::Time stamp_now = ros::Time::now();
225 
226  if(output_tf_)
227  {
228  geometry_msgs::TransformStamped msg;
229  msg.header.stamp = stamp_now;
230  msg.header.frame_id = frame_id_;
231  msg.child_frame_id = tf_child_frame_id_;
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);
240  }
241  else
242  {
243  geometry_msgs::PoseStamped pose_msg;
244  pose_msg.header.stamp = stamp_now;
245  pose_msg.header.frame_id = frame_id_;
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];
253  pose_pub_.publish(pose_msg);
254 
255  geometry_msgs::TwistStamped vel_msg;
256  mjtNum vel[6];
257  mj_objectVelocity(m, d, mjOBJ_XBODY, body_id_, vel, 0);
258  vel_msg.header.stamp = stamp_now;
259  vel_msg.header.frame_id = frame_id_;
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];
266  vel_pub_.publish(vel_msg);
267  }
268 }
269 
270 } // namespace MujocoRosUtils
MujocoRosUtils::PosePublisher::PosePublisher
PosePublisher(PosePublisher &&)=default
Copy constructor.
MujocoRosUtils::PosePublisher::RegisterPlugin
static void RegisterPlugin()
Register plugin.
Definition: PosePublisher.cpp:14
MujocoRosUtils::PosePublisher::nh_
std::shared_ptr< ros::NodeHandle > nh_
ROS node handle.
Definition: PosePublisher.h:77
MujocoRosUtils::PosePublisher::output_tf_
bool output_tf_
Whether to broadcast TF.
Definition: PosePublisher.h:101
MujocoRosUtils::PosePublisher::tf_child_frame_id_
std::string tf_child_frame_id_
Child frame ID for TF.
Definition: PosePublisher.h:104
MujocoRosUtils::PosePublisher::compute
void compute(const mjModel *m, mjData *d, int plugin_id)
Compute.
Definition: PosePublisher.cpp:215
MujocoRosUtils::PosePublisher::Create
static PosePublisher * Create(const mjModel *m, mjData *d, int plugin_id)
Create an instance.
Definition: PosePublisher.cpp:73
MujocoRosUtils::PosePublisher
Plugin to publish topics or broadcast TF of pose and velocity of the body.
Definition: PosePublisher.h:17
MujocoRosUtils::PosePublisher::sim_cnt_
int sim_cnt_
Iteration count of simulation.
Definition: PosePublisher.h:107
MujocoRosUtils::PosePublisher::pose_topic_name_
std::string pose_topic_name_
Topic name of pose.
Definition: PosePublisher.h:92
PosePublisher.h
MujocoRosUtils::PosePublisher::tf_br_
std::shared_ptr< tf2_ros::TransformBroadcaster > tf_br_
TF broadcaster.
Definition: PosePublisher.h:86
MujocoRosUtils::PosePublisher::reset
void reset(const mjModel *m, int plugin_id)
Reset.
Definition: PosePublisher.cpp:209
MujocoRosUtils::PosePublisher::vel_pub_
ros::Publisher vel_pub_
ROS publisher for velocity.
Definition: PosePublisher.h:83
MujocoRosUtils::PosePublisher::frame_id_
std::string frame_id_
Frame ID of topics header or TF parent.
Definition: PosePublisher.h:89
MujocoRosUtils::PosePublisher::body_id_
int body_id_
Body ID.
Definition: PosePublisher.h:74
MujocoRosUtils::PosePublisher::pose_pub_
ros::Publisher pose_pub_
ROS publisher for pose.
Definition: PosePublisher.h:80
MujocoRosUtils::PosePublisher::publish_skip_
int publish_skip_
Iteration interval to skip ROS publish.
Definition: PosePublisher.h:98
MujocoRosUtils::PosePublisher::vel_topic_name_
std::string vel_topic_name_
Topic name of velocity.
Definition: PosePublisher.h:95
MujocoRosUtils
Definition: ActuatorCommand.cpp:7