mujoco_ros_utils
ActuatorCommand.cpp
Go to the documentation of this file.
1 #include "ActuatorCommand.h"
2 
3 #include <mujoco/mujoco.h>
4 
5 #include <iostream>
6 
7 namespace MujocoRosUtils
8 {
9 
11 {
12  mjpPlugin plugin;
13  mjp_defaultPlugin(&plugin);
14 
15  plugin.name = "MujocoRosUtils::ActuatorCommand";
16  // Allow plugins to be placed on either the body element or the actuator element
17  plugin.capabilityflags |= mjPLUGIN_ACTUATOR;
18  plugin.capabilityflags |= mjPLUGIN_PASSIVE;
19 
20  const char * attributes[] = {"actuator_name", "topic_name"};
21 
22  plugin.nattribute = sizeof(attributes) / sizeof(attributes[0]);
23  plugin.attributes = attributes;
24 
25  plugin.nstate = +[](const mjModel *, // m
26  int // plugin_id
27  ) { return 0; };
28 
29  plugin.nsensordata = +[](const mjModel *, // m
30  int, // plugin_id
31  int // sensor_id
32  ) { return 0; };
33 
34  plugin.needstage = mjSTAGE_VEL;
35 
36  plugin.init = +[](const mjModel * m, mjData * d, int plugin_id)
37  {
38  auto * plugin_instance = ActuatorCommand::Create(m, d, plugin_id);
39  if(!plugin_instance)
40  {
41  return -1;
42  }
43  d->plugin_data[plugin_id] = reinterpret_cast<uintptr_t>(plugin_instance);
44  return 0;
45  };
46 
47  plugin.destroy = +[](mjData * d, int plugin_id)
48  {
49  delete reinterpret_cast<ActuatorCommand *>(d->plugin_data[plugin_id]);
50  d->plugin_data[plugin_id] = 0;
51  };
52 
53  plugin.reset = +[](const mjModel * m, double *, // plugin_state
54  void * plugin_data, int plugin_id)
55  {
56  auto * plugin_instance = reinterpret_cast<class ActuatorCommand *>(plugin_data);
57  plugin_instance->reset(m, plugin_id);
58  };
59 
60  plugin.compute = +[](const mjModel * m, mjData * d, int plugin_id, int // capability_bit
61  )
62  {
63  auto * plugin_instance = reinterpret_cast<class ActuatorCommand *>(d->plugin_data[plugin_id]);
64  plugin_instance->compute(m, d, plugin_id);
65  };
66 
67  mjp_registerPlugin(&plugin);
68 }
69 
70 ActuatorCommand * ActuatorCommand::Create(const mjModel * m, mjData * d, int plugin_id)
71 {
72  // actuator_name
73  const char * actuator_name_char = mj_getPluginConfig(m, plugin_id, "actuator_name");
74  if(strlen(actuator_name_char) == 0)
75  {
76  mju_error("[ActuatorCommand] `actuator_name` is missing.");
77  return nullptr;
78  }
79  int actuator_id = 0;
80  for(; actuator_id < m->nu; actuator_id++)
81  {
82  if(strcmp(actuator_name_char, mj_id2name(m, mjOBJ_ACTUATOR, actuator_id)) == 0)
83  {
84  break;
85  }
86  }
87  if(actuator_id == m->nu)
88  {
89  mju_error("[ActuatorCommand] The actuator with the specified name not found.");
90  return nullptr;
91  }
92 
93  // topic_name
94  const char * topic_name_char = mj_getPluginConfig(m, plugin_id, "topic_name");
95  std::string topic_name = "";
96  if(strlen(topic_name_char) > 0)
97  {
98  topic_name = std::string(topic_name_char);
99  }
100 
101  std::cout << "[ActuatorCommand] Create." << std::endl;
102 
103  return new ActuatorCommand(m, d, actuator_id, topic_name);
104 }
105 
107  mjData *, // d
108  int actuator_id,
109  std::string topic_name)
110 : actuator_id_(actuator_id)
111 {
112  if(topic_name.empty())
113  {
114  std::string actuator_name = std::string(mj_id2name(m, mjOBJ_ACTUATOR, actuator_id));
115  topic_name = "mujoco/" + actuator_name;
116  }
117 
118  int argc = 0;
119  char ** argv = nullptr;
120  if(!ros::isInitialized())
121  {
122  ros::init(argc, argv, "mujoco_ros", ros::init_options::NoSigintHandler);
123  }
124 
125  nh_ = std::make_shared<ros::NodeHandle>();
126  // Use a dedicated queue so as not to call callbacks of other modules
127  nh_->setCallbackQueue(&callbackQueue_);
128  sub_ = nh_->subscribe<std_msgs::Float64>(topic_name, 1, &ActuatorCommand::callback, this);
129 }
130 
131 void ActuatorCommand::reset(const mjModel *, // m
132  int // plugin_id
133 )
134 {
135 }
136 
137 void ActuatorCommand::compute(const mjModel *, // m
138  mjData * d,
139  int // plugin_id
140 )
141 {
142  // Call ROS callback
143  callbackQueue_.callAvailable(ros::WallDuration());
144 
145  // Set actuator command
146  if(!std::isnan(ctrl_))
147  {
148  d->ctrl[actuator_id_] = ctrl_;
149  ctrl_ = std::numeric_limits<mjtNum>::quiet_NaN();
150  }
151 }
152 
153 void ActuatorCommand::callback(const std_msgs::Float64::ConstPtr & msg)
154 {
155  ctrl_ = msg->data;
156 }
157 
158 } // namespace MujocoRosUtils
MujocoRosUtils::ActuatorCommand::ctrl_
mjtNum ctrl_
Actuator command (NaN for no command)
Definition: ActuatorCommand.h:68
ActuatorCommand.h
MujocoRosUtils::ActuatorCommand::ActuatorCommand
ActuatorCommand(ActuatorCommand &&)=default
Copy constructor.
MujocoRosUtils::ActuatorCommand::Create
static ActuatorCommand * Create(const mjModel *m, mjData *d, int plugin_id)
Create an instance.
Definition: ActuatorCommand.cpp:70
MujocoRosUtils::ActuatorCommand::reset
void reset(const mjModel *m, int plugin_id)
Reset.
Definition: ActuatorCommand.cpp:131
MujocoRosUtils::ActuatorCommand::nh_
std::shared_ptr< ros::NodeHandle > nh_
Definition: ActuatorCommand.h:72
MujocoRosUtils::ActuatorCommand::callback
void callback(const std_msgs::Float64::ConstPtr &msg)
Constructor.
Definition: ActuatorCommand.cpp:153
MujocoRosUtils::ActuatorCommand::callbackQueue_
ros::CallbackQueue callbackQueue_
Definition: ActuatorCommand.h:73
MujocoRosUtils::ActuatorCommand::sub_
ros::Subscriber sub_
Definition: ActuatorCommand.h:74
MujocoRosUtils::ActuatorCommand
Plugin to send a command to an actuator via ROS topic.
Definition: ActuatorCommand.h:19
MujocoRosUtils::ActuatorCommand::actuator_id_
int actuator_id_
Actuator ID.
Definition: ActuatorCommand.h:65
MujocoRosUtils::ActuatorCommand::RegisterPlugin
static void RegisterPlugin()
Register plugin.
Definition: ActuatorCommand.cpp:10
MujocoRosUtils::ActuatorCommand::compute
void compute(const mjModel *m, mjData *d, int plugin_id)
Compute.
Definition: ActuatorCommand.cpp:137
MujocoRosUtils
Definition: ActuatorCommand.cpp:7