ign_system.cpp
Go to the documentation of this file.
1 // Copyright 2022 The ros_control team.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
17 #include <ignition/gazebo/components/JointForce.hh>
18 #include <ignition/gazebo/components/JointForceCmd.hh>
19 #include <ignition/gazebo/components/JointPosition.hh>
20 #include <ignition/gazebo/components/JointVelocity.hh>
21 #include <ignition/gazebo/components/JointVelocityCmd.hh>
22 #include <ignition/gazebo/components/Name.hh>
23 #include <ignition/gazebo/components/ParentEntity.hh>
24 #include <ignition/transport/Node.hh>
25 
26 #include <limits>
27 #include <map>
28 #include <memory>
29 #include <string>
30 #include <utility>
31 #include <vector>
32 
34 
35 struct jointData
36 {
38  std::string name;
39 
42 
45 
47  double joint_effort;
48 
51 
54 
57 
59  ignition::gazebo::Entity sim_joint;
60 
63 };
64 
66 {
67 public:
68  IgnitionSystemPrivate() = default;
69 
70  ~IgnitionSystemPrivate() = default;
72  size_t n_dof_;
73 
76 
78  std::vector<struct jointData> joints_;
79 
82  ignition::gazebo::EntityComponentManager* ecm_;
83 
86 
88  ignition::transport::Node node;
89 };
90 
91 namespace ign_ros_control
92 {
93 
95  : dataPtr(nullptr)
96 {
97 
98 }
99 
101 
103  std::map<std::string, ignition::gazebo::Entity> & enableJoints,
104  ignition::gazebo::EntityComponentManager & ecm,
105  std::vector<transmission_interface::TransmissionInfo> transmissions,
106  int & update_rate)
107 {
108  this->dataPtr = std::make_unique<IgnitionSystemPrivate>();
109  this->dataPtr->last_update_sim_time_ros_ = ros::Time::now();
110 
111  this->nh_ = model_nh;
112  this->dataPtr->ecm_ = &ecm;
113  this->dataPtr->n_dof_ = transmissions.size();
114  this->dataPtr->update_rate_ = update_rate;
115 
116  ROS_DEBUG("[Ignition ROS Control] n_dof_ %lu", this->dataPtr->n_dof_);
117 
118  this->dataPtr->joints_.resize(this->dataPtr->n_dof_);
119 
120  if (this->dataPtr->n_dof_ == 0) {
121  ROS_WARN_STREAM("[Ignition ROS Control] There is not joint available");
122  return false;
123  }
124 
125  std::string joint_name;
126  for (unsigned int j = 0; j < this->dataPtr->n_dof_; j++) {
127  joint_name = this->dataPtr->joints_[j].name = transmissions[j].joints_[0].name_;
128 
129  ignition::gazebo::Entity simjoint = enableJoints[joint_name];
130  this->dataPtr->joints_[j].sim_joint = simjoint;
131 
132  // Create joint position component if one doesn't exist
133  if (!ecm.EntityHasComponentType(
134  simjoint,
135  ignition::gazebo::components::JointPosition().TypeId()))
136  {
137  ecm.CreateComponent(simjoint, ignition::gazebo::components::JointPosition());
138  }
139 
140  // Create joint velocity component if one doesn't exist
141  if (!ecm.EntityHasComponentType(
142  simjoint,
143  ignition::gazebo::components::JointVelocity().TypeId()))
144  {
145  ecm.CreateComponent(simjoint, ignition::gazebo::components::JointVelocity());
146  }
147 
148  // Create joint force component if one doesn't exist
149  if (!ecm.EntityHasComponentType(
150  simjoint,
151  ignition::gazebo::components::JointForce().TypeId()))
152  {
153  ecm.CreateComponent(simjoint, ignition::gazebo::components::JointForce());
154  }
155 
156  // Accept this joint and continue configuration
157  ROS_INFO_STREAM("[Ignition ROS Control] Loading joint: " << joint_name);
158 
159  // Add data from transmission
160  this->dataPtr->joints_[j].joint_position = 0.0;
161  this->dataPtr->joints_[j].joint_velocity = 0.0;
162  this->dataPtr->joints_[j].joint_effort = 0.0; // N/m for continuous joints
163  this->dataPtr->joints_[j].joint_effort_cmd = 0.0;
164  this->dataPtr->joints_[j].joint_position_cmd = 0.0;
165  this->dataPtr->joints_[j].joint_velocity_cmd = 0.0;
166 
167  std::vector<std::string> joint_interfaces = transmissions[j].joints_[0].hardware_interfaces_;
168 
169  if (joint_interfaces.empty() &&
170  !(transmissions[j].actuators_.empty()) &&
171  !(transmissions[j].actuators_[0].hardware_interfaces_.empty()))
172  {
173  // TODO: Deprecate HW interface specification in actuators in ROS J
174  joint_interfaces = transmissions[j].actuators_[0].hardware_interfaces_;
175  ROS_WARN_STREAM("[Ignition ROS Control] The <hardware_interface> element of tranmission " <<
176  transmissions[j].name_ << " should be nested inside the <joint> element, not <actuator>. " <<
177  "The transmission will be properly loaded, but please update " <<
178  "your robot model to remain compatible with future versions of the plugin.");
179  }
180  if (joint_interfaces.empty())
181  {
182  ROS_WARN_STREAM("[Ignition ROS Control] Joint " << transmissions[j].joints_[0].name_ <<
183  " of transmission " << transmissions[j].name_ << " does not specify any hardware interface. " <<
184  "Not adding it to the robot hardware simulation.");
185  continue;
186  }
187  else if (joint_interfaces.size() > 1)
188  {
189  ROS_WARN_STREAM("[Ignition ROS Control] Joint " << transmissions[j].joints_[0].name_ <<
190  " of transmission " << transmissions[j].name_ << " specifies multiple hardware interfaces. " <<
191  "Currently the default robot hardware simulation interface only supports one. Using the first entry");
192  //continue;
193  }
194 
195  const std::string& hardware_interface = joint_interfaces.front();
196 
197  // Create joint state interface for all joints
199  joint_name, &this->dataPtr->joints_[j].joint_position, &this->dataPtr->joints_[j].joint_velocity, &this->dataPtr->joints_[j].joint_effort));
200 
201  // Decide what kind of command interface this actuator/joint has
202  hardware_interface::JointHandle joint_handle;
203  if(hardware_interface == "EffortJointInterface" || hardware_interface == "hardware_interface/EffortJointInterface")
204  {
205  // Create effort joint interface
206  this->dataPtr->joints_[j].joint_control_method = EFFORT;
207  joint_handle = hardware_interface::JointHandle(js_interface_.getHandle(joint_name),
208  &this->dataPtr->joints_[j].joint_effort_cmd);
209  ej_interface_.registerHandle(joint_handle);
210  }
211  else if(hardware_interface == "PositionJointInterface" || hardware_interface == "hardware_interface/PositionJointInterface")
212  {
213  // Create position joint interface
214  this->dataPtr->joints_[j].joint_control_method = POSITION;
215  joint_handle = hardware_interface::JointHandle(js_interface_.getHandle(joint_name),
216  &this->dataPtr->joints_[j].joint_position_cmd);
217  pj_interface_.registerHandle(joint_handle);
218  }
219  else if(hardware_interface == "VelocityJointInterface" || hardware_interface == "hardware_interface/VelocityJointInterface")
220  {
221  // Create velocity joint interface
222  this->dataPtr->joints_[j].joint_control_method = VELOCITY;
223  joint_handle = hardware_interface::JointHandle(js_interface_.getHandle(joint_name),
224  &this->dataPtr->joints_[j].joint_velocity_cmd);
225  vj_interface_.registerHandle(joint_handle);
226  }
227  else
228  {
229  ROS_FATAL_STREAM_NAMED("default_robot_hw_sim","No matching hardware interface found for '"
230  << hardware_interface << "' while loading interfaces for " << joint_name );
231  return false;
232  }
233 
234  if(hardware_interface == "EffortJointInterface" || hardware_interface == "PositionJointInterface" || hardware_interface == "VelocityJointInterface") {
235  ROS_WARN_STREAM("[Ignition ROS Control] Deprecated syntax, please prepend 'hardware_interface/' to '" << hardware_interface << "' within the <hardwareInterface> tag in joint '" << joint_name << "'.");
236  }
237  }
238 
239  // Register interfaces
244 
245  return true;
246 }
247 
249 {
250  for (unsigned int i = 0; i < this->dataPtr->joints_.size(); ++i) {
251  // Get the joint velocity
252  const auto * jointVelocity =
253  this->dataPtr->ecm_->Component<ignition::gazebo::components::JointVelocity>(
254  this->dataPtr->joints_[i].sim_joint);
255 
256  // TODO Same issue as in https://github.com/ignitionrobotics/ign_ros2_control/blob/main/ign_ros2_control/src/ign_system.cpp#L413-L417
257  // Get the joint force
258  //const auto * jointForce =
259  // this->dataPtr->ecm_->Component<ignition::gazebo::components::JointForce>(
260  // this->dataPtr->joints_[i].sim_joint);
261 
262  // Get the joint position
263  const auto * jointPositions =
264  this->dataPtr->ecm_->Component<ignition::gazebo::components::JointPosition>(
265  this->dataPtr->joints_[i].sim_joint);
266 
267  this->dataPtr->joints_[i].joint_position = jointPositions->Data()[0];
268  this->dataPtr->joints_[i].joint_velocity = jointVelocity->Data()[0];
269  //this->dataPtr->joints_[i].joint_effort = jointForce->Data()[0];
270  }
271 }
272 
274 {
275 
276  for (unsigned int i = 0; i < this->dataPtr->joints_.size(); ++i) {
277  if (this->dataPtr->joints_[i].joint_control_method == VELOCITY) {
278  if (!this->dataPtr->ecm_->Component<ignition::gazebo::components::JointVelocityCmd>(
279  this->dataPtr->joints_[i].sim_joint))
280  {
281  this->dataPtr->ecm_->CreateComponent(
282  this->dataPtr->joints_[i].sim_joint,
283  ignition::gazebo::components::JointVelocityCmd({0}));
284  } else {
285 
286  double targetVel = this->dataPtr->joints_[i].joint_velocity_cmd;
287  auto vel =
288  this->dataPtr->ecm_->Component<ignition::gazebo::components::JointVelocityCmd>(
289  this->dataPtr->joints_[i].sim_joint);
290 
291  if (vel == nullptr) {
292  this->dataPtr->ecm_->CreateComponent(
293  this->dataPtr->joints_[i].sim_joint,
294  ignition::gazebo::components::JointVelocityCmd({targetVel}));
295  } else if (!vel->Data().empty()) {
296  vel->Data()[0] = targetVel;
297  }
298  }
299  }
300 
301  if (this->dataPtr->joints_[i].joint_control_method == POSITION) {
302  // Get error in position
303  double error;
304  error = (this->dataPtr->joints_[i].joint_position -
305  this->dataPtr->joints_[i].joint_position_cmd) * this->dataPtr->update_rate_;
306  // Calculate target velocity
307  double targetVel = -error;
308 
309  auto vel =
310  this->dataPtr->ecm_->Component<ignition::gazebo::components::JointVelocityCmd>(
311  this->dataPtr->joints_[i].sim_joint);
312 
313  if (vel == nullptr) {
314  this->dataPtr->ecm_->CreateComponent(
315  this->dataPtr->joints_[i].sim_joint,
316  ignition::gazebo::components::JointVelocityCmd({targetVel}));
317  } else if (!vel->Data().empty()) {
318  vel->Data()[0] = targetVel;
319  }
320  }
321 
322  if (this->dataPtr->joints_[i].joint_control_method == EFFORT) {
323  if (!this->dataPtr->ecm_->Component<ignition::gazebo::components::JointForceCmd>(
324  this->dataPtr->joints_[i].sim_joint))
325  {
326  this->dataPtr->ecm_->CreateComponent(
327  this->dataPtr->joints_[i].sim_joint,
328  ignition::gazebo::components::JointForceCmd({0}));
329  } else {
330  const auto jointEffortCmd =
331  this->dataPtr->ecm_->Component<ignition::gazebo::components::JointForceCmd>(
332  this->dataPtr->joints_[i].sim_joint);
333  *jointEffortCmd = ignition::gazebo::components::JointForceCmd(
334  {this->dataPtr->joints_[i].joint_effort_cmd});
335  }
336  }
337  }
338 }
339 
340 } // namespace ign_ros_control
341 
342 #include "pluginlib/class_list_macros.hpp" // NOLINT
ign_ros_control::IgnitionSystem::pj_interface_
hardware_interface::PositionJointInterface pj_interface_
Definition: ign_system.hpp:62
ign_ros_control::IgnitionSystem::~IgnitionSystem
virtual ~IgnitionSystem() override
ign_ros_control
Definition: ign_ros_control_plugin.hpp:22
HardwareResourceManager< JointStateHandle >::getHandle
JointStateHandle getHandle(const std::string &name)
jointData::joint_position
double joint_position
Current joint position.
Definition: ign_system.cpp:41
hardware_interface::InterfaceManager::registerInterface
void registerInterface(T *iface)
ign_ros_control::IgnitionSystemInterface::POSITION
@ POSITION
Definition: ign_system_interface.hpp:57
hardware_interface.h
ign_ros_control::IgnitionSystemPrivate::ecm_
ignition::gazebo::EntityComponentManager * ecm_
Entity component manager, ECM shouldn't be accessed outside those methods, otherwise the app will cra...
Definition: ign_system.cpp:82
ign_ros_control::IgnitionSystemPrivate::IgnitionSystemPrivate
IgnitionSystemPrivate()=default
jointData::sim_joint
ignition::gazebo::Entity sim_joint
handles to the joints from within Gazebo
Definition: ign_system.cpp:59
ign_ros_control::IgnitionSystemPrivate::node
ignition::transport::Node node
Ignition communication node.
Definition: ign_system.cpp:88
ign_ros_control::IgnitionSystemPrivate::~IgnitionSystemPrivate
~IgnitionSystemPrivate()=default
ign_ros_control::IgnitionSystemInterface::nh_
ros::NodeHandle nh_
Definition: ign_system_interface.hpp:67
ign_ros_control::IgnitionSystem::IgnitionSystem
IgnitionSystem()
Definition: ign_system.cpp:94
ROS_WARN_STREAM
#define ROS_WARN_STREAM(args)
jointData::joint_position_cmd
double joint_position_cmd
Current cmd joint position.
Definition: ign_system.cpp:50
ign_system.hpp
jointData
Definition: ign_system.cpp:35
PLUGINLIB_EXPORT_CLASS
#define PLUGINLIB_EXPORT_CLASS(class_type, base_class_type)
hardware_interface
ign_ros_control::IgnitionSystem::read
virtual void read() override
Definition: ign_system.cpp:248
ROS_FATAL_STREAM_NAMED
#define ROS_FATAL_STREAM_NAMED(name, args)
ROS_DEBUG
#define ROS_DEBUG(...)
ign_ros_control::IgnitionSystem::ej_interface_
hardware_interface::EffortJointInterface ej_interface_
Definition: ign_system.hpp:61
hardware_interface::JointStateHandle
ign_ros_control::IgnitionSystemPrivate::joints_
std::vector< struct jointData > joints_
vector with the joint's names.
Definition: ign_system.cpp:78
ign_ros_control::IgnitionSystem::js_interface_
hardware_interface::JointStateInterface js_interface_
Definition: ign_system.hpp:60
ign_ros_control::IgnitionSystemInterface::EFFORT
@ EFFORT
Definition: ign_system_interface.hpp:57
ign_ros_control::IgnitionSystem
Definition: ign_system.hpp:33
jointData::joint_velocity_cmd
double joint_velocity_cmd
Current cmd joint velocity.
Definition: ign_system.cpp:53
ROS_INFO_STREAM
#define ROS_INFO_STREAM(args)
ign_ros_control::IgnitionSystem::write
virtual void write() override
Definition: ign_system.cpp:273
ResourceManager< JointStateHandle >::registerHandle
void registerHandle(const JointStateHandle &handle)
ign_ros_control::IgnitionSystem::vj_interface_
hardware_interface::VelocityJointInterface vj_interface_
Definition: ign_system.hpp:63
jointData::joint_effort_cmd
double joint_effort_cmd
Current cmd joint effort.
Definition: ign_system.cpp:56
ign_ros_control::IgnitionSystemInterface
Definition: ign_system_interface.hpp:37
hardware_interface::JointHandle
ros::Time
ign_ros_control::IgnitionSystemPrivate
Definition: ign_system.cpp:65
jointData::joint_control_method
ign_ros_control::IgnitionSystemInterface::ControlMethod joint_control_method
Control method defined in the URDF for each joint.
Definition: ign_system.cpp:62
class_list_macros.hpp
ign_ros_control::IgnitionSystemInterface::ControlMethod
ControlMethod
Definition: ign_system_interface.hpp:57
ign_ros_control::IgnitionSystemPrivate::update_rate_
int update_rate_
controller update rate
Definition: ign_system.cpp:85
ign_ros_control::IgnitionSystem::initSim
bool initSim(ros::NodeHandle model_nh, std::map< std::string, ignition::gazebo::Entity > &joints, ignition::gazebo::EntityComponentManager &ecm, std::vector< transmission_interface::TransmissionInfo > transmissions, int &update_rate) override
Initialize the system interface param[in] model_nh Pointer to the ros node param[in] joints Map with ...
Definition: ign_system.cpp:102
ign_ros_control::IgnitionSystem::dataPtr
std::unique_ptr< IgnitionSystemPrivate > dataPtr
Private data class.
Definition: ign_system.hpp:58
jointData::joint_velocity
double joint_velocity
Current joint velocity.
Definition: ign_system.cpp:44
ign_ros_control::IgnitionSystemPrivate::last_update_sim_time_ros_
ros::Time last_update_sim_time_ros_
last time the write method was called.
Definition: ign_system.cpp:75
jointData::joint_effort
double joint_effort
Current joint effort.
Definition: ign_system.cpp:47
ign_ros_control::IgnitionSystemPrivate::n_dof_
size_t n_dof_
Degrees od freedom.
Definition: ign_system.cpp:72
ign_ros_control::IgnitionSystemInterface::VELOCITY
@ VELOCITY
Definition: ign_system_interface.hpp:57
ros::NodeHandle
ros::Time::now
static Time now()
jointData::name
std::string name
Joint's names.
Definition: ign_system.cpp:38


ign_ros_control
Author(s): Gennaro Raiola
autogenerated on Sun Aug 14 2022 02:23:53