3 #include <mujoco/mujoco.h> 
   13   mjp_defaultPlugin(&plugin);
 
   15   plugin.name = 
"MujocoRosUtils::ExternalForce";
 
   16   plugin.capabilityflags |= mjPLUGIN_PASSIVE;
 
   18   const char * attributes[] = {
"topic_name", 
"vis_scale"};
 
   20   plugin.nattribute = 
sizeof(attributes) / 
sizeof(attributes[0]);
 
   21   plugin.attributes = attributes;
 
   23   plugin.nstate = +[](
const mjModel *, 
 
   27   plugin.nsensordata = +[](
const mjModel *, 
 
   32   plugin.needstage = mjSTAGE_ACC;
 
   34   plugin.init = +[](
const mjModel * m, mjData * d, 
int plugin_id)
 
   41     d->plugin_data[plugin_id] = 
reinterpret_cast<uintptr_t
>(plugin_instance);
 
   45   plugin.destroy = +[](mjData * d, 
int plugin_id)
 
   47     delete reinterpret_cast<ExternalForce *
>(d->plugin_data[plugin_id]);
 
   48     d->plugin_data[plugin_id] = 0;
 
   51   plugin.
reset = +[](
const mjModel * m, 
double *, 
 
   52                      void * plugin_data, 
int plugin_id)
 
   54     auto * plugin_instance = 
reinterpret_cast<class 
ExternalForce *
>(plugin_data);
 
   55     plugin_instance->
reset(m, plugin_id);
 
   58   plugin.compute = +[](
const mjModel * m, mjData * d, 
int plugin_id, 
int  
   61     auto * plugin_instance = 
reinterpret_cast<class 
ExternalForce *
>(d->plugin_data[plugin_id]);
 
   62     plugin_instance->
compute(m, d, plugin_id);
 
   65   plugin.visualize = +[](
const mjModel * m, mjData * d, 
const mjvOption * opt, mjvScene * scn, 
int plugin_id)
 
   67     auto * plugin_instance = 
reinterpret_cast<class 
ExternalForce *
>(d->plugin_data[plugin_id]);
 
   68     plugin_instance->
visualize(m, d, opt, scn, plugin_id);
 
   71   mjp_registerPlugin(&plugin);
 
   77   const char * topic_name_char = mj_getPluginConfig(m, plugin_id, 
"topic_name");
 
   78   std::string topic_name = 
"";
 
   79   if(strlen(topic_name_char) > 0)
 
   81     topic_name = std::string(topic_name_char);
 
   85   const char * vis_scale_char = mj_getPluginConfig(m, plugin_id, 
"vis_scale");
 
   86   mjtNum vis_scale = 0.1;
 
   87   if(strlen(vis_scale_char) > 0)
 
   89     vis_scale = strtod(vis_scale_char, 
nullptr);
 
   94   for(; body_id < m->nbody; body_id++)
 
   96     if(m->body_plugin[body_id] == plugin_id)
 
  101   if(body_id == m->nbody)
 
  103     mju_error(
"[ExternalForce] Plugin not found in bodies.");
 
  107   std::cout << 
"[ExternalForce] Create." << std::endl;
 
  109   return new ExternalForce(m, d, body_id, topic_name, vis_scale);
 
  115                              const std::string & topic_name,
 
  117 : body_id_(body_id), topic_name_(topic_name), vis_scale_(vis_scale)
 
  125   char ** argv = 
nullptr;
 
  128     rclcpp::init(argc, argv);
 
  130   rclcpp::NodeOptions node_options;
 
  132   nh_ = rclcpp::Node::make_shared(
"mujoco_ros", node_options);
 
  133   sub_ = 
nh_->create_subscription<mujoco_ros_utils::msg::ExternalForce>(
 
  136   executor_ = std::make_shared<rclcpp::executors::SingleThreadedExecutor>();
 
  153   executor_->spin_once(std::chrono::seconds(0));
 
  155   if(
end_time_ >= 0 && end_time_ <= d->time)
 
  167   pos_local[0] = 
msg_->pos.x;
 
  168   pos_local[1] = 
msg_->pos.y;
 
  169   pos_local[2] = 
msg_->pos.z;
 
  171   force[0] = 
msg_->force.x;
 
  172   force[1] = 
msg_->force.y;
 
  173   force[2] = 
msg_->force.z;
 
  175   mju_rotVecMat(pos_world, pos_local, d->xmat + 9 * 
body_id_);
 
  176   mju_addTo3(pos_world, d->xpos + 3 * 
body_id_);
 
  177   mjtNum moment_arm[3];
 
  178   mju_sub3(moment_arm, pos_world, d->xipos + 3 * 
body_id_);
 
  180   mju_cross(moment, moment_arm, force);
 
  182   mjtNum * data_force = d->xfrc_applied + 6 * 
body_id_;
 
  183   mjtNum * data_moment = d->xfrc_applied + 6 * 
body_id_ + 3;
 
  184   mju_copy3(data_force, force);
 
  185   mju_copy3(data_moment, moment);
 
  210 #if mjVERSION_HEADER >= 300 
  217   pos_local[0] = 
msg_->pos.x;
 
  218   pos_local[1] = 
msg_->pos.y;
 
  219   pos_local[2] = 
msg_->pos.z;
 
  221   force[0] = 
msg_->force.x;
 
  222   force[1] = 
msg_->force.y;
 
  223   force[2] = 
msg_->force.z;
 
  225   mju_rotVecMat(pos_world, pos_local, d->xmat + 9 * 
body_id_);
 
  226   mju_addTo3(pos_world, d->xpos + 3 * 
body_id_);
 
  228   mju_addScl3(arrow_end, pos_world, force, 
vis_scale_);
 
  229   float rgba[4] = {1.0, 0.0, 0.0, 1.0};
 
  230   constexpr mjtNum width = 0.01;
 
  231   mjvGeom * force_geom = scn->geoms + scn->ngeom;
 
  232   mjv_initGeom(force_geom, mjGEOM_NONE, NULL, NULL, NULL, rgba);
 
  233   mjv_makeConnector(force_geom, mjGEOM_ARROW, width, pos_world[0], pos_world[1], pos_world[2], arrow_end[0],
 
  234                     arrow_end[1], arrow_end[2]);
 
  235   force_geom->objtype = mjOBJ_UNKNOWN;
 
  236   force_geom->objid = -1;
 
  237   force_geom->category = mjCAT_DECOR;
 
  238   force_geom->segid = scn->ngeom;
 
  241 #if mjVERSION_HEADER >= 300 
  252     mju_warning(
"[ExternalForce] New message received while processing a previous message. Ignore the new message.");
 
  255   msg_ = std::make_shared<mujoco_ros_utils::msg::ExternalForce>(*msg);
 
Plugin to apply external force.
std::shared_ptr< mujoco_ros_utils::msg::ExternalForce > msg_
External force message.
static ExternalForce * Create(const mjModel *m, mjData *d, int plugin_id)
Create an instance.
void visualize(const mjModel *m, mjData *d, const mjvOption *opt, mjvScene *scn, int plugin_id)
Visualize.
rclcpp::Subscription< mujoco_ros_utils::msg::ExternalForce >::SharedPtr sub_
ROS publisher for external force.
ExternalForce(ExternalForce &&)=default
Copy constructor.
mjtNum end_time_
End time to apply external force (-1 if no external force is applied)
void reset(const mjModel *m, int plugin_id)
Reset.
std::string topic_name_
Topic name of external force.
rclcpp::Node::SharedPtr nh_
ROS node handle.
static void RegisterPlugin()
Register plugin.
rclcpp::executors::SingleThreadedExecutor::SharedPtr executor_
ROS callback queue.
mjtNum vis_scale_
Arrow length scale (negative value for no visualization)
void callback(const mujoco_ros_utils::msg::ExternalForce::SharedPtr msg)
Constructor.
void compute(const mjModel *m, mjData *d, int plugin_id)
Compute.