robot_model.cpp
Go to the documentation of this file.
1 #include "robot_model.hpp"
2 #include "hebi.h"
3 
4 namespace hebi {
5 namespace robot_model {
6 
8 
10  : _weight(1.0f), _x(obj[0]), _y(obj[1]), _z(obj[2])
11 { }
12 
13 EndEffectorPositionObjective::EndEffectorPositionObjective(double weight, const Eigen::Vector3d& obj)
14  : _weight(weight), _x(obj[0]), _y(obj[1]), _z(obj[2])
15 { }
16 
18 {
19  return hebiIKAddObjectiveEndEffectorPosition(ik, static_cast<float>(_weight), 0, _x, _y, _z);
20 }
21 
23  : _weight(1.0f), _matrix{
24  matrix(0,0), matrix(0,1), matrix(0,2),
25  matrix(1,0), matrix(1,1), matrix(1,2),
26  matrix(2,0), matrix(2,1), matrix(2,2)}
27 { }
28 
29 EndEffectorSO3Objective::EndEffectorSO3Objective(double weight, const Eigen::Matrix3d& matrix)
30  : _weight(weight), _matrix{
31  matrix(0,0), matrix(0,1), matrix(0,2),
32  matrix(1,0), matrix(1,1), matrix(1,2),
33  matrix(2,0), matrix(2,1), matrix(2,2)}
34 { }
35 
37 {
39 }
40 
42  : _weight(1.0f), _x(obj[0]), _y(obj[1]), _z(obj[2])
43 { }
44 
45 EndEffectorTipAxisObjective::EndEffectorTipAxisObjective(double weight, const Eigen::Vector3d& obj)
46  : _weight(weight), _x(obj[0]), _y(obj[1]), _z(obj[2])
47 { }
48 
50 {
52 }
53 
54 JointLimitConstraint::JointLimitConstraint(const Eigen::VectorXd& min_positions, const Eigen::VectorXd& max_positions)
55  : _weight(1.0f), _min_positions(min_positions), _max_positions(max_positions)
56 { }
57 
58 JointLimitConstraint::JointLimitConstraint(double weight, const Eigen::VectorXd& min_positions, const Eigen::VectorXd& max_positions)
59  : _weight(weight), _min_positions(min_positions), _max_positions(max_positions)
60 { }
61 
63 {
64  if (_min_positions.size() != _max_positions.size())
66 
67  int num_joints = _min_positions.size();
68 
69  auto min_positions_array = new double[num_joints];
70  {
71  Map<Eigen::VectorXd> tmp(min_positions_array, num_joints);
72  tmp = _min_positions;
73  }
74  auto max_positions_array = new double[num_joints];
75  {
76  Map<Eigen::VectorXd> tmp(max_positions_array, num_joints);
77  tmp = _max_positions;
78  }
79 
80  auto res = hebiIKAddConstraintJointAngles(ik, _weight, num_joints, min_positions_array, max_positions_array);
81 
82  delete[] min_positions_array;
83  delete[] max_positions_array;
84 
85  return res;
86 }
87 
89 
90 void RobotModel::setTranslate(Eigen::Matrix4d& matrix, double x, double y, double z)
91 {
92  matrix(0, 3) = x;
93  matrix(1, 3) = y;
94  matrix(2, 3) = z;
95 }
96 
97 void RobotModel::setRotX(Eigen::Matrix4d& matrix, double radians) {
98  matrix(0, 0) = 1;
99  matrix(0, 1) = 0;
100  matrix(0, 2) = 0;
101  matrix(1, 0) = 0;
102  matrix(1, 1) = cos(radians);
103  matrix(1, 2) = -sin(radians);
104  matrix(2, 0) = 0;
105  matrix(2, 1) = sin(radians);
106  matrix(2, 2) = cos(radians);
107 }
108 
109 void RobotModel::setSphereInertia(Eigen::VectorXd& inertia, double mass, double radius)
110 {
111  if (inertia.size() != 6)
112  inertia.resize(6);
113 
114  // Ixx = Iyy = Izz = 2mr^2 / 5
115  // Ixy = Ixz = Iyz = 0;
116  inertia[0] = inertia[1] = inertia[2] = 0.4f * mass * radius * radius;
117  inertia[3] = inertia[4] = inertia[5] = 0;
118 }
119 
120 void RobotModel::setRodXAxisInertia(Eigen::VectorXd& inertia, double mass, double length)
121 {
122  if (inertia.size() != 6)
123  inertia.resize(6);
124 
125  // Iyy = Izz = ml^2 / 12
126  // Ixx = Ixy = Ixz = Iyz = 0;
127  inertia[1] = inertia[2] = mass * length * length / 12.f;
128  inertia[0] = inertia[3] = inertia[4] = inertia[5] = 0;
129 }
130 
131 bool RobotModel::tryAdd(HebiRobotModelElementPtr element, bool combine)
132 {
134  internal_, nullptr, 0, element, combine ? 1 : 0);
135  if (res == HebiStatusFailure)
136  {
138  return false;
139  }
140  return true;
141 }
142 
144  : internal_(hebiRobotModelCreate())
145 {
146 }
147 
149 {
151 }
152 
153 void RobotModel::setBaseFrame(const Eigen::Matrix4d& base_frame)
154 {
155  // Put data into an array
156  double transform[16];
157  Map<Matrix<double, 4, 4, RowMajor> > tmp(transform);
158  tmp = base_frame;
160 }
161 
162 Eigen::Matrix4d RobotModel::getBaseFrame() const
163 {
164  // Get the data into an array
165  double transform[16];
167 
168  // Copy out data
170  Eigen::Matrix4d res;
171  res = tmp;
172  return res;
173 }
174 
175 size_t RobotModel::getFrameCount(HebiFrameType frame_type) const
176 {
177  return hebiRobotModelGetNumberOfFrames(internal_, frame_type);
178 }
179 
181 {
183 }
184 
185 // TODO: handle trees/etc by passing in parent object here, and output index
187  const Eigen::Matrix4d& com,
188  const Eigen::VectorXd& inertia,
189  double mass,
190  const Eigen::Matrix4d& output,
191  bool combine)
192 {
193  if (inertia.size() != 6)
194  return false;
195 
196  // Allocate double arrays for C interop:
197  double com_array[16];
198  double inertia_array[6];
199  double output_array[16];
200 
201  // Convert the data:
202  {
203  Map<Matrix<double, 4, 4, RowMajor> > tmp(com_array);
204  tmp = com;
205  }
206  {
207  Map<Eigen::VectorXd> tmp(inertia_array, 6);
208  tmp = inertia;
209  }
210  {
211  Map<Matrix<double, 4, 4, RowMajor> > tmp(output_array);
212  tmp = output;
213  }
214 
216  com_array, inertia_array, mass, 1, output_array);
217 
218  return tryAdd(body, combine);
219 }
220 
221 // TODO: handle trees/etc by passing in parent object here, and output index
223  HebiJointType joint_type,
224  bool combine)
225 {
226  return tryAdd(hebiRobotModelElementCreateJoint(joint_type), combine);
227 }
228 
230 {
231  Matrix4d com = Matrix4d::Identity();
232 
233  Matrix4d input_to_axis = Matrix4d::Identity();
234 
235  double mass = actuator_masses_.at(actuator_type);
237 
238  VectorXd inertia(6);
239  if (actuator_type == ActuatorType::X5_1 ||
240  actuator_type == ActuatorType::X5_4 ||
241  actuator_type == ActuatorType::X5_9)
242  {
243  setTranslate(com, -0.0142, -0.0031, 0.0165);
244  setTranslate(input_to_axis, 0.0, 0.0, 0.03105);
245 
246  inertia << 0.00015, // XX
247  0.000255, // YY
248  0.000350, // ZZ
249  0.0000341, // XY
250  0.0000118, // XZ
251  0.00000229; // YZ
252  }
253  else if (actuator_type == ActuatorType::X8_3 ||
254  actuator_type == ActuatorType::X8_9 ||
255  actuator_type == ActuatorType::X8_16)
256  {
257  setTranslate(com, -0.0145, -0.0031, 0.0242);
258  setTranslate(input_to_axis, 0.0, 0.0, 0.0451);
259  inertia << 0.000246, // XX
260  0.000380, // YY
261  0.000463, // ZZ
262  0.0000444, // XY
263  0.0000266, // XZ
264  0.00000422; // YZ
265  }
266  else
267  {
268  return false;
269  }
270 
272  // Create the actuator (currently, this is X-series specific)
273 
274  // Create and add the body (and handle failure cases)
275  if (!addRigidBody(com, inertia, mass, input_to_axis, false))
276  return false;
277 
278  // Create and add the joint (and handle failure cases)
279  // Note -- weird case if this fails, as we've already added the body...
280  // leaves the kinematic object in an odd state.
281  return addJoint(joint_type, true);
282 }
283 
284 bool RobotModel::addLink(LinkType link_type, double extension, double twist)
285 {
286  if (link_type != LinkType::X5)
287  return false;
288 
289  Matrix4d com = Matrix4d::Identity();
290  Matrix4d output = Matrix4d::Identity();
291 
292  // Tube approx. 0.4kg / 1m; 0.03 m shorter than the total extension length
293  // End brackets + hardware approx. 0.26 kg
294  double mass = 0.4f * (extension - 0.03) + 0.26f;
295 
296  // Edge of bracket to center of pipe.
297  double edge_to_center = .0175f;
298 
299  // Note that this ignores the effect of the end brackets on moving the com
300  // slightly off center.
301  setTranslate(com, extension * 0.5f, 0, edge_to_center);
302  setRotX(output, twist);
303  setTranslate(output, extension,
304  -edge_to_center * sin(twist),
305  edge_to_center * (1 + cos(twist)));
306 
307  // Inertia: current approximation is a thin rod; will be improved in future.
308  VectorXd inertia(6);
309  setRodXAxisInertia(inertia, mass, extension);
310 
311  // Generic -- (try to) create and add the body
312  return addRigidBody(com, inertia, mass, output, false);
313 }
314 
316 {
317  Matrix4d com = Matrix4d::Identity();
318  Matrix4d output = Matrix4d::Identity();
319  double mass = 0;
320 
321  // Light bracket
322  switch(bracket_type)
323  {
326  {
327  double mult = 1;
328  if (bracket_type == BracketType::X5LightRight)
329  mult = -1;
330 
331  mass = 0.1;
332 
333  setTranslate(com, 0, mult * 0.0215f, 0.02f);
334  setRotX(output, mult * (-M_PI / 2.0f));
335  setTranslate(output, 0, mult * .043f, 0.04f);
336  break;
337  }
342  {
343  double lr_mult = 1;
344  if (bracket_type == BracketType::X5HeavyRightInside ||
345  bracket_type == BracketType::X5HeavyRightOutside)
346  lr_mult = -1;
347 
348  double y_dist = -0.0225; // Inside
349  if (bracket_type == BracketType::X5HeavyLeftOutside ||
350  bracket_type == BracketType::X5HeavyRightOutside)
351  y_dist = 0.0375; // Outside
352 
353  mass = 0.215;
354 
355  setTranslate(com, 0, lr_mult * 0.5 * y_dist, 0.0275);
356  setRotX(output, lr_mult * (-M_PI / 2.0));
357  setTranslate(output, 0, lr_mult * y_dist, 0.055);
358  break;
359  }
360  default:
361  return false;
362  }
363 
364  // Inertia: current approximation is a 6cm sphere; will be improved in future.
365  VectorXd inertia(6);
366  setSphereInertia(inertia, mass, 0.06);
367 
368  // Generic -- (try to) create and add the body
369  return addRigidBody(com, inertia, mass, output, false);
370 }
371 
372 void RobotModel::getForwardKinematics(HebiFrameType frame_type, const Eigen::VectorXd& positions, Matrix4dVector& frames) const
373 {
374  getFK(frame_type, positions, frames);
375 }
376 
377 void RobotModel::getFK(HebiFrameType frame_type, const Eigen::VectorXd& positions, Matrix4dVector& frames) const
378 {
379  // Put data into an array
380  auto positions_array = new double[positions.size()];
381  {
382  Map<Eigen::VectorXd> tmp(positions_array, positions.size());
383  tmp = positions;
384  }
385  size_t num_frames = getFrameCount(frame_type);
386  auto frame_array = new double[16 * num_frames];
387  // Get data from C API
388  hebiRobotModelGetForwardKinematics(internal_, frame_type, positions_array, frame_array);
389  delete[] positions_array;
390  // Copy into vector of matrices passed in
391  frames.resize(num_frames);
392  for (size_t i = 0; i < num_frames; ++i)
393  {
394  Map<Matrix<double, 4, 4, RowMajor> > tmp(frame_array + i * 16);
395  frames[i] = tmp;
396  }
397  delete[] frame_array;
398 }
399 
400 void RobotModel::getEndEffector(const Eigen::VectorXd& positions, Eigen::Matrix4d& transform) const
401 {
402  // Put data into an array
403  auto positions_array = new double[positions.size()];
404  {
405  Map<Eigen::VectorXd> tmp(positions_array, positions.size());
406  tmp = positions;
407  }
408 
409  double transform_array[16];
410  hebiRobotModelGetForwardKinematics(internal_, HebiFrameTypeEndEffector, positions_array, transform_array);
411  delete[] positions_array;
412  {
413  Map<Matrix<double, 4, 4, RowMajor> > tmp(transform_array);
414  transform = tmp;
415  }
416 }
417 
418 void RobotModel::getJacobians(HebiFrameType frame_type, const Eigen::VectorXd& positions, MatrixXdVector& jacobians) const
419 {
420  getJ(frame_type, positions, jacobians);
421 }
422 void RobotModel::getJ(HebiFrameType frame_type, const Eigen::VectorXd& positions, MatrixXdVector& jacobians) const
423 {
424  // Put data into an array
425  auto positions_array = new double[positions.size()];
426  {
427  Map<Eigen::VectorXd> tmp(positions_array, positions.size());
428  tmp = positions;
429  }
430 
431  size_t num_frames = getFrameCount(frame_type);
432  size_t num_dofs = positions.size();
433  size_t rows = 6 * num_frames;
434  size_t cols = num_dofs;
435  auto jacobians_array = new double[rows * cols];
436  hebiRobotModelGetJacobians(internal_, frame_type, positions_array, jacobians_array);
437  delete[] positions_array;
438  jacobians.resize(num_frames);
439  for (size_t i = 0; i < num_frames; ++i)
440  {
441  Map<Matrix<double, Dynamic, Dynamic, RowMajor> > tmp(jacobians_array + i * cols * 6, 6, cols);
442  jacobians[i] = tmp;
443  }
444  delete[] jacobians_array;
445 }
446 void RobotModel::getJacobianEndEffector(const Eigen::VectorXd& positions, Eigen::MatrixXd& jacobian) const
447 {
448  getJEndEffector(positions, jacobian);
449 }
450 void RobotModel::getJEndEffector(const Eigen::VectorXd& positions, Eigen::MatrixXd& jacobian) const
451 {
452  MatrixXdVector tmp_jacobians;
453  getJacobians(HebiFrameTypeEndEffector, positions, tmp_jacobians);
454 
455  // NOTE: could make this more efficient by writing additional lib function
456  // for this, instead of tossing away almost everything from the full one!
457 
458  size_t num_dofs = positions.size();
459  jacobian.resize(6, num_dofs);
460  jacobian = *tmp_jacobians.rbegin();
461 }
462 
463 void RobotModel::getMasses(Eigen::VectorXd& masses) const
464 {
465  size_t num_masses = getFrameCount(HebiFrameTypeCenterOfMass);
466  auto masses_array = new double[num_masses];
467  hebiRobotModelGetMasses(internal_, masses_array);
468  {
469  Map<VectorXd> tmp(masses_array, num_masses);
470  masses = tmp;
471  }
472  delete[] masses_array;
473 }
474 
475 const std::map<RobotModel::ActuatorType, double> RobotModel::actuator_masses_ = {
476  std::make_pair(ActuatorType::X5_1, 0.315),
477  std::make_pair(ActuatorType::X5_4, 0.335),
478  std::make_pair(ActuatorType::X5_9, 0.360),
479  std::make_pair(ActuatorType::X8_3, 0.460),
480  std::make_pair(ActuatorType::X8_9, 0.480),
481  std::make_pair(ActuatorType::X8_16, 0.500)
482 };
483 
484 } // namespace robot_model
485 } // namespace hebi
HebiStatusCode hebiIKAddObjectiveEndEffectorSO3(HebiIKPtr ik, double weight, size_t end_effector_index, const double *matrix)
Add an objective that optimizes for the end effector output frame orientation to be given by the 3x3 ...
std::vector< Matrix4d, Eigen::aligned_allocator< Eigen::Matrix4d > > Matrix4dVector
Definition: robot_model.hpp:14
static void setTranslate(Eigen::Matrix4d &matrix, double x, double y, double z)
Definition: robot_model.cpp:90
Returned when an accessor function attempts to retrieve a field which is not set. ...
Definition: hebi.h:24
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 hebiRobotModelGetForwardKinematics(HebiRobotModelPtr robot_model, HebiFrameType frame_type, const double *positions, double *frames)
Generates the transforms for the forward kinematics of the given robot model.
void getMasses(Eigen::VectorXd &masses) const
Returns the mass of each rigid body (or combination of rigid bodies) in the robot model...
HebiStatusCode hebiRobotModelGetJacobians(HebiRobotModelPtr robot_model, HebiFrameType frame_type, const double *positions, double *jacobians)
Generates the jacobian for each frame in the given kinematic tree.
HebiStatusCode addObjective(HebiIKPtr ik) const override
Definition: robot_model.cpp:62
static const std::map< ActuatorType, double > actuator_masses_
EndEffectorPositionObjective(const Eigen::Vector3d &)
Definition: robot_model.cpp:9
A matrix or vector expression mapping an existing array of data.
Definition: Map.h:88
bool addJoint(HebiJointType joint_type, bool combine)
Adds a degree of freedom about the specified axis.
HebiRobotModelElementPtr hebiRobotModelElementCreateJoint(HebiJointType joint_type)
Creates a one-dof joint about the specified axis.
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.
struct _HebiIK * HebiIKPtr
Definition: hebi.h:369
HebiRobotModelPtr hebiRobotModelCreate(void)
Creates an object to hold a robot model (tree topology). This structure has a single output available...
static int f(const TensorMap< Tensor< int, 3 > > &tensor)
Definition: color.hpp:5
HebiStatusCode addObjective(HebiIKPtr ik) const override
Definition: robot_model.cpp:36
bool addLink(LinkType link_type, double extension, double twist)
Add an element to the robot model with the kinematics/dynamics of a link between two actuators...
HebiFrameType
Definition: hebi.h:280
void getJ(HebiFrameType, const Eigen::VectorXd &positions, MatrixXdVector &jacobians) const
Generates the Jacobian for each frame in the given kinematic tree.
HebiRobotModelPtr const internal_
Definition: robot_model.hpp:94
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:54
static void setRodXAxisInertia(Eigen::VectorXd &inertia, double mass, double length)
void getForwardKinematics(HebiFrameType, const Eigen::VectorXd &positions, Matrix4dVector &frames) const
Generates the forward kinematics for the given robot model.
bool tryAdd(HebiRobotModelElementPtr element, bool combine)
size_t hebiRobotModelGetNumberOfDoFs(HebiRobotModelPtr robot_model)
Returns the number of settable degrees of freedom in the kinematic tree. (This is equal to the number...
void hebiRobotModelElementRelease(HebiRobotModelElementPtr element)
Frees resources created by this element.
HebiJointType
Definition: hebi.h:290
EIGEN_DEVICE_FUNC const CosReturnType cos() const
HebiStatusCode addObjective(HebiIKPtr ik) const override
Definition: robot_model.cpp:17
void getFK(HebiFrameType, const Eigen::VectorXd &positions, Matrix4dVector &frames) const
Generates the forward kinematics for the given robot model.
HebiRobotModelElementPtr hebiRobotModelElementCreateRigidBody(const double *com, const double *inertia, double mass, size_t num_outputs, const double *outputs)
Creates a rigid body defining static transforms to the given outputs.
Eigen::Matrix4d getBaseFrame() const
Returns the transform from the world coordinate system to the root kinematic body, as set by the setBaseFrame function.
#define M_PI
Definition: hebi.h:12
void getEndEffector(const Eigen::VectorXd &positions, Eigen::Matrix4d &transform) const
Generates the forward kinematics to the end effector (leaf node) frame(s).
RobotModel()
Creates a robot model object with no bodies and an identity base frame.
struct _HebiRobotModelElement * HebiRobotModelElementPtr
Definition: hebi.h:381
HebiStatusCode hebiIKAddObjectiveEndEffectorPosition(HebiIKPtr ik, float 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...
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.
void getJEndEffector(const Eigen::VectorXd &positions, Eigen::MatrixXd &jacobian) const
Generates the Jacobian for the end effector (leaf node) frames(s).
HebiStatusCode hebiRobotModelAdd(HebiRobotModelPtr robot_model, HebiRobotModelElementPtr existing_element, size_t output_index, HebiRobotModelElementPtr new_element, int32_t combine)
Add an element to a parent element connected to a robot model object.
Success; no failures occurred.
Definition: hebi.h:21
HebiStatusCode hebiRobotModelSetBaseFrame(HebiRobotModelPtr robot_model, const double *transform)
Sets the fixed transform from the origin to the input of the first added model element.
HebiStatusCode addObjective(HebiIKPtr ik) const override
Definition: robot_model.cpp:49
EndEffectorTipAxisObjective(const Eigen::Vector3d &)
Definition: robot_model.cpp:41
bool addBracket(BracketType bracket_type)
Add an element to the robot model with the kinematics/dynamics of a bracket between two actuators...
size_t getFrameCount(HebiFrameType frame_type) const
Return the number of frames in the forward kinematics.
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.
static void setRotX(Eigen::Matrix4d &matrix, double radians)
Definition: robot_model.cpp:97
EIGEN_DEVICE_FUNC const SinReturnType sin() const
HebiStatusCode hebiRobotModelGetBaseFrame(HebiRobotModelPtr robot_model, double *transform)
Retreives the fixed transform from the origin to the input of the first added model element...
HebiStatusCode hebiIKAddConstraintJointAngles(HebiIKPtr ik, double weight, size_t num_joints, const double *min_positions, const double *max_positions)
Define joint angle constraints.
void getJacobianEndEffector(const Eigen::VectorXd &positions, Eigen::MatrixXd &jacobian) const
Generates the Jacobian for the end effector (leaf node) frames(s).
size_t hebiRobotModelGetNumberOfFrames(HebiRobotModelPtr robot_model, HebiFrameType frame_type)
Return the number of frames in the forward kinematic tree of the robot model.
EndEffectorSO3Objective(const Eigen::Matrix3d &)
Definition: robot_model.cpp:22
void getJacobians(HebiFrameType, const Eigen::VectorXd &positions, MatrixXdVector &jacobians) const
Generates the Jacobian for each frame in the given kinematic tree.
static void setSphereInertia(Eigen::VectorXd &inertia, double mass, double radius)
bool addActuator(ActuatorType actuator_type)
Add an element to the robot model with the kinematics/dynamics of an X5 actuator. ...
HebiStatusCode
Definition: hebi.h:19
std::vector< MatrixXd, Eigen::aligned_allocator< Eigen::MatrixXd > > MatrixXdVector
Definition: robot_model.hpp:15
~RobotModel() noexcept
Destructor cleans up robot model object, including all managed elements.


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