robot_model.cpp
Go to the documentation of this file.
1 #include "robot_model.hpp"
2 
3 #include <iostream>
4 
5 namespace hebi {
6 namespace robot_model {
7 
9 
11  : _weight(1.0f), _x(obj[0]), _y(obj[1]), _z(obj[2]) {}
12 
13 EndEffectorPositionObjective::EndEffectorPositionObjective(double weight, const Eigen::Vector3d& obj)
14  : _weight(weight), _x(obj[0]), _y(obj[1]), _z(obj[2]) {}
15 
17  return hebiIKAddObjectiveEndEffectorPosition(ik, static_cast<float>(_weight), 0, _x, _y, _z);
18 }
19 
20 // clang-format off
22  : _weight(1.0f), _matrix{
23  matrix(0,0), matrix(1,0), matrix(2,0),
24  matrix(0,1), matrix(1,1), matrix(2,1),
25  matrix(0,2), matrix(1,2), matrix(2,2)}
26 { }
27 
28 EndEffectorSO3Objective::EndEffectorSO3Objective(double weight, const Eigen::Matrix3d& matrix)
29  : _weight(weight), _matrix{
30  matrix(0,0), matrix(1,0), matrix(2,0),
31  matrix(0,1), matrix(1,1), matrix(2,1),
32  matrix(0,2), matrix(1,2), matrix(2,2)}
33 { }
34 // clang-format on
35 
38 }
39 
41  : _weight(1.0f), _x(obj[0]), _y(obj[1]), _z(obj[2]) {}
42 
43 EndEffectorTipAxisObjective::EndEffectorTipAxisObjective(double weight, const Eigen::Vector3d& obj)
44  : _weight(weight), _x(obj[0]), _y(obj[1]), _z(obj[2]) {}
45 
48 }
49 
50 JointLimitConstraint::JointLimitConstraint(const Eigen::VectorXd& min_positions, const Eigen::VectorXd& max_positions)
51  : _weight(1.0f), _min_positions(min_positions), _max_positions(max_positions) {}
52 
53 JointLimitConstraint::JointLimitConstraint(double weight, const Eigen::VectorXd& min_positions,
54  const Eigen::VectorXd& max_positions)
55  : _weight(weight), _min_positions(min_positions), _max_positions(max_positions) {}
56 
58  if (_min_positions.size() != _max_positions.size())
60 
61  int num_joints = _min_positions.size();
62 
63  auto min_positions_array = new double[num_joints];
64  {
65  Map<Eigen::VectorXd> tmp(min_positions_array, num_joints);
66  tmp = _min_positions;
67  }
68  auto max_positions_array = new double[num_joints];
69  {
70  Map<Eigen::VectorXd> tmp(max_positions_array, num_joints);
71  tmp = _max_positions;
72  }
73 
74  auto res = hebiIKAddConstraintJointAngles(ik, _weight, num_joints, min_positions_array, max_positions_array);
75 
76  delete[] min_positions_array;
77  delete[] max_positions_array;
78 
79  return res;
80 }
81 
83 
85  HebiStatusCode res = hebiRobotModelAdd(internal_, nullptr, 0, element);
86  if (res == HebiStatusFailure) {
88  return false;
89  }
90  return true;
91 }
92 
93 RobotModel::RobotModel(HebiRobotModelPtr internal) : internal_(internal) {}
94 
96 
97 std::unique_ptr<RobotModel> RobotModel::loadHRDF(const std::string& file) {
98  HebiRobotModelPtr internal = hebiRobotModelImport(file.c_str());
99  // nullptr return means an import error; print error and return empty
100  // unique_ptr.
101  if (internal == nullptr) {
102  std::cerr << "HRDF Error: " << hebiRobotModelGetImportError() << std::endl;
103  return nullptr;
104  }
105 
106  // Display any relevant warnings.
107  size_t num_warnings = hebiRobotModelGetImportWarningCount();
108  for (size_t i = 0; i < num_warnings; ++i)
109  std::cerr << "HRDF Warning: " << hebiRobotModelGetImportWarning(i) << std::endl;
110 
111  // Create/return the robot model
112  return std::unique_ptr<RobotModel>(new RobotModel(internal));
113 }
114 
116 
117 void RobotModel::setBaseFrame(const Eigen::Matrix4d& base_frame) {
118  // Put data into an array
119  double transform[16];
120  Map<Matrix<double, 4, 4>> tmp(transform);
121  tmp = base_frame;
123 }
124 
125 Eigen::Matrix4d RobotModel::getBaseFrame() const {
126  // Get the data into an array
127  double transform[16];
129 
130  // Copy out data
131  Map<const Matrix<double, 4, 4>> tmp(transform);
132  Eigen::Matrix4d res;
133  res = tmp;
134  return res;
135 }
136 
137 size_t RobotModel::getFrameCount(FrameType frame_type) const {
138  return hebiRobotModelGetNumberOfFrames(internal_, static_cast<HebiFrameType>(frame_type));
139 }
140 
142 
143 // TODO: handle trees/etc by passing in parent object here, and output index
144 bool RobotModel::addRigidBody(const Eigen::Matrix4d& com, const Eigen::VectorXd& inertia, double mass,
145  const Eigen::Matrix4d& output) {
146  if (inertia.size() != 6)
147  return false;
148 
149  // Allocate double arrays for C interop:
150  double com_array[16];
151  double inertia_array[6];
152  double output_array[16];
153 
154  // Convert the data:
155  {
156  Map<Matrix<double, 4, 4>> tmp(com_array);
157  tmp = com;
158  }
159  {
160  Map<Eigen::VectorXd> tmp(inertia_array, 6);
161  tmp = inertia;
162  }
163  {
164  Map<Matrix<double, 4, 4>> tmp(output_array);
165  tmp = output;
166  }
167 
168  HebiRobotModelElementPtr body = hebiRobotModelElementCreateRigidBody(com_array, inertia_array, mass, 1, output_array, HebiMatrixOrderingColumnMajor);
169 
170  return tryAdd(body);
171 }
172 
173 // TODO: handle trees/etc by passing in parent object here, and output index
174 bool RobotModel::addJoint(JointType joint_type) {
175  return tryAdd(hebiRobotModelElementCreateJoint(static_cast<HebiJointType>(joint_type)));
176 }
177 
179  HebiRobotModelElementPtr element = hebiRobotModelElementCreateActuator(static_cast<HebiActuatorType>(actuator_type));
180  if (element == nullptr)
181  return false;
182  return tryAdd(element);
183 }
184 
185 bool RobotModel::addLink(robot_model::LinkType link_type, double extension, double twist,
186  LinkInputType input_type, LinkOutputType output_type) {
187  HebiRobotModelElementPtr element =
188  hebiRobotModelElementCreateLink(static_cast<HebiLinkType>(link_type),
189  static_cast<HebiLinkInputType>(input_type),
190  static_cast<HebiLinkOutputType>(output_type),
191  extension, twist);
192  if (element == nullptr)
193  return false;
194  return tryAdd(element);
195 }
196 
198  HebiRobotModelElementPtr element = hebiRobotModelElementCreateBracket(static_cast<HebiBracketType>(bracket_type));
199  if (element == nullptr)
200  return false;
201  return tryAdd(element);
202 }
203 
205  auto element = hebiRobotModelElementCreateEndEffector(static_cast<HebiEndEffectorType>(end_effector_type), nullptr,
206  nullptr, 0, nullptr, HebiMatrixOrderingColumnMajor);
207  if (element == nullptr)
208  return false;
209  return tryAdd(element);
210 }
211 
212 void RobotModel::getForwardKinematics(FrameType frame_type, const Eigen::VectorXd& positions,
213  Matrix4dVector& frames) const {
214  getFK(frame_type, positions, frames);
215 }
216 
217 void RobotModel::getFK(FrameType frame_type, const Eigen::VectorXd& positions, Matrix4dVector& frames) const {
218  // Put data into an array
219  auto positions_array = new double[positions.size()];
220  {
221  Map<Eigen::VectorXd> tmp(positions_array, positions.size());
222  tmp = positions;
223  }
224  size_t num_frames = getFrameCount(frame_type);
225  auto frame_array = new double[16 * num_frames];
226  // Get data from C API
227  hebiRobotModelGetForwardKinematics(internal_, static_cast<HebiFrameType>(frame_type), positions_array, frame_array, HebiMatrixOrderingColumnMajor);
228  delete[] positions_array;
229  // Copy into vector of matrices passed in
230  frames.resize(num_frames);
231  for (size_t i = 0; i < num_frames; ++i) {
232  Map<Matrix<double, 4, 4>> tmp(frame_array + i * 16);
233  frames[i] = tmp;
234  }
235  delete[] frame_array;
236 }
237 
238 void RobotModel::getEndEffector(const Eigen::VectorXd& positions, Eigen::Matrix4d& transform) const {
239  // Put data into an array
240  auto positions_array = new double[positions.size()];
241  {
242  Map<Eigen::VectorXd> tmp(positions_array, positions.size());
243  tmp = positions;
244  }
245 
246  double transform_array[16];
248  delete[] positions_array;
249  {
250  Map<Matrix<double, 4, 4>> tmp(transform_array);
251  transform = tmp;
252  }
253 }
254 
255 void RobotModel::getJacobians(FrameType frame_type, const Eigen::VectorXd& positions,
256  MatrixXdVector& jacobians) const {
257  getJ(frame_type, positions, jacobians);
258 }
259 void RobotModel::getJ(FrameType frame_type, const Eigen::VectorXd& positions, MatrixXdVector& jacobians) const {
260  // Put data into an array
261  auto positions_array = new double[positions.size()];
262  {
263  Map<Eigen::VectorXd> tmp(positions_array, positions.size());
264  tmp = positions;
265  }
266 
267  size_t num_frames = getFrameCount(frame_type);
268  size_t num_dofs = positions.size();
269  size_t rows = 6 * num_frames;
270  size_t cols = num_dofs;
271  auto jacobians_array = new double[rows * cols];
272  hebiRobotModelGetJacobians(internal_, static_cast<HebiFrameType>(frame_type), positions_array, jacobians_array, HebiMatrixOrderingColumnMajor);
273  delete[] positions_array;
274  jacobians.resize(num_frames);
275  for (size_t i = 0; i < num_frames; ++i) {
276  Map<Matrix<double, Dynamic, Dynamic>> tmp(jacobians_array + i * cols * 6, 6, cols);
277  jacobians[i] = tmp;
278  }
279  delete[] jacobians_array;
280 }
281 void RobotModel::getJacobianEndEffector(const Eigen::VectorXd& positions, Eigen::MatrixXd& jacobian) const {
282  getJEndEffector(positions, jacobian);
283 }
284 void RobotModel::getJEndEffector(const Eigen::VectorXd& positions, Eigen::MatrixXd& jacobian) const {
285  MatrixXdVector tmp_jacobians;
286  getJacobians(FrameType::EndEffector, positions, tmp_jacobians);
287 
288  // NOTE: could make this more efficient by writing additional lib function
289  // for this, instead of tossing away almost everything from the full one!
290 
291  size_t num_dofs = positions.size();
292  jacobian.resize(6, num_dofs);
293  jacobian = *tmp_jacobians.rbegin();
294 }
295 
296 void RobotModel::getMasses(Eigen::VectorXd& masses) const {
297  size_t num_masses = getFrameCount(FrameType::CenterOfMass);
298  auto masses_array = new double[num_masses];
299  hebiRobotModelGetMasses(internal_, masses_array);
300  {
301  Map<VectorXd> tmp(masses_array, num_masses);
302  masses = tmp;
303  }
304  delete[] masses_array;
305 }
306 
307 void RobotModel::getMetadata(std::vector<MetadataBase>& metadata) const {
308  const auto num_elems = hebiRobotModelGetNumberOfElements(internal_);
309  metadata.resize(num_elems);
310  for (auto i = 0; i < num_elems; i++) {
311  hebiRobotModelGetElementMetadata(internal_, i, &metadata[i].metadata_);
312  }
313 }
314 
315 } // namespace robot_model
316 } // namespace hebi
HebiStatusCode hebiRobotModelGetForwardKinematics(HebiRobotModelPtr robot_model, HebiFrameType frame_type, const double *positions, double *frames, HebiMatrixOrdering ordering)
Generates the transforms for the forward kinematics of the given robot model.
Returned when an accessor function attempts to retrieve a field which is not set. ...
Definition: hebi.h:28
HebiStatusCode hebiIKAddObjectiveEndEffectorTipAxis(HebiIKPtr ik, double weight, size_t end_effector_index, double x, double y, double z)
Add an objective that points the end effector&#39;s z axis in a given direction. Note that this is incomp...
HebiStatusCode hebiRobotModelGetJacobians(HebiRobotModelPtr robot_model, HebiFrameType frame_type, const double *positions, double *jacobians, HebiMatrixOrdering ordering)
Generates the jacobian for each frame in the given kinematic tree.
HebiStatusCode hebiIKAddObjectiveEndEffectorSO3(HebiIKPtr ik, double weight, size_t end_effector_index, const double *matrix, HebiMatrixOrdering ordering)
Add an objective that optimizes for the end effector output frame orientation to be given by the 3x3 ...
void getFK(FrameType, const Eigen::VectorXd &positions, Matrix4dVector &frames) const
Generates the forward kinematics for the given robot model.
void getJacobians(FrameType, const Eigen::VectorXd &positions, MatrixXdVector &jacobians) const
Generates the Jacobian for each frame in the given kinematic tree.
void getMasses(Eigen::VectorXd &masses) const
Returns the mass of each rigid body (or combination of rigid bodies) in the robot model...
HebiStatusCode addObjective(HebiIKPtr ik) const override
Definition: robot_model.cpp:57
EndEffectorPositionObjective(const Eigen::Vector3d &)
Definition: robot_model.cpp:10
HebiRobotModelElementPtr hebiRobotModelElementCreateJoint(HebiJointType joint_type)
RobotModel API.
HebiStatusCode hebiRobotModelGetMasses(HebiRobotModelPtr robot_model, double *masses)
Fill in the masses vector with the mass of each body with mass in the kinematic tree, reported in a depth-first ordering.
HebiRobotModelPtr hebiRobotModelCreate(void)
Creates an object to hold a robot model (tree topology). This structure has a single output available...
HebiStatusCode hebiRobotModelGetElementMetadata(HebiRobotModelPtr model, size_t index, HebiRobotModelElementMetadata *output)
Retrieves metadata about an element in the robot model. This metadata includes what type of element t...
HebiRobotModelElementPtr hebiRobotModelElementCreateActuator(HebiActuatorType actuator_type)
Creates a robot model element corresponding to a standard HEBI actuator.
bool addLink(robot_model::LinkType link_type, double extension, double twist, LinkInputType input_type=LinkInputType::RightAngle, LinkOutputType output_type=LinkOutputType::RightAngle)
Add an element to the robot model with the kinematics/dynamics of a link between two actuators...
Definition: arm.cpp:5
HebiStatusCode addObjective(HebiIKPtr ik) const override
Definition: robot_model.cpp:36
size_t getFrameCount(FrameType frame_type) const
Return the number of frames in the forward kinematics.
const char * hebiRobotModelGetImportError()
Retrieve any error string from the last call to hebiRobotModelImport. This must be called on the same...
HebiRobotModelPtr const internal_
void setBaseFrame(const Eigen::Matrix4d &base_frame)
Set the transform from a world coordinate system to the input of the root element in this robot model...
JointLimitConstraint(const Eigen::VectorXd &min_positions, const Eigen::VectorXd &max_positions)
Definition: robot_model.cpp:50
static std::unique_ptr< RobotModel > loadHRDF(const std::string &file)
Creates a robot model object with no bodies and an identity base frame.
Definition: robot_model.cpp:97
std::vector< MatrixXd, Eigen::aligned_allocator< Eigen::MatrixXd >> MatrixXdVector
Definition: robot_model.hpp:17
size_t hebiRobotModelGetNumberOfDoFs(HebiRobotModelPtr robot_model)
Returns the number of settable degrees of freedom in the kinematic tree. (This is equal to the number...
struct HebiRobotModel_ * HebiRobotModelPtr
Definition: hebi.h:527
bool addBracket(robot_model::BracketType bracket_type)
Add an element to the robot model with the kinematics/dynamics of a bracket between two actuators...
void hebiRobotModelElementRelease(HebiRobotModelElementPtr element)
Frees resources created by this element.
void getMetadata(std::vector< MetadataBase > &metadata) const
Returns the metadata of each component of the robot model.
HebiStatusCode addObjective(HebiIKPtr ik) const override
Definition: robot_model.cpp:16
bool addJoint(JointType joint_type)
Adds a degree of freedom about the specified axis.
Eigen::Matrix4d getBaseFrame() const
Returns the transform from the world coordinate system to the root kinematic body, as set by the setBaseFrame function.
HebiRobotModelElementPtr hebiRobotModelElementCreateLink(HebiLinkType link_type, HebiLinkInputType input_type, HebiLinkOutputType output_type, double extension, double twist)
Creates a rigid body, including mass and static transforms, corresponding to a standard HEBI link...
void getJ(FrameType, const Eigen::VectorXd &positions, MatrixXdVector &jacobians) const
Generates the Jacobian for each frame in the given kinematic tree.
void getEndEffector(const Eigen::VectorXd &positions, Eigen::Matrix4d &transform) const
Generates the forward kinematics to the end effector (leaf node) frame(s).
size_t hebiRobotModelGetImportWarningCount()
Retrieve the number of warnings corresponding to the last call to hebiRobotModelImport. This must be called on the same thread as the call to hebiRobotModelImport.
RobotModel()
Creates a robot model object with no bodies and an identity base frame.
Definition: robot_model.cpp:95
HebiStatusCode hebiRobotModelAdd(HebiRobotModelPtr robot_model, HebiRobotModelElementPtr existing_element, size_t output_index, HebiRobotModelElementPtr new_element)
Add an element to a parent element connected to a robot model object.
void getJEndEffector(const Eigen::VectorXd &positions, Eigen::MatrixXd &jacobian) const
Generates the Jacobian for the end effector (leaf node) frames(s).
bool addActuator(robot_model::ActuatorType actuator_type)
Add an element to the robot model with the kinematics/dynamics of an X5 actuator. ...
bool tryAdd(HebiRobotModelElementPtr element)
Definition: robot_model.cpp:84
Success; no failures occurred.
Definition: hebi.h:25
size_t hebiRobotModelGetNumberOfElements(HebiRobotModelPtr robot_model)
Returns the number of elements added to the kinematic tree.
HebiRobotModelElementPtr hebiRobotModelElementCreateBracket(HebiBracketType bracket_type)
Creates a rigid body, including mass and static transforms, corresponding to a standard HEBI bracket...
HebiRobotModelElementPtr hebiRobotModelElementCreateRigidBody(const double *com, const double *inertia, double mass, size_t num_outputs, const double *outputs, HebiMatrixOrdering ordering)
Creates a rigid body defining static transforms to the given outputs.
void getForwardKinematics(FrameType, const Eigen::VectorXd &positions, Matrix4dVector &frames) const
Generates the forward kinematics for the given robot model.
HebiStatusCode addObjective(HebiIKPtr ik) const override
Definition: robot_model.cpp:46
EndEffectorTipAxisObjective(const Eigen::Vector3d &)
Definition: robot_model.cpp:40
HebiStatusCode hebiRobotModelSetBaseFrame(HebiRobotModelPtr robot_model, const double *transform, HebiMatrixOrdering ordering)
Sets the fixed transform from the origin to the input of the first added model element.
HebiStatusCode hebiRobotModelGetBaseFrame(HebiRobotModelPtr robot_model, double *transform, HebiMatrixOrdering ordering)
Retreives the fixed transform from the origin to the input of the first added model element...
bool addEndEffector(EndEffectorType end_effector_type)
Add an end effector element to the robot model.
size_t getDoFCount() const
Returns the number of settable degrees of freedom in the kinematic tree. (This is equal to the number...
void hebiRobotModelRelease(HebiRobotModelPtr robot_model)
Frees resources created by this robot model object.
HebiStatusCode hebiIKAddObjectiveEndEffectorPosition(HebiIKPtr ik, double weight, size_t end_effector_index, double x, double y, double z)
Add an objective that optimizes for the end effector output frame origin to be at the given (x...
HebiRobotModelElementPtr hebiRobotModelElementCreateEndEffector(HebiEndEffectorType end_effector_type, const double *com, const double *inertia, double mass, const double *output_frame, HebiMatrixOrdering ordering)
Creates a robot model element corresponding to a standard HEBI end effector, or a custom end effector...
std::vector< Matrix4d, Eigen::aligned_allocator< Eigen::Matrix4d >> Matrix4dVector
Definition: robot_model.hpp:16
HebiStatusCode hebiIKAddConstraintJointAngles(HebiIKPtr ik, double weight, size_t num_joints, const double *min_positions, const double *max_positions)
Define joint angle constraints.
bool addRigidBody(const Eigen::Matrix4d &com, const Eigen::VectorXd &inertia, double mass, const Eigen::Matrix4d &output)
Adds a rigid body with the specified properties to the robot model.
void getJacobianEndEffector(const Eigen::VectorXd &positions, Eigen::MatrixXd &jacobian) const
Generates the Jacobian for the end effector (leaf node) frames(s).
struct HebiRobotModelElement_ * HebiRobotModelElementPtr
Definition: hebi.h:533
size_t hebiRobotModelGetNumberOfFrames(HebiRobotModelPtr robot_model, HebiFrameType frame_type)
Return the number of frames in the forward kinematic tree of the robot model.
struct HebiIK_ * HebiIKPtr
Definition: hebi.h:540
EndEffectorSO3Objective(const Eigen::Matrix3d &)
Definition: robot_model.cpp:21
const char * hebiRobotModelGetImportWarning(size_t warning_index)
Retrieve the &#39;ith&#39; warning string from the last call to hebiRobotModelImport. This must be called on ...
HebiRobotModelPtr hebiRobotModelImport(const char *file)
Import robot model from a file into a RobotModel object.
HebiStatusCode
Enum Types.
Definition: hebi.h:23
~RobotModel() noexcept
Destructor cleans up robot model object, including all managed elements.


hebi_cpp_api_ros
Author(s): Chris Bollinger , Matthew Tesch
autogenerated on Thu May 28 2020 03:14:45