3 #include <mujoco/mujoco.h>
13 mjp_defaultPlugin(&plugin);
15 plugin.name =
"MujocoRosUtils::SensorPublisher";
16 plugin.capabilityflags |= mjPLUGIN_SENSOR;
18 const char * attributes[] = {
"sensor_name",
"frame_id",
"topic_name",
"publish_rate"};
20 plugin.nattribute =
sizeof(attributes) /
sizeof(attributes[0]);
21 plugin.attributes = attributes;
23 plugin.nstate = +[](
const mjModel *,
27 plugin.nsensordata = +[](
const mjModel *,
33 plugin.needstage = mjSTAGE_ACC;
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)
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
SensorPublisher *
>(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
SensorPublisher *
>(d->plugin_data[plugin_id]);
63 plugin_instance->
compute(m, d, plugin_id);
66 mjp_registerPlugin(&plugin);
72 const char * sensor_name_char = mj_getPluginConfig(m, plugin_id,
"sensor_name");
73 if(strlen(sensor_name_char) == 0)
75 mju_error(
"[SensorPublisher] `sensor_name` is missing.");
79 for(; sensor_id < m->nsensor; sensor_id++)
81 if(strcmp(sensor_name_char, mj_id2name(m, mjOBJ_SENSOR, sensor_id)) == 0)
86 if(sensor_id == m->nsensor)
88 mju_error(
"[SensorCommand] The sensor with the specified name not found.");
94 int sensor_dim = m->sensor_dim[sensor_id];
99 else if(sensor_dim == 3)
101 if(m->sensor_type[sensor_id] == mjSENS_FRAMEPOS)
110 else if(sensor_dim == 4)
116 mju_error(
"[SensorPublisher] Unsupported sensor data dimensions: %d.", sensor_dim);
121 const char * frame_id_char = mj_getPluginConfig(m, plugin_id,
"frame_id");
122 std::string frame_id =
"";
123 if(strlen(frame_id_char) > 0)
125 frame_id = std::string(frame_id_char);
129 const char * topic_name_char = mj_getPluginConfig(m, plugin_id,
"topic_name");
130 std::string topic_name =
"";
131 if(strlen(topic_name_char) > 0)
133 topic_name = std::string(topic_name_char);
137 const char * publish_rate_char = mj_getPluginConfig(m, plugin_id,
"publish_rate");
138 mjtNum publish_rate = 30.0;
139 if(strlen(publish_rate_char) > 0)
141 publish_rate = strtod(publish_rate_char,
nullptr);
143 if(publish_rate <= 0)
145 mju_error(
"[SensorPublisher] `publish_rate` must be positive.");
149 std::cout <<
"[SensorPublisher] Create." << std::endl;
151 return new SensorPublisher(m, d, sensor_id, msg_type, frame_id, topic_name, publish_rate);
158 const std::string & frame_id,
159 const std::string & topic_name,
161 : sensor_id_(sensor_id), msg_type_(msg_type), frame_id_(frame_id), topic_name_(topic_name),
162 publish_skip_(std::max(static_cast<int>(1.0 / (publish_rate * m->opt.timestep)), 1))
170 std::string sensor_name = std::string(mj_id2name(m, mjOBJ_SENSOR,
sensor_id_));
175 char ** argv =
nullptr;
178 rclcpp::init(argc, argv);
180 rclcpp::NodeOptions node_options;
182 nh_ = rclcpp::Node::make_shared(
"mujoco_ros", node_options);
216 std_msgs::msg::Header header;
217 header.stamp =
nh_->get_clock()->now();
223 mujoco_ros_utils::msg::ScalarStamped msg;
225 msg.value.data = d->sensordata[sensor_adr];
226 std::dynamic_pointer_cast<rclcpp::Publisher<mujoco_ros_utils::msg::ScalarStamped>>(
pub_)->publish(msg);
230 geometry_msgs::msg::PointStamped msg;
232 msg.point.x = d->sensordata[sensor_adr + 0];
233 msg.point.y = d->sensordata[sensor_adr + 1];
234 msg.point.z = d->sensordata[sensor_adr + 2];
235 std::dynamic_pointer_cast<rclcpp::Publisher<geometry_msgs::msg::PointStamped>>(
pub_)->publish(msg);
239 geometry_msgs::msg::Vector3Stamped msg;
241 msg.vector.x = d->sensordata[sensor_adr + 0];
242 msg.vector.y = d->sensordata[sensor_adr + 1];
243 msg.vector.z = d->sensordata[sensor_adr + 2];
244 std::dynamic_pointer_cast<rclcpp::Publisher<geometry_msgs::msg::Vector3Stamped>>(
pub_)->publish(msg);
248 geometry_msgs::msg::QuaternionStamped msg;
250 msg.quaternion.w = d->sensordata[sensor_adr + 0];
251 msg.quaternion.x = d->sensordata[sensor_adr + 1];
252 msg.quaternion.y = d->sensordata[sensor_adr + 2];
253 msg.quaternion.z = d->sensordata[sensor_adr + 3];
254 std::dynamic_pointer_cast<rclcpp::Publisher<geometry_msgs::msg::QuaternionStamped>>(
pub_)->publish(msg);
Plugin to publish sensor data.
std::string topic_name_
Topic name.
rclcpp::Node::SharedPtr nh_
ROS node handle.
SensorPublisher(SensorPublisher &&)=default
Copy constructor.
int publish_skip_
Iteration interval to skip ROS publish.
static void RegisterPlugin()
Register plugin.
static SensorPublisher * Create(const mjModel *m, mjData *d, int plugin_id)
Create an instance.
int sim_cnt_
Iteration count of simulation.
MessageType msg_type_
Type of ROS message.
std::string frame_id_
Frame ID of message header.
enum MujocoRosUtils::SensorPublisher::MessageType_ MessageType
Type of ROS message.
rclcpp::PublisherBase::SharedPtr pub_
ROS publisher.
void reset(const mjModel *m, int plugin_id)
Reset.
void compute(const mjModel *m, mjData *d, int plugin_id)
Compute.
@ MsgQuaternion
Quaternion.