hebiros_model.cpp
Go to the documentation of this file.
1 #include "hebiros_model.h"
2 
3 #include "hebiros.h"
4 
5 std::map<std::string, HebirosModel> HebirosModel::models;
6 
7 bool HebirosModel::load(const std::string& name, const std::string& description_param) {
8 
9  // Try to load:
11  bool success = loadURDF(description_param, model);
12  if (!success)
13  return false;
14 
15  std::unique_ptr<hebi::robot_model::RobotModel> robot_model = parseURDF(model);
16  if (!robot_model)
17  return false;
18 
19  models.emplace(name, std::move(robot_model));
20  return true;
21 }
22 
23 
24 HebirosModel::HebirosModel(std::unique_ptr<hebi::robot_model::RobotModel> model_)
25  : model(std::move(model_)) {
26 }
27 
28 HebirosModel* HebirosModel::getModel(const std::string& model_name) {
29  if (models.count(model_name) == 0)
30  return nullptr;
31  return &models.at(model_name);
32 }
33 
35  return *model;
36 }
37 
38 bool HebirosModel::loadURDF(const std::string& description_param, urdf::Model& model) {
39 
40  if (!model.initParam(description_param)) {
41  ROS_WARN_STREAM("Could not load " << description_param);
42  return false;
43  }
44 
45  ROS_INFO_STREAM("Loaded URDF from " << description_param);
46  return true;
47 }
48 
49 class UnsupportedStructureException : public std::exception {
50  public:
51  UnsupportedStructureException(const std::string& structure_type) :
52  message_("Structures of type " + structure_type + " not yet supported.") {
53  }
54  const char* what() const noexcept override {
55  return message_.c_str();
56  }
57  private:
58  std::string message_;
59 };
60 
61 class UnsupportedJointException : public std::exception {
62  public:
63  UnsupportedJointException(const std::string& joint_type) :
64  message_("Joints of type " + joint_type + " not yet supported.") {
65  }
66  const char* what() const noexcept override {
67  return message_.c_str();
68  }
69  private:
70  std::string message_;
71 };
72 
73 Eigen::MatrixXd ROSPoseToEigenMatrix(const urdf::Pose& pose) {
74  Eigen::Matrix4d res = Eigen::Matrix4d::Identity();
75  Eigen::Quaterniond q(pose.rotation.w, pose.rotation.x, pose.rotation.y, pose.rotation.z);
76  res.topLeftCorner<3,3>() = q.toRotationMatrix();
77  res(0, 3) = pose.position.x;
78  res(1, 3) = pose.position.y;
79  res(2, 3) = pose.position.z;
80  return res;
81 }
82 
83 void parseInner(const urdf::Link& link, hebi::robot_model::RobotModel& model) {
84  Eigen::Matrix4d com = Eigen::Matrix4d::Identity();
85  Eigen::VectorXd inertia;
86  inertia.resize(6);
87  inertia << 0, 0, 0, 0, 0, 0;
88  float mass = 0;
89 
90  // Add details about this link:
91  auto& inertial = link.inertial;
92  if (inertial) {
93  com = ROSPoseToEigenMatrix(inertial->origin);
94  inertia <<
95  inertial->ixx, inertial->iyy, inertial->izz,
96  inertial->ixy, inertial->ixz, inertial->iyz;
97  mass = inertial->mass;
98  }
99 
100  auto& child_links = link.child_links;
101 
102  // TODO: support multi-output elements once supported in the C/C++ HEBI API;
103  // the below code would then iterate through the child links
104  if (child_links.size() > 1)
105  throw UnsupportedStructureException("tree");
106 
107  if (child_links.size() == 0) {
108  // TODO: provide some smart default for leaf nodes (e.g., COM * 2)?
109  Eigen::Matrix4d output = Eigen::Matrix4d::Identity();
110  model.addRigidBody(com, inertia, mass, output, false);
111  return;
112  }
113 
114  // hebi robot model "outputs" depends on where the children connect.
115  // (assume one output here for now; can support trees later)
116  {
117  auto& child_link = child_links[0];
118  auto& child_joint = child_link->parent_joint;
119  Eigen::Matrix4d output =
120  ROSPoseToEigenMatrix(child_joint->parent_to_joint_origin_transform);
121 
122  // Add rigid body for this link
123  model.addRigidBody(com, inertia, mass, output, false);
124  }
125 
126  // Add joint(s) to children, and child links (this is written to support
127  // trees)
128  for (auto& child_link : child_links) {
129  auto& child_joint = child_link->parent_joint;
131  // Add joint and link:
132  if (child_joint->type == urdf::Joint::REVOLUTE | child_joint->type == urdf::Joint::CONTINUOUS) {
133  if (child_joint->axis.x != 0) {
134  if (child_joint->axis.y != 0 && child_joint->axis.z != 0) {
135  throw UnsupportedJointException("non-principal rotation axis");
136  }
137  joint_type = HebiJointTypeRotationX;
138  } else if (child_joint->axis.y != 0) {
139  if (child_joint->axis.z != 0) { // We know x == 0
140  throw UnsupportedJointException("non-principal rotation axis");
141  }
142  joint_type = HebiJointTypeRotationY;
143  } else if (child_joint->axis.z != 0) {
144  joint_type = HebiJointTypeRotationZ; // We know x == 0 && y == 0
145  }
146  model.addJoint(joint_type, false);
147  } else if (child_joint->type == urdf::Joint::PRISMATIC) {
148  if (child_joint->axis.x != 0) {
149  if (child_joint->axis.y != 0 && child_joint->axis.z != 0) {
150  throw UnsupportedJointException("non-principal translation axis");
151  }
152  joint_type = HebiJointTypeTranslationX;
153  } else if (child_joint->axis.y != 0) {
154  if (child_joint->axis.z != 0) { // We know x == 0
155  throw UnsupportedJointException("non-principal translation axis");
156  }
157  joint_type = HebiJointTypeTranslationY;
158  } else if (child_joint->axis.z != 0) {
159  joint_type = HebiJointTypeTranslationZ; // We know x == 0 && y == 0
160  }
161  model.addJoint(joint_type, false);
162  } else if (child_joint->type == urdf::Joint::FIXED) {
163  // This is supported, we just don't need a "binding" joint in the hebi
164  // robot model classes
165  } else {
166  throw UnsupportedJointException("unknown");
167  }
168  // This recursively adds this child link (and its children)
169  parseInner(*child_link, model);
170  }
171 }
172 
173 std::unique_ptr<hebi::robot_model::RobotModel> HebirosModel::parseURDF(const urdf::Model& model)
174 {
175  const urdf::Link* root = model.getRoot().get();
176  std::unique_ptr<hebi::robot_model::RobotModel> rm(new hebi::robot_model::RobotModel());
177 
178  // Note: in the future, we could support selection of specific child links
179  // from the URDF file.
180  try {
181  auto& children = root->child_links;
182  if (children.size() != 1) {
183  throw UnsupportedStructureException("more or less than a single model in the world");
184  }
185  auto& child = children[0];
186  if (child->parent_joint->type != urdf::Joint::FIXED) {
187  throw UnsupportedStructureException("parent joint not connected via a fixed joint");
188  }
189 
190  // Set base frame according to this object
191  rm->setBaseFrame(ROSPoseToEigenMatrix(child->parent_joint->parent_to_joint_origin_transform));
192 
193  parseInner(*child, *rm.get());
194  } catch (const std::exception& e) {
195  ROS_ERROR_STREAM(std::string(e.what()));
196  return nullptr;
197  }
198 
199  return rm;
200 }
UnsupportedStructureException(const std::string &structure_type)
root
void parseInner(const urdf::Link &link, hebi::robot_model::RobotModel &model)
UnsupportedJointException(const std::string &joint_type)
bool addJoint(HebiJointType joint_type, bool combine)
Adds a degree of freedom about the specified axis.
EIGEN_DEVICE_FUNC Matrix3 toRotationMatrix() const
Definition: Quaternion.h:531
Represents a chain or tree of robot elements (rigid bodies and joints).
Definition: robot_model.hpp:86
HebirosModel(std::unique_ptr< hebi::robot_model::RobotModel > model_)
static std::map< std::string, HebirosModel > models
Definition: hebiros_model.h:25
HebiJointType
Definition: hebi.h:290
EIGEN_DEVICE_FUNC const Scalar & q
static bool loadURDF(const std::string &description_param, urdf::Model &model)
bool addRigidBody(const Eigen::Matrix4d &com, const Eigen::VectorXd &inertia, double mass, const Eigen::Matrix4d &output, bool combine)
Adds a rigid body with the specified properties to the robot model.
Eigen::MatrixXd ROSPoseToEigenMatrix(const urdf::Pose &pose)
URDF_EXPORT bool initParam(const std::string &param)
#define ROS_WARN_STREAM(args)
hebi::robot_model::RobotModel & getModel()
#define ROS_INFO_STREAM(args)
The quaternion class used to represent 3D orientations and rotations.
static bool load(const std::string &name, const std::string &description_param)
const char * what() const noexceptoverride
std::unique_ptr< hebi::robot_model::RobotModel > model
Definition: hebiros_model.h:28
#define ROS_ERROR_STREAM(args)
const char * what() const noexceptoverride
static std::unique_ptr< hebi::robot_model::RobotModel > parseURDF(const urdf::Model &model)


hebiros
Author(s): Xavier Artache , Matthew Tesch
autogenerated on Thu Sep 3 2020 04:08:14