Revert "Cleanup: make format."
This reverts commit06b8ddca8f. Add ".clang-format" which prevents these files from being formatted. Commit [0] missed adding this file. [0]:f43da6fc4c
This commit is contained in:
2
intern/itasc/.clang-format
Normal file
2
intern/itasc/.clang-format
Normal file
@@ -0,0 +1,2 @@
|
||||
DisableFormat: true
|
||||
SortIncludes: false
|
||||
@@ -8,8 +8,8 @@
|
||||
|
||||
#include "Armature.hpp"
|
||||
#include <algorithm>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
@@ -19,141 +19,129 @@ static const unsigned int constraintCacheSize = 5;
|
||||
#endif
|
||||
std::string Armature::m_root = "root";
|
||||
|
||||
Armature::Armature()
|
||||
: ControlledObject(),
|
||||
m_tree(),
|
||||
m_njoint(0),
|
||||
m_nconstraint(0),
|
||||
m_noutput(0),
|
||||
m_neffector(0),
|
||||
m_finalized(false),
|
||||
m_cache(NULL),
|
||||
m_buf(NULL),
|
||||
m_qCCh(-1),
|
||||
m_qCTs(0),
|
||||
m_yCCh(-1),
|
||||
Armature::Armature():
|
||||
ControlledObject(),
|
||||
m_tree(),
|
||||
m_njoint(0),
|
||||
m_nconstraint(0),
|
||||
m_noutput(0),
|
||||
m_neffector(0),
|
||||
m_finalized(false),
|
||||
m_cache(NULL),
|
||||
m_buf(NULL),
|
||||
m_qCCh(-1),
|
||||
m_qCTs(0),
|
||||
m_yCCh(-1),
|
||||
#if 0
|
||||
m_yCTs(0),
|
||||
#endif
|
||||
m_qKdl(),
|
||||
m_oldqKdl(),
|
||||
m_newqKdl(),
|
||||
m_qdotKdl(),
|
||||
m_jac(NULL),
|
||||
m_armlength(0.0),
|
||||
m_jacsolver(NULL),
|
||||
m_fksolver(NULL)
|
||||
m_qKdl(),
|
||||
m_oldqKdl(),
|
||||
m_newqKdl(),
|
||||
m_qdotKdl(),
|
||||
m_jac(NULL),
|
||||
m_armlength(0.0),
|
||||
m_jacsolver(NULL),
|
||||
m_fksolver(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
Armature::~Armature()
|
||||
{
|
||||
if (m_jac)
|
||||
delete m_jac;
|
||||
if (m_jacsolver)
|
||||
delete m_jacsolver;
|
||||
if (m_fksolver)
|
||||
delete m_fksolver;
|
||||
for (JointConstraintList::iterator it = m_constraints.begin(); it != m_constraints.end(); it++) {
|
||||
if (*it != NULL)
|
||||
delete (*it);
|
||||
}
|
||||
if (m_buf)
|
||||
delete[] m_buf;
|
||||
m_constraints.clear();
|
||||
if (m_jac)
|
||||
delete m_jac;
|
||||
if (m_jacsolver)
|
||||
delete m_jacsolver;
|
||||
if (m_fksolver)
|
||||
delete m_fksolver;
|
||||
for (JointConstraintList::iterator it=m_constraints.begin(); it != m_constraints.end(); it++) {
|
||||
if (*it != NULL)
|
||||
delete (*it);
|
||||
}
|
||||
if (m_buf)
|
||||
delete [] m_buf;
|
||||
m_constraints.clear();
|
||||
}
|
||||
|
||||
Armature::JointConstraint_struct::JointConstraint_struct(SegmentMap::const_iterator _segment,
|
||||
unsigned int _y_nr,
|
||||
ConstraintCallback _function,
|
||||
void *_param,
|
||||
bool _freeParam,
|
||||
bool _substep)
|
||||
: segment(_segment),
|
||||
value(),
|
||||
values(),
|
||||
function(_function),
|
||||
y_nr(_y_nr),
|
||||
param(_param),
|
||||
freeParam(_freeParam),
|
||||
substep(_substep)
|
||||
Armature::JointConstraint_struct::JointConstraint_struct(SegmentMap::const_iterator _segment, unsigned int _y_nr, ConstraintCallback _function, void* _param, bool _freeParam, bool _substep):
|
||||
segment(_segment), value(), values(), function(_function), y_nr(_y_nr), param(_param), freeParam(_freeParam), substep(_substep)
|
||||
{
|
||||
memset(values, 0, sizeof(values));
|
||||
memset(value, 0, sizeof(value));
|
||||
values[0].feedback = 20.0;
|
||||
values[1].feedback = 20.0;
|
||||
values[2].feedback = 20.0;
|
||||
values[0].tolerance = 1.0;
|
||||
values[1].tolerance = 1.0;
|
||||
values[2].tolerance = 1.0;
|
||||
values[0].values = &value[0];
|
||||
values[1].values = &value[1];
|
||||
values[2].values = &value[2];
|
||||
values[0].number = 1;
|
||||
values[1].number = 1;
|
||||
values[2].number = 1;
|
||||
switch (segment->second.segment.getJoint().getType()) {
|
||||
case Joint::RotX:
|
||||
value[0].id = ID_JOINT_RX;
|
||||
values[0].id = ID_JOINT_RX;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::RotY:
|
||||
value[0].id = ID_JOINT_RY;
|
||||
values[0].id = ID_JOINT_RY;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::RotZ:
|
||||
value[0].id = ID_JOINT_RZ;
|
||||
values[0].id = ID_JOINT_RZ;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::TransX:
|
||||
value[0].id = ID_JOINT_TX;
|
||||
values[0].id = ID_JOINT_TX;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::TransY:
|
||||
value[0].id = ID_JOINT_TY;
|
||||
values[0].id = ID_JOINT_TY;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::TransZ:
|
||||
value[0].id = ID_JOINT_TZ;
|
||||
values[0].id = ID_JOINT_TZ;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::Sphere:
|
||||
values[0].id = value[0].id = ID_JOINT_RX;
|
||||
values[1].id = value[1].id = ID_JOINT_RY;
|
||||
values[2].id = value[2].id = ID_JOINT_RZ;
|
||||
v_nr = 3;
|
||||
break;
|
||||
case Joint::Swing:
|
||||
values[0].id = value[0].id = ID_JOINT_RX;
|
||||
values[1].id = value[1].id = ID_JOINT_RZ;
|
||||
v_nr = 2;
|
||||
break;
|
||||
case Joint::None:
|
||||
break;
|
||||
}
|
||||
memset(values, 0, sizeof(values));
|
||||
memset(value, 0, sizeof(value));
|
||||
values[0].feedback = 20.0;
|
||||
values[1].feedback = 20.0;
|
||||
values[2].feedback = 20.0;
|
||||
values[0].tolerance = 1.0;
|
||||
values[1].tolerance = 1.0;
|
||||
values[2].tolerance = 1.0;
|
||||
values[0].values = &value[0];
|
||||
values[1].values = &value[1];
|
||||
values[2].values = &value[2];
|
||||
values[0].number = 1;
|
||||
values[1].number = 1;
|
||||
values[2].number = 1;
|
||||
switch (segment->second.segment.getJoint().getType()) {
|
||||
case Joint::RotX:
|
||||
value[0].id = ID_JOINT_RX;
|
||||
values[0].id = ID_JOINT_RX;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::RotY:
|
||||
value[0].id = ID_JOINT_RY;
|
||||
values[0].id = ID_JOINT_RY;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::RotZ:
|
||||
value[0].id = ID_JOINT_RZ;
|
||||
values[0].id = ID_JOINT_RZ;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::TransX:
|
||||
value[0].id = ID_JOINT_TX;
|
||||
values[0].id = ID_JOINT_TX;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::TransY:
|
||||
value[0].id = ID_JOINT_TY;
|
||||
values[0].id = ID_JOINT_TY;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::TransZ:
|
||||
value[0].id = ID_JOINT_TZ;
|
||||
values[0].id = ID_JOINT_TZ;
|
||||
v_nr = 1;
|
||||
break;
|
||||
case Joint::Sphere:
|
||||
values[0].id = value[0].id = ID_JOINT_RX;
|
||||
values[1].id = value[1].id = ID_JOINT_RY;
|
||||
values[2].id = value[2].id = ID_JOINT_RZ;
|
||||
v_nr = 3;
|
||||
break;
|
||||
case Joint::Swing:
|
||||
values[0].id = value[0].id = ID_JOINT_RX;
|
||||
values[1].id = value[1].id = ID_JOINT_RZ;
|
||||
v_nr = 2;
|
||||
break;
|
||||
case Joint::None:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Armature::JointConstraint_struct::~JointConstraint_struct()
|
||||
{
|
||||
if (freeParam && param)
|
||||
free(param);
|
||||
if (freeParam && param)
|
||||
free(param);
|
||||
}
|
||||
|
||||
void Armature::initCache(Cache *_cache)
|
||||
{
|
||||
m_cache = _cache;
|
||||
m_qCCh = -1;
|
||||
m_yCCh = -1;
|
||||
m_buf = NULL;
|
||||
if (m_cache) {
|
||||
// add a special channel for the joint
|
||||
m_qCCh = m_cache->addChannel(this, "q", m_qKdl.rows() * sizeof(double));
|
||||
m_cache = _cache;
|
||||
m_qCCh = -1;
|
||||
m_yCCh = -1;
|
||||
m_buf = NULL;
|
||||
if (m_cache) {
|
||||
// add a special channel for the joint
|
||||
m_qCCh = m_cache->addChannel(this, "q", m_qKdl.rows()*sizeof(double));
|
||||
#if 0
|
||||
// for the constraints, instead of creating many different channels, we will
|
||||
// create a single channel for all the constraints
|
||||
@@ -164,36 +152,35 @@ void Armature::initCache(Cache *_cache)
|
||||
// store the initial cache position at timestamp 0
|
||||
pushConstraints(0);
|
||||
#endif
|
||||
pushQ(0);
|
||||
}
|
||||
pushQ(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Armature::pushQ(CacheTS timestamp)
|
||||
{
|
||||
if (m_qCCh >= 0) {
|
||||
// try to keep the cache if the joints are the same
|
||||
m_cache->addCacheVectorIfDifferent(
|
||||
this, m_qCCh, timestamp, m_qKdl(0), m_qKdl.rows(), KDL::epsilon);
|
||||
m_qCTs = timestamp;
|
||||
}
|
||||
if (m_qCCh >= 0) {
|
||||
// try to keep the cache if the joints are the same
|
||||
m_cache->addCacheVectorIfDifferent(this, m_qCCh, timestamp, m_qKdl(0), m_qKdl.rows(), KDL::epsilon);
|
||||
m_qCTs = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/* return true if a m_cache position was loaded */
|
||||
bool Armature::popQ(CacheTS timestamp)
|
||||
{
|
||||
if (m_qCCh >= 0) {
|
||||
double *item;
|
||||
item = (double *)m_cache->getPreviousCacheItem(this, m_qCCh, ×tamp);
|
||||
if (item && m_qCTs != timestamp) {
|
||||
double *q = m_qKdl(0);
|
||||
memcpy(q, item, m_qKdl.rows() * sizeof(double));
|
||||
m_qCTs = timestamp;
|
||||
// changing the joint => recompute the jacobian
|
||||
updateJacobian();
|
||||
}
|
||||
return (item) ? true : false;
|
||||
}
|
||||
return true;
|
||||
if (m_qCCh >= 0) {
|
||||
double* item;
|
||||
item = (double *)m_cache->getPreviousCacheItem(this, m_qCCh, ×tamp);
|
||||
if (item && m_qCTs != timestamp) {
|
||||
double* q = m_qKdl(0);
|
||||
memcpy(q, item, m_qKdl.rows()*sizeof(double));
|
||||
m_qCTs = timestamp;
|
||||
// changing the joint => recompute the jacobian
|
||||
updateJacobian();
|
||||
}
|
||||
return (item) ? true : false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#if 0
|
||||
void Armature::pushConstraints(CacheTS timestamp)
|
||||
@@ -242,606 +229,550 @@ bool Armature::popConstraints(CacheTS timestamp)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Armature::addSegment(const std::string &segment_name,
|
||||
const std::string &hook_name,
|
||||
const Joint &joint,
|
||||
const double &q_rest,
|
||||
const Frame &f_tip,
|
||||
const Inertia &M)
|
||||
bool Armature::addSegment(const std::string& segment_name, const std::string& hook_name, const Joint& joint, const double& q_rest, const Frame& f_tip, const Inertia& M)
|
||||
{
|
||||
if (m_finalized)
|
||||
return false;
|
||||
if (m_finalized)
|
||||
return false;
|
||||
|
||||
Segment segment(joint, f_tip, M);
|
||||
if (!m_tree.addSegment(segment, segment_name, hook_name))
|
||||
return false;
|
||||
int ndof = joint.getNDof();
|
||||
for (int dof = 0; dof < ndof; dof++) {
|
||||
Joint_struct js(joint.getType(), ndof, (&q_rest)[dof]);
|
||||
m_joints.push_back(js);
|
||||
}
|
||||
m_njoint += ndof;
|
||||
return true;
|
||||
Segment segment(joint, f_tip, M);
|
||||
if (!m_tree.addSegment(segment, segment_name, hook_name))
|
||||
return false;
|
||||
int ndof = joint.getNDof();
|
||||
for (int dof=0; dof<ndof; dof++) {
|
||||
Joint_struct js(joint.getType(), ndof, (&q_rest)[dof]);
|
||||
m_joints.push_back(js);
|
||||
}
|
||||
m_njoint+=ndof;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Armature::getSegment(const std::string &name,
|
||||
const unsigned int q_size,
|
||||
const Joint *&p_joint,
|
||||
double &q_rest,
|
||||
double &q,
|
||||
const Frame *&p_tip)
|
||||
bool Armature::getSegment(const std::string& name, const unsigned int q_size, const Joint* &p_joint, double &q_rest, double &q, const Frame* &p_tip)
|
||||
{
|
||||
SegmentMap::const_iterator sit = m_tree.getSegment(name);
|
||||
if (sit == m_tree.getSegments().end())
|
||||
return false;
|
||||
p_joint = &sit->second.segment.getJoint();
|
||||
if (q_size < p_joint->getNDof())
|
||||
return false;
|
||||
p_tip = &sit->second.segment.getFrameToTip();
|
||||
for (unsigned int dof = 0; dof < p_joint->getNDof(); dof++) {
|
||||
(&q_rest)[dof] = m_joints[sit->second.q_nr + dof].rest;
|
||||
(&q)[dof] = m_qKdl[sit->second.q_nr + dof];
|
||||
}
|
||||
return true;
|
||||
SegmentMap::const_iterator sit = m_tree.getSegment(name);
|
||||
if (sit == m_tree.getSegments().end())
|
||||
return false;
|
||||
p_joint = &sit->second.segment.getJoint();
|
||||
if (q_size < p_joint->getNDof())
|
||||
return false;
|
||||
p_tip = &sit->second.segment.getFrameToTip();
|
||||
for (unsigned int dof=0; dof<p_joint->getNDof(); dof++) {
|
||||
(&q_rest)[dof] = m_joints[sit->second.q_nr+dof].rest;
|
||||
(&q)[dof] = m_qKdl[sit->second.q_nr+dof];
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
double Armature::getMaxJointChange()
|
||||
{
|
||||
if (!m_finalized)
|
||||
return 0.0;
|
||||
double maxJoint = 0.0;
|
||||
for (unsigned int i = 0; i < m_njoint; i++) {
|
||||
// this is a very rough calculation, it doesn't work well for spherical joint
|
||||
double joint = fabs(m_oldqKdl[i] - m_qKdl[i]);
|
||||
if (maxJoint < joint)
|
||||
maxJoint = joint;
|
||||
}
|
||||
return maxJoint;
|
||||
if (!m_finalized)
|
||||
return 0.0;
|
||||
double maxJoint = 0.0;
|
||||
for (unsigned int i=0; i<m_njoint; i++) {
|
||||
// this is a very rough calculation, it doesn't work well for spherical joint
|
||||
double joint = fabs(m_oldqKdl[i]-m_qKdl[i]);
|
||||
if (maxJoint < joint)
|
||||
maxJoint = joint;
|
||||
}
|
||||
return maxJoint;
|
||||
}
|
||||
|
||||
double Armature::getMaxEndEffectorChange()
|
||||
{
|
||||
if (!m_finalized)
|
||||
return 0.0;
|
||||
double maxDelta = 0.0;
|
||||
double delta;
|
||||
Twist twist;
|
||||
for (unsigned int i = 0; i < m_neffector; i++) {
|
||||
twist = diff(m_effectors[i].pose, m_effectors[i].oldpose);
|
||||
delta = twist.rot.Norm();
|
||||
if (delta > maxDelta)
|
||||
maxDelta = delta;
|
||||
delta = twist.vel.Norm();
|
||||
if (delta > maxDelta)
|
||||
maxDelta = delta;
|
||||
}
|
||||
return maxDelta;
|
||||
if (!m_finalized)
|
||||
return 0.0;
|
||||
double maxDelta = 0.0;
|
||||
double delta;
|
||||
Twist twist;
|
||||
for (unsigned int i = 0; i<m_neffector; i++) {
|
||||
twist = diff(m_effectors[i].pose, m_effectors[i].oldpose);
|
||||
delta = twist.rot.Norm();
|
||||
if (delta > maxDelta)
|
||||
maxDelta = delta;
|
||||
delta = twist.vel.Norm();
|
||||
if (delta > maxDelta)
|
||||
maxDelta = delta;
|
||||
}
|
||||
return maxDelta;
|
||||
}
|
||||
|
||||
int Armature::addConstraint(const std::string &segment_name,
|
||||
ConstraintCallback _function,
|
||||
void *_param,
|
||||
bool _freeParam,
|
||||
bool _substep)
|
||||
int Armature::addConstraint(const std::string& segment_name, ConstraintCallback _function, void* _param, bool _freeParam, bool _substep)
|
||||
{
|
||||
SegmentMap::const_iterator segment_it = m_tree.getSegment(segment_name);
|
||||
// not suitable for NDof joints
|
||||
if (segment_it == m_tree.getSegments().end()) {
|
||||
if (_freeParam && _param)
|
||||
free(_param);
|
||||
return -1;
|
||||
}
|
||||
JointConstraintList::iterator constraint_it;
|
||||
JointConstraint_struct *pConstraint;
|
||||
int iConstraint;
|
||||
for (iConstraint = 0, constraint_it = m_constraints.begin();
|
||||
constraint_it != m_constraints.end();
|
||||
constraint_it++, iConstraint++)
|
||||
{
|
||||
pConstraint = *constraint_it;
|
||||
if (pConstraint->segment == segment_it) {
|
||||
// redefining a constraint
|
||||
if (pConstraint->freeParam && pConstraint->param) {
|
||||
free(pConstraint->param);
|
||||
}
|
||||
pConstraint->function = _function;
|
||||
pConstraint->param = _param;
|
||||
pConstraint->freeParam = _freeParam;
|
||||
pConstraint->substep = _substep;
|
||||
return iConstraint;
|
||||
}
|
||||
}
|
||||
if (m_finalized) {
|
||||
if (_freeParam && _param)
|
||||
free(_param);
|
||||
return -1;
|
||||
}
|
||||
// new constraint, append
|
||||
pConstraint = new JointConstraint_struct(
|
||||
segment_it, m_noutput, _function, _param, _freeParam, _substep);
|
||||
m_constraints.push_back(pConstraint);
|
||||
m_noutput += pConstraint->v_nr;
|
||||
return m_nconstraint++;
|
||||
SegmentMap::const_iterator segment_it = m_tree.getSegment(segment_name);
|
||||
// not suitable for NDof joints
|
||||
if (segment_it == m_tree.getSegments().end()) {
|
||||
if (_freeParam && _param)
|
||||
free(_param);
|
||||
return -1;
|
||||
}
|
||||
JointConstraintList::iterator constraint_it;
|
||||
JointConstraint_struct* pConstraint;
|
||||
int iConstraint;
|
||||
for (iConstraint=0, constraint_it=m_constraints.begin(); constraint_it != m_constraints.end(); constraint_it++, iConstraint++) {
|
||||
pConstraint = *constraint_it;
|
||||
if (pConstraint->segment == segment_it) {
|
||||
// redefining a constraint
|
||||
if (pConstraint->freeParam && pConstraint->param) {
|
||||
free(pConstraint->param);
|
||||
}
|
||||
pConstraint->function = _function;
|
||||
pConstraint->param = _param;
|
||||
pConstraint->freeParam = _freeParam;
|
||||
pConstraint->substep = _substep;
|
||||
return iConstraint;
|
||||
}
|
||||
}
|
||||
if (m_finalized) {
|
||||
if (_freeParam && _param)
|
||||
free(_param);
|
||||
return -1;
|
||||
}
|
||||
// new constraint, append
|
||||
pConstraint = new JointConstraint_struct(segment_it, m_noutput, _function, _param, _freeParam, _substep);
|
||||
m_constraints.push_back(pConstraint);
|
||||
m_noutput += pConstraint->v_nr;
|
||||
return m_nconstraint++;
|
||||
}
|
||||
|
||||
int Armature::addLimitConstraint(const std::string &segment_name,
|
||||
unsigned int dof,
|
||||
double _min,
|
||||
double _max)
|
||||
int Armature::addLimitConstraint(const std::string& segment_name, unsigned int dof, double _min, double _max)
|
||||
{
|
||||
SegmentMap::const_iterator segment_it = m_tree.getSegment(segment_name);
|
||||
if (segment_it == m_tree.getSegments().end())
|
||||
return -1;
|
||||
const Joint &joint = segment_it->second.segment.getJoint();
|
||||
if (joint.getNDof() != 1 && joint.getType() != Joint::Swing) {
|
||||
// not suitable for Sphere joints
|
||||
return -1;
|
||||
}
|
||||
if ((joint.getNDof() == 1 && dof > 0) || (joint.getNDof() == 2 && dof > 1))
|
||||
return -1;
|
||||
Joint_struct &p_joint = m_joints[segment_it->second.q_nr + dof];
|
||||
p_joint.min = _min;
|
||||
p_joint.max = _max;
|
||||
p_joint.useLimit = true;
|
||||
return 0;
|
||||
SegmentMap::const_iterator segment_it = m_tree.getSegment(segment_name);
|
||||
if (segment_it == m_tree.getSegments().end())
|
||||
return -1;
|
||||
const Joint& joint = segment_it->second.segment.getJoint();
|
||||
if (joint.getNDof() != 1 && joint.getType() != Joint::Swing) {
|
||||
// not suitable for Sphere joints
|
||||
return -1;
|
||||
}
|
||||
if ((joint.getNDof() == 1 && dof > 0) || (joint.getNDof() == 2 && dof > 1))
|
||||
return -1;
|
||||
Joint_struct& p_joint = m_joints[segment_it->second.q_nr+dof];
|
||||
p_joint.min = _min;
|
||||
p_joint.max = _max;
|
||||
p_joint.useLimit = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Armature::addEndEffector(const std::string &name)
|
||||
int Armature::addEndEffector(const std::string& name)
|
||||
{
|
||||
const SegmentMap &segments = m_tree.getSegments();
|
||||
if (segments.find(name) == segments.end())
|
||||
return -1;
|
||||
const SegmentMap& segments = m_tree.getSegments();
|
||||
if (segments.find(name) == segments.end())
|
||||
return -1;
|
||||
|
||||
EffectorList::const_iterator it;
|
||||
int ee;
|
||||
for (it = m_effectors.begin(), ee = 0; it != m_effectors.end(); it++, ee++) {
|
||||
if (it->name == name)
|
||||
return ee;
|
||||
}
|
||||
if (m_finalized)
|
||||
return -1;
|
||||
Effector_struct effector(name);
|
||||
m_effectors.push_back(effector);
|
||||
return m_neffector++;
|
||||
EffectorList::const_iterator it;
|
||||
int ee;
|
||||
for (it=m_effectors.begin(), ee=0; it!=m_effectors.end(); it++, ee++) {
|
||||
if (it->name == name)
|
||||
return ee;
|
||||
}
|
||||
if (m_finalized)
|
||||
return -1;
|
||||
Effector_struct effector(name);
|
||||
m_effectors.push_back(effector);
|
||||
return m_neffector++;
|
||||
}
|
||||
|
||||
bool Armature::finalize()
|
||||
{
|
||||
unsigned int i, j, c;
|
||||
if (m_finalized)
|
||||
return true;
|
||||
if (m_njoint == 0)
|
||||
return false;
|
||||
initialize(m_njoint, m_noutput, m_neffector);
|
||||
for (i = c = 0; i < m_nconstraint; i++) {
|
||||
JointConstraint_struct *pConstraint = m_constraints[i];
|
||||
for (j = 0; j < pConstraint->v_nr; j++, c++) {
|
||||
m_Cq(c, pConstraint->segment->second.q_nr + j) = 1.0;
|
||||
m_Wy(c) = pConstraint->values[j]
|
||||
.alpha /*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
|
||||
}
|
||||
}
|
||||
m_jacsolver = new KDL::TreeJntToJacSolver(m_tree);
|
||||
m_fksolver = new KDL::TreeFkSolverPos_recursive(m_tree);
|
||||
m_jac = new Jacobian(m_njoint);
|
||||
m_qKdl.resize(m_njoint);
|
||||
m_oldqKdl.resize(m_njoint);
|
||||
m_newqKdl.resize(m_njoint);
|
||||
m_qdotKdl.resize(m_njoint);
|
||||
for (i = 0; i < m_njoint; i++) {
|
||||
m_newqKdl[i] = m_oldqKdl[i] = m_qKdl[i] = m_joints[i].rest;
|
||||
}
|
||||
updateJacobian();
|
||||
// estimate the maximum size of the robot arms
|
||||
double length;
|
||||
m_armlength = 0.0;
|
||||
for (i = 0; i < m_neffector; i++) {
|
||||
length = 0.0;
|
||||
KDL::SegmentMap::value_type const *sit = m_tree.getSegmentPtr(m_effectors[i].name);
|
||||
while (sit->first != "root") {
|
||||
Frame tip = sit->second.segment.pose(m_qKdl(sit->second.q_nr));
|
||||
length += tip.p.Norm();
|
||||
sit = sit->second.parent;
|
||||
}
|
||||
if (length > m_armlength)
|
||||
m_armlength = length;
|
||||
}
|
||||
if (m_armlength < KDL::epsilon)
|
||||
m_armlength = KDL::epsilon;
|
||||
m_finalized = true;
|
||||
return true;
|
||||
unsigned int i, j, c;
|
||||
if (m_finalized)
|
||||
return true;
|
||||
if (m_njoint == 0)
|
||||
return false;
|
||||
initialize(m_njoint, m_noutput, m_neffector);
|
||||
for (i=c=0; i<m_nconstraint; i++) {
|
||||
JointConstraint_struct* pConstraint = m_constraints[i];
|
||||
for (j=0; j<pConstraint->v_nr; j++, c++) {
|
||||
m_Cq(c,pConstraint->segment->second.q_nr+j) = 1.0;
|
||||
m_Wy(c) = pConstraint->values[j].alpha/*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
|
||||
}
|
||||
}
|
||||
m_jacsolver= new KDL::TreeJntToJacSolver(m_tree);
|
||||
m_fksolver = new KDL::TreeFkSolverPos_recursive(m_tree);
|
||||
m_jac = new Jacobian(m_njoint);
|
||||
m_qKdl.resize(m_njoint);
|
||||
m_oldqKdl.resize(m_njoint);
|
||||
m_newqKdl.resize(m_njoint);
|
||||
m_qdotKdl.resize(m_njoint);
|
||||
for (i=0; i<m_njoint; i++) {
|
||||
m_newqKdl[i] = m_oldqKdl[i] = m_qKdl[i] = m_joints[i].rest;
|
||||
}
|
||||
updateJacobian();
|
||||
// estimate the maximum size of the robot arms
|
||||
double length;
|
||||
m_armlength = 0.0;
|
||||
for (i=0; i<m_neffector; i++) {
|
||||
length = 0.0;
|
||||
KDL::SegmentMap::value_type const *sit = m_tree.getSegmentPtr(m_effectors[i].name);
|
||||
while (sit->first != "root") {
|
||||
Frame tip = sit->second.segment.pose(m_qKdl(sit->second.q_nr));
|
||||
length += tip.p.Norm();
|
||||
sit = sit->second.parent;
|
||||
}
|
||||
if (length > m_armlength)
|
||||
m_armlength = length;
|
||||
}
|
||||
if (m_armlength < KDL::epsilon)
|
||||
m_armlength = KDL::epsilon;
|
||||
m_finalized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Armature::pushCache(const Timestamp ×tamp)
|
||||
void Armature::pushCache(const Timestamp& timestamp)
|
||||
{
|
||||
if (!timestamp.substep && timestamp.cache) {
|
||||
pushQ(timestamp.cacheTimestamp);
|
||||
// pushConstraints(timestamp.cacheTimestamp);
|
||||
}
|
||||
if (!timestamp.substep && timestamp.cache) {
|
||||
pushQ(timestamp.cacheTimestamp);
|
||||
//pushConstraints(timestamp.cacheTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
bool Armature::setJointArray(const KDL::JntArray &joints)
|
||||
bool Armature::setJointArray(const KDL::JntArray& joints)
|
||||
{
|
||||
if (!m_finalized)
|
||||
return false;
|
||||
if (joints.rows() != m_qKdl.rows())
|
||||
return false;
|
||||
m_qKdl = joints;
|
||||
updateJacobian();
|
||||
return true;
|
||||
if (!m_finalized)
|
||||
return false;
|
||||
if (joints.rows() != m_qKdl.rows())
|
||||
return false;
|
||||
m_qKdl = joints;
|
||||
updateJacobian();
|
||||
return true;
|
||||
}
|
||||
|
||||
const KDL::JntArray &Armature::getJointArray()
|
||||
const KDL::JntArray& Armature::getJointArray()
|
||||
{
|
||||
return m_qKdl;
|
||||
return m_qKdl;
|
||||
}
|
||||
|
||||
bool Armature::updateJoint(const Timestamp ×tamp, JointLockCallback &callback)
|
||||
bool Armature::updateJoint(const Timestamp& timestamp, JointLockCallback& callback)
|
||||
{
|
||||
if (!m_finalized)
|
||||
return false;
|
||||
if (!m_finalized)
|
||||
return false;
|
||||
|
||||
// integration and joint limit
|
||||
// for spherical joint we must use a more sophisticated method
|
||||
unsigned int q_nr;
|
||||
double* qdot=m_qdotKdl(0);
|
||||
double* q=m_qKdl(0);
|
||||
double* newq=m_newqKdl(0);
|
||||
double norm, qx, qz, CX, CZ, sx, sz;
|
||||
bool locked = false;
|
||||
int unlocked = 0;
|
||||
|
||||
// integration and joint limit
|
||||
// for spherical joint we must use a more sophisticated method
|
||||
unsigned int q_nr;
|
||||
double *qdot = m_qdotKdl(0);
|
||||
double *q = m_qKdl(0);
|
||||
double *newq = m_newqKdl(0);
|
||||
double norm, qx, qz, CX, CZ, sx, sz;
|
||||
bool locked = false;
|
||||
int unlocked = 0;
|
||||
for (q_nr=0; q_nr<m_nq; ++q_nr)
|
||||
qdot[q_nr]=m_qdot[q_nr];
|
||||
|
||||
for (q_nr = 0; q_nr < m_nq; ++q_nr)
|
||||
qdot[q_nr] = m_qdot[q_nr];
|
||||
|
||||
for (q_nr = 0; q_nr < m_nq;) {
|
||||
Joint_struct *joint = &m_joints[q_nr];
|
||||
if (!joint->locked) {
|
||||
switch (joint->type) {
|
||||
case KDL::Joint::Swing: {
|
||||
KDL::Rotation base = KDL::Rot(KDL::Vector(q[0], 0.0, q[1]));
|
||||
(base * KDL::Rot(KDL::Vector(qdot[0], 0.0, qdot[1]) * timestamp.realTimestep))
|
||||
.GetXZRot()
|
||||
.GetValue(newq);
|
||||
if (joint[0].useLimit) {
|
||||
if (joint[1].useLimit) {
|
||||
// elliptical limit
|
||||
sx = sz = 1.0;
|
||||
qx = newq[0];
|
||||
qz = newq[1];
|
||||
// determine in which quadrant we are
|
||||
if (qx > 0.0 && qz > 0.0) {
|
||||
CX = joint[0].max;
|
||||
CZ = joint[1].max;
|
||||
}
|
||||
else if (qx <= 0.0 && qz > 0.0) {
|
||||
CX = -joint[0].min;
|
||||
CZ = joint[1].max;
|
||||
qx = -qx;
|
||||
sx = -1.0;
|
||||
}
|
||||
else if (qx <= 0.0 && qz <= 0.0) {
|
||||
CX = -joint[0].min;
|
||||
CZ = -joint[1].min;
|
||||
qx = -qx;
|
||||
qz = -qz;
|
||||
sx = sz = -1.0;
|
||||
}
|
||||
else {
|
||||
CX = joint[0].max;
|
||||
CZ = -joint[0].min;
|
||||
qz = -qz;
|
||||
sz = -1.0;
|
||||
}
|
||||
if (CX < KDL::epsilon || CZ < KDL::epsilon) {
|
||||
// quadrant is degenerated
|
||||
if (qx > CX) {
|
||||
newq[0] = CX * sx;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
if (qz > CZ) {
|
||||
newq[1] = CZ * sz;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// general case
|
||||
qx /= CX;
|
||||
qz /= CZ;
|
||||
norm = KDL::sqrt(KDL::sqr(qx) + KDL::sqr(qz));
|
||||
if (norm > 1.0) {
|
||||
norm = 1.0 / norm;
|
||||
newq[0] = qx * norm * CX * sx;
|
||||
newq[1] = qz * norm * CZ * sz;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// limit on X only
|
||||
qx = newq[0];
|
||||
if (qx > joint[0].max) {
|
||||
newq[0] = joint[0].max;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
else if (qx < joint[0].min) {
|
||||
newq[0] = joint[0].min;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (joint[1].useLimit) {
|
||||
// limit on Z only
|
||||
qz = newq[1];
|
||||
if (qz > joint[1].max) {
|
||||
newq[1] = joint[1].max;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
else if (qz < joint[1].min) {
|
||||
newq[1] = joint[1].min;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
if (joint[0].locked) {
|
||||
// check the difference from previous position
|
||||
locked = true;
|
||||
norm = KDL::sqr(newq[0] - q[0]) + KDL::sqr(newq[1] - q[1]);
|
||||
if (norm < KDL::epsilon2) {
|
||||
// joint didn't move, no need to update the jacobian
|
||||
callback.lockJoint(q_nr, 2);
|
||||
}
|
||||
else {
|
||||
// joint moved, compute the corresponding velocity
|
||||
double deltaq[2];
|
||||
(base.Inverse() * KDL::Rot(KDL::Vector(newq[0], 0.0, newq[1])))
|
||||
.GetXZRot()
|
||||
.GetValue(deltaq);
|
||||
deltaq[0] /= timestamp.realTimestep;
|
||||
deltaq[1] /= timestamp.realTimestep;
|
||||
callback.lockJoint(q_nr, 2, deltaq);
|
||||
// no need to update the other joints, it will be done after next rerun
|
||||
goto end_loop;
|
||||
}
|
||||
}
|
||||
else
|
||||
unlocked++;
|
||||
break;
|
||||
}
|
||||
case KDL::Joint::Sphere: {
|
||||
(KDL::Rot(KDL::Vector(q)) * KDL::Rot(KDL::Vector(qdot) * timestamp.realTimestep))
|
||||
.GetRot()
|
||||
.GetValue(newq);
|
||||
// no limit on this joint
|
||||
unlocked++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
for (unsigned int i = 0; i < joint->ndof; i++) {
|
||||
newq[i] = q[i] + qdot[i] * timestamp.realTimestep;
|
||||
if (joint[i].useLimit) {
|
||||
if (newq[i] > joint[i].max) {
|
||||
newq[i] = joint[i].max;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
else if (newq[i] < joint[i].min) {
|
||||
newq[i] = joint[i].min;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (joint[0].locked) {
|
||||
locked = true;
|
||||
norm = 0.0;
|
||||
// compute delta to locked position
|
||||
for (unsigned int i = 0; i < joint->ndof; i++) {
|
||||
qdot[i] = newq[i] - q[i];
|
||||
norm += qdot[i] * qdot[i];
|
||||
}
|
||||
if (norm < KDL::epsilon2) {
|
||||
// joint didn't move, no need to update the jacobian
|
||||
callback.lockJoint(q_nr, joint->ndof);
|
||||
}
|
||||
else {
|
||||
// solver needs velocity, compute equivalent velocity
|
||||
for (unsigned int i = 0; i < joint->ndof; i++) {
|
||||
qdot[i] /= timestamp.realTimestep;
|
||||
}
|
||||
callback.lockJoint(q_nr, joint->ndof, qdot);
|
||||
goto end_loop;
|
||||
}
|
||||
}
|
||||
else
|
||||
unlocked++;
|
||||
}
|
||||
}
|
||||
qdot += joint->ndof;
|
||||
q += joint->ndof;
|
||||
newq += joint->ndof;
|
||||
q_nr += joint->ndof;
|
||||
}
|
||||
for (q_nr=0; q_nr<m_nq; ) {
|
||||
Joint_struct* joint = &m_joints[q_nr];
|
||||
if (!joint->locked) {
|
||||
switch (joint->type) {
|
||||
case KDL::Joint::Swing:
|
||||
{
|
||||
KDL::Rotation base = KDL::Rot(KDL::Vector(q[0],0.0,q[1]));
|
||||
(base*KDL::Rot(KDL::Vector(qdot[0],0.0,qdot[1])*timestamp.realTimestep)).GetXZRot().GetValue(newq);
|
||||
if (joint[0].useLimit) {
|
||||
if (joint[1].useLimit) {
|
||||
// elliptical limit
|
||||
sx = sz = 1.0;
|
||||
qx = newq[0];
|
||||
qz = newq[1];
|
||||
// determine in which quadrant we are
|
||||
if (qx > 0.0 && qz > 0.0) {
|
||||
CX = joint[0].max;
|
||||
CZ = joint[1].max;
|
||||
} else if (qx <= 0.0 && qz > 0.0) {
|
||||
CX = -joint[0].min;
|
||||
CZ = joint[1].max;
|
||||
qx = -qx;
|
||||
sx = -1.0;
|
||||
} else if (qx <= 0.0 && qz <= 0.0) {
|
||||
CX = -joint[0].min;
|
||||
CZ = -joint[1].min;
|
||||
qx = -qx;
|
||||
qz = -qz;
|
||||
sx = sz = -1.0;
|
||||
} else {
|
||||
CX = joint[0].max;
|
||||
CZ = -joint[0].min;
|
||||
qz = -qz;
|
||||
sz = -1.0;
|
||||
}
|
||||
if (CX < KDL::epsilon || CZ < KDL::epsilon) {
|
||||
// quadrant is degenerated
|
||||
if (qx > CX) {
|
||||
newq[0] = CX*sx;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
if (qz > CZ) {
|
||||
newq[1] = CZ*sz;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
} else {
|
||||
// general case
|
||||
qx /= CX;
|
||||
qz /= CZ;
|
||||
norm = KDL::sqrt(KDL::sqr(qx)+KDL::sqr(qz));
|
||||
if (norm > 1.0) {
|
||||
norm = 1.0/norm;
|
||||
newq[0] = qx*norm*CX*sx;
|
||||
newq[1] = qz*norm*CZ*sz;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// limit on X only
|
||||
qx = newq[0];
|
||||
if (qx > joint[0].max) {
|
||||
newq[0] = joint[0].max;
|
||||
joint[0].locked = true;
|
||||
} else if (qx < joint[0].min) {
|
||||
newq[0] = joint[0].min;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
} else if (joint[1].useLimit) {
|
||||
// limit on Z only
|
||||
qz = newq[1];
|
||||
if (qz > joint[1].max) {
|
||||
newq[1] = joint[1].max;
|
||||
joint[0].locked = true;
|
||||
} else if (qz < joint[1].min) {
|
||||
newq[1] = joint[1].min;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
if (joint[0].locked) {
|
||||
// check the difference from previous position
|
||||
locked = true;
|
||||
norm = KDL::sqr(newq[0]-q[0])+KDL::sqr(newq[1]-q[1]);
|
||||
if (norm < KDL::epsilon2) {
|
||||
// joint didn't move, no need to update the jacobian
|
||||
callback.lockJoint(q_nr, 2);
|
||||
} else {
|
||||
// joint moved, compute the corresponding velocity
|
||||
double deltaq[2];
|
||||
(base.Inverse()*KDL::Rot(KDL::Vector(newq[0],0.0,newq[1]))).GetXZRot().GetValue(deltaq);
|
||||
deltaq[0] /= timestamp.realTimestep;
|
||||
deltaq[1] /= timestamp.realTimestep;
|
||||
callback.lockJoint(q_nr, 2, deltaq);
|
||||
// no need to update the other joints, it will be done after next rerun
|
||||
goto end_loop;
|
||||
}
|
||||
} else
|
||||
unlocked++;
|
||||
break;
|
||||
}
|
||||
case KDL::Joint::Sphere:
|
||||
{
|
||||
(KDL::Rot(KDL::Vector(q))*KDL::Rot(KDL::Vector(qdot)*timestamp.realTimestep)).GetRot().GetValue(newq);
|
||||
// no limit on this joint
|
||||
unlocked++;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
for (unsigned int i=0; i<joint->ndof; i++) {
|
||||
newq[i] = q[i]+qdot[i]*timestamp.realTimestep;
|
||||
if (joint[i].useLimit) {
|
||||
if (newq[i] > joint[i].max) {
|
||||
newq[i] = joint[i].max;
|
||||
joint[0].locked = true;
|
||||
} else if (newq[i] < joint[i].min) {
|
||||
newq[i] = joint[i].min;
|
||||
joint[0].locked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (joint[0].locked) {
|
||||
locked = true;
|
||||
norm = 0.0;
|
||||
// compute delta to locked position
|
||||
for (unsigned int i=0; i<joint->ndof; i++) {
|
||||
qdot[i] = newq[i] - q[i];
|
||||
norm += qdot[i]*qdot[i];
|
||||
}
|
||||
if (norm < KDL::epsilon2) {
|
||||
// joint didn't move, no need to update the jacobian
|
||||
callback.lockJoint(q_nr, joint->ndof);
|
||||
} else {
|
||||
// solver needs velocity, compute equivalent velocity
|
||||
for (unsigned int i=0; i<joint->ndof; i++) {
|
||||
qdot[i] /= timestamp.realTimestep;
|
||||
}
|
||||
callback.lockJoint(q_nr, joint->ndof, qdot);
|
||||
goto end_loop;
|
||||
}
|
||||
} else
|
||||
unlocked++;
|
||||
}
|
||||
}
|
||||
qdot += joint->ndof;
|
||||
q += joint->ndof;
|
||||
newq += joint->ndof;
|
||||
q_nr += joint->ndof;
|
||||
}
|
||||
end_loop:
|
||||
// check if there any other unlocked joint
|
||||
for (; q_nr < m_nq;) {
|
||||
Joint_struct *joint = &m_joints[q_nr];
|
||||
if (!joint->locked)
|
||||
unlocked++;
|
||||
q_nr += joint->ndof;
|
||||
}
|
||||
// if all joints have been locked no need to run the solver again
|
||||
return (unlocked) ? locked : false;
|
||||
// check if there any other unlocked joint
|
||||
for ( ; q_nr<m_nq; ) {
|
||||
Joint_struct* joint = &m_joints[q_nr];
|
||||
if (!joint->locked)
|
||||
unlocked++;
|
||||
q_nr += joint->ndof;
|
||||
}
|
||||
// if all joints have been locked no need to run the solver again
|
||||
return (unlocked) ? locked : false;
|
||||
}
|
||||
|
||||
void Armature::updateKinematics(const Timestamp ×tamp)
|
||||
{
|
||||
void Armature::updateKinematics(const Timestamp& timestamp){
|
||||
|
||||
// Integrate m_qdot
|
||||
if (!m_finalized)
|
||||
return;
|
||||
//Integrate m_qdot
|
||||
if (!m_finalized)
|
||||
return;
|
||||
|
||||
// the new joint value have been computed already, just copy
|
||||
memcpy(m_qKdl(0), m_newqKdl(0), sizeof(double) * m_qKdl.rows());
|
||||
pushCache(timestamp);
|
||||
updateJacobian();
|
||||
// here update the desired output.
|
||||
// We assume constant desired output for the joint limit constraint, no need to update it.
|
||||
// the new joint value have been computed already, just copy
|
||||
memcpy(m_qKdl(0), m_newqKdl(0), sizeof(double)*m_qKdl.rows());
|
||||
pushCache(timestamp);
|
||||
updateJacobian();
|
||||
// here update the desired output.
|
||||
// We assume constant desired output for the joint limit constraint, no need to update it.
|
||||
}
|
||||
|
||||
void Armature::updateJacobian()
|
||||
{
|
||||
// calculate pose and jacobian
|
||||
for (unsigned int ee = 0; ee < m_nee; ee++) {
|
||||
m_fksolver->JntToCart(m_qKdl, m_effectors[ee].pose, m_effectors[ee].name, m_root);
|
||||
m_jacsolver->JntToJac(m_qKdl, *m_jac, m_effectors[ee].name);
|
||||
// get the jacobian for the base point, to prepare transformation to world reference
|
||||
changeRefPoint(*m_jac, -m_effectors[ee].pose.p, *m_jac);
|
||||
// copy to Jq:
|
||||
e_matrix &Jq = m_JqArray[ee];
|
||||
for (unsigned int i = 0; i < 6; i++) {
|
||||
for (unsigned int j = 0; j < m_nq; j++)
|
||||
Jq(i, j) = (*m_jac)(i, j);
|
||||
}
|
||||
}
|
||||
// remember that this object has moved
|
||||
m_updated = true;
|
||||
//calculate pose and jacobian
|
||||
for (unsigned int ee=0; ee<m_nee; ee++) {
|
||||
m_fksolver->JntToCart(m_qKdl,m_effectors[ee].pose,m_effectors[ee].name,m_root);
|
||||
m_jacsolver->JntToJac(m_qKdl,*m_jac,m_effectors[ee].name);
|
||||
// get the jacobian for the base point, to prepare transformation to world reference
|
||||
changeRefPoint(*m_jac,-m_effectors[ee].pose.p,*m_jac);
|
||||
//copy to Jq:
|
||||
e_matrix& Jq = m_JqArray[ee];
|
||||
for(unsigned int i=0;i<6;i++) {
|
||||
for(unsigned int j=0;j<m_nq;j++)
|
||||
Jq(i,j)=(*m_jac)(i,j);
|
||||
}
|
||||
}
|
||||
// remember that this object has moved
|
||||
m_updated = true;
|
||||
}
|
||||
|
||||
const Frame &Armature::getPose(const unsigned int ee)
|
||||
const Frame& Armature::getPose(const unsigned int ee)
|
||||
{
|
||||
if (!m_finalized)
|
||||
return F_identity;
|
||||
return (ee >= m_nee) ? F_identity : m_effectors[ee].pose;
|
||||
if (!m_finalized)
|
||||
return F_identity;
|
||||
return (ee >= m_nee) ? F_identity : m_effectors[ee].pose;
|
||||
}
|
||||
|
||||
bool Armature::getRelativeFrame(Frame &result,
|
||||
const std::string &segment_name,
|
||||
const std::string &base_name)
|
||||
bool Armature::getRelativeFrame(Frame& result, const std::string& segment_name, const std::string& base_name)
|
||||
{
|
||||
if (!m_finalized)
|
||||
return false;
|
||||
return (m_fksolver->JntToCart(m_qKdl, result, segment_name, base_name) < 0) ? false : true;
|
||||
if (!m_finalized)
|
||||
return false;
|
||||
return (m_fksolver->JntToCart(m_qKdl,result,segment_name,base_name) < 0) ? false : true;
|
||||
}
|
||||
|
||||
void Armature::updateControlOutput(const Timestamp ×tamp)
|
||||
void Armature::updateControlOutput(const Timestamp& timestamp)
|
||||
{
|
||||
if (!m_finalized)
|
||||
return;
|
||||
if (!m_finalized)
|
||||
return;
|
||||
|
||||
if (!timestamp.substep && !timestamp.reiterate && timestamp.interpolate) {
|
||||
popQ(timestamp.cacheTimestamp);
|
||||
// popConstraints(timestamp.cacheTimestamp);
|
||||
}
|
||||
|
||||
if (!timestamp.substep) {
|
||||
// save previous joint state for getMaxJointChange()
|
||||
memcpy(m_oldqKdl(0), m_qKdl(0), sizeof(double) * m_qKdl.rows());
|
||||
for (unsigned int i = 0; i < m_neffector; i++) {
|
||||
m_effectors[i].oldpose = m_effectors[i].pose;
|
||||
}
|
||||
}
|
||||
if (!timestamp.substep && !timestamp.reiterate && timestamp.interpolate) {
|
||||
popQ(timestamp.cacheTimestamp);
|
||||
//popConstraints(timestamp.cacheTimestamp);
|
||||
}
|
||||
|
||||
// remove all joint lock
|
||||
for (JointList::iterator jit = m_joints.begin(); jit != m_joints.end(); ++jit) {
|
||||
(*jit).locked = false;
|
||||
}
|
||||
if (!timestamp.substep) {
|
||||
// save previous joint state for getMaxJointChange()
|
||||
memcpy(m_oldqKdl(0), m_qKdl(0), sizeof(double)*m_qKdl.rows());
|
||||
for (unsigned int i=0; i<m_neffector; i++) {
|
||||
m_effectors[i].oldpose = m_effectors[i].pose;
|
||||
}
|
||||
}
|
||||
|
||||
JointConstraintList::iterator it;
|
||||
unsigned int iConstraint;
|
||||
// remove all joint lock
|
||||
for (JointList::iterator jit=m_joints.begin(); jit!=m_joints.end(); ++jit) {
|
||||
(*jit).locked = false;
|
||||
}
|
||||
|
||||
// scan through the constraints and call the callback functions
|
||||
for (iConstraint = 0, it = m_constraints.begin(); it != m_constraints.end(); it++, iConstraint++)
|
||||
{
|
||||
JointConstraint_struct *pConstraint = *it;
|
||||
unsigned int nr, i;
|
||||
for (i = 0, nr = pConstraint->segment->second.q_nr; i < pConstraint->v_nr; i++, nr++) {
|
||||
*(double *)&pConstraint->value[i].y = m_qKdl[nr];
|
||||
*(double *)&pConstraint->value[i].ydot = m_qdotKdl[nr];
|
||||
}
|
||||
if (pConstraint->function &&
|
||||
(pConstraint->substep || (!timestamp.reiterate && !timestamp.substep)))
|
||||
{
|
||||
(*pConstraint->function)(
|
||||
timestamp, pConstraint->values, pConstraint->v_nr, pConstraint->param);
|
||||
}
|
||||
// recompute the weight in any case, that's the most likely modification
|
||||
for (i = 0, nr = pConstraint->y_nr; i < pConstraint->v_nr; i++, nr++) {
|
||||
m_Wy(nr) = pConstraint->values[i]
|
||||
.alpha /*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
|
||||
m_ydot(nr) = pConstraint->value[i].yddot +
|
||||
pConstraint->values[i].feedback *
|
||||
(pConstraint->value[i].yd - pConstraint->value[i].y);
|
||||
}
|
||||
}
|
||||
JointConstraintList::iterator it;
|
||||
unsigned int iConstraint;
|
||||
|
||||
// scan through the constraints and call the callback functions
|
||||
for (iConstraint=0, it=m_constraints.begin(); it!=m_constraints.end(); it++, iConstraint++) {
|
||||
JointConstraint_struct* pConstraint = *it;
|
||||
unsigned int nr, i;
|
||||
for (i=0, nr = pConstraint->segment->second.q_nr; i<pConstraint->v_nr; i++, nr++) {
|
||||
*(double *)&pConstraint->value[i].y = m_qKdl[nr];
|
||||
*(double *)&pConstraint->value[i].ydot = m_qdotKdl[nr];
|
||||
}
|
||||
if (pConstraint->function && (pConstraint->substep || (!timestamp.reiterate && !timestamp.substep))) {
|
||||
(*pConstraint->function)(timestamp, pConstraint->values, pConstraint->v_nr, pConstraint->param);
|
||||
}
|
||||
// recompute the weight in any case, that's the most likely modification
|
||||
for (i=0, nr=pConstraint->y_nr; i<pConstraint->v_nr; i++, nr++) {
|
||||
m_Wy(nr) = pConstraint->values[i].alpha/*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
|
||||
m_ydot(nr)=pConstraint->value[i].yddot+pConstraint->values[i].feedback*(pConstraint->value[i].yd-pConstraint->value[i].y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Armature::setControlParameter(unsigned int constraintId,
|
||||
unsigned int valueId,
|
||||
ConstraintAction action,
|
||||
double value,
|
||||
double timestep)
|
||||
bool Armature::setControlParameter(unsigned int constraintId, unsigned int valueId, ConstraintAction action, double value, double timestep)
|
||||
{
|
||||
unsigned int lastid, i;
|
||||
if (constraintId == CONSTRAINT_ID_ALL) {
|
||||
constraintId = 0;
|
||||
lastid = m_nconstraint;
|
||||
}
|
||||
else if (constraintId < m_nconstraint) {
|
||||
lastid = constraintId + 1;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
for (; constraintId < lastid; ++constraintId) {
|
||||
JointConstraint_struct *pConstraint = m_constraints[constraintId];
|
||||
if (valueId == ID_JOINT) {
|
||||
for (i = 0; i < pConstraint->v_nr; i++) {
|
||||
switch (action) {
|
||||
case ACT_TOLERANCE:
|
||||
pConstraint->values[i].tolerance = value;
|
||||
break;
|
||||
case ACT_FEEDBACK:
|
||||
pConstraint->values[i].feedback = value;
|
||||
break;
|
||||
case ACT_ALPHA:
|
||||
pConstraint->values[i].alpha = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < pConstraint->v_nr; i++) {
|
||||
if (valueId == pConstraint->value[i].id) {
|
||||
switch (action) {
|
||||
case ACT_VALUE:
|
||||
pConstraint->value[i].yd = value;
|
||||
break;
|
||||
case ACT_VELOCITY:
|
||||
pConstraint->value[i].yddot = value;
|
||||
break;
|
||||
case ACT_TOLERANCE:
|
||||
pConstraint->values[i].tolerance = value;
|
||||
break;
|
||||
case ACT_FEEDBACK:
|
||||
pConstraint->values[i].feedback = value;
|
||||
break;
|
||||
case ACT_ALPHA:
|
||||
pConstraint->values[i].alpha = value;
|
||||
break;
|
||||
case ACT_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_finalized) {
|
||||
for (i = 0; i < pConstraint->v_nr; i++)
|
||||
m_Wy(pConstraint->y_nr +
|
||||
i) = pConstraint->values[i]
|
||||
.alpha /*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
unsigned int lastid, i;
|
||||
if (constraintId == CONSTRAINT_ID_ALL) {
|
||||
constraintId = 0;
|
||||
lastid = m_nconstraint;
|
||||
} else if (constraintId < m_nconstraint) {
|
||||
lastid = constraintId+1;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
for ( ; constraintId<lastid; ++constraintId) {
|
||||
JointConstraint_struct* pConstraint = m_constraints[constraintId];
|
||||
if (valueId == ID_JOINT) {
|
||||
for (i=0; i<pConstraint->v_nr; i++) {
|
||||
switch (action) {
|
||||
case ACT_TOLERANCE:
|
||||
pConstraint->values[i].tolerance = value;
|
||||
break;
|
||||
case ACT_FEEDBACK:
|
||||
pConstraint->values[i].feedback = value;
|
||||
break;
|
||||
case ACT_ALPHA:
|
||||
pConstraint->values[i].alpha = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i=0; i<pConstraint->v_nr; i++) {
|
||||
if (valueId == pConstraint->value[i].id) {
|
||||
switch (action) {
|
||||
case ACT_VALUE:
|
||||
pConstraint->value[i].yd = value;
|
||||
break;
|
||||
case ACT_VELOCITY:
|
||||
pConstraint->value[i].yddot = value;
|
||||
break;
|
||||
case ACT_TOLERANCE:
|
||||
pConstraint->values[i].tolerance = value;
|
||||
break;
|
||||
case ACT_FEEDBACK:
|
||||
pConstraint->values[i].feedback = value;
|
||||
break;
|
||||
case ACT_ALPHA:
|
||||
pConstraint->values[i].alpha = value;
|
||||
break;
|
||||
case ACT_NONE:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_finalized) {
|
||||
for (i=0; i<pConstraint->v_nr; i++)
|
||||
m_Wy(pConstraint->y_nr+i) = pConstraint->values[i].alpha/*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
|
||||
@@ -9,168 +9,132 @@
|
||||
#ifndef ARMATURE_HPP_
|
||||
#define ARMATURE_HPP_
|
||||
|
||||
#include "ConstraintSet.hpp"
|
||||
#include "ControlledObject.hpp"
|
||||
#include "kdl/treefksolverpos_recursive.hpp"
|
||||
#include "ConstraintSet.hpp"
|
||||
#include "kdl/treejnttojacsolver.hpp"
|
||||
#include "kdl/treefksolverpos_recursive.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
class Armature : public iTaSC::ControlledObject {
|
||||
public:
|
||||
Armature();
|
||||
virtual ~Armature();
|
||||
class Armature: public iTaSC::ControlledObject {
|
||||
public:
|
||||
Armature();
|
||||
virtual ~Armature();
|
||||
|
||||
bool addSegment(const std::string &segment_name,
|
||||
const std::string &hook_name,
|
||||
const Joint &joint,
|
||||
const double &q_rest,
|
||||
const Frame &f_tip = F_identity,
|
||||
const Inertia &M = Inertia::Zero());
|
||||
// general purpose constraint on joint
|
||||
int addConstraint(const std::string &segment_name,
|
||||
ConstraintCallback _function,
|
||||
void *_param = NULL,
|
||||
bool _freeParam = false,
|
||||
bool _substep = false);
|
||||
// specific limit constraint on joint
|
||||
int addLimitConstraint(const std::string &segment_name,
|
||||
unsigned int dof,
|
||||
double _min,
|
||||
double _max);
|
||||
double getMaxJointChange();
|
||||
double getMaxEndEffectorChange();
|
||||
bool getSegment(const std::string &segment_name,
|
||||
const unsigned int q_size,
|
||||
const Joint *&p_joint,
|
||||
double &q_rest,
|
||||
double &q,
|
||||
const Frame *&p_tip);
|
||||
bool getRelativeFrame(Frame &result,
|
||||
const std::string &segment_name,
|
||||
const std::string &base_name = m_root);
|
||||
bool addSegment(const std::string& segment_name, const std::string& hook_name, const Joint& joint, const double& q_rest, const Frame& f_tip=F_identity, const Inertia& M = Inertia::Zero());
|
||||
// general purpose constraint on joint
|
||||
int addConstraint(const std::string& segment_name, ConstraintCallback _function, void* _param=NULL, bool _freeParam=false, bool _substep=false);
|
||||
// specific limit constraint on joint
|
||||
int addLimitConstraint(const std::string& segment_name, unsigned int dof, double _min, double _max);
|
||||
double getMaxJointChange();
|
||||
double getMaxEndEffectorChange();
|
||||
bool getSegment(const std::string& segment_name, const unsigned int q_size, const Joint* &p_joint, double &q_rest, double &q, const Frame* &p_tip);
|
||||
bool getRelativeFrame(Frame& result, const std::string& segment_name, const std::string& base_name=m_root);
|
||||
|
||||
virtual bool finalize();
|
||||
virtual bool finalize();
|
||||
|
||||
virtual int addEndEffector(const std::string &name);
|
||||
virtual const Frame &getPose(const unsigned int end_effector);
|
||||
virtual bool updateJoint(const Timestamp ×tamp, JointLockCallback &callback);
|
||||
virtual void updateKinematics(const Timestamp ×tamp);
|
||||
virtual void pushCache(const Timestamp ×tamp);
|
||||
virtual void updateControlOutput(const Timestamp ×tamp);
|
||||
virtual bool setControlParameter(unsigned int constraintId,
|
||||
unsigned int valueId,
|
||||
ConstraintAction action,
|
||||
double value,
|
||||
double timestep = 0.0);
|
||||
virtual void initCache(Cache *_cache);
|
||||
virtual bool setJointArray(const KDL::JntArray &joints);
|
||||
virtual const KDL::JntArray &getJointArray();
|
||||
virtual int addEndEffector(const std::string& name);
|
||||
virtual const Frame& getPose(const unsigned int end_effector);
|
||||
virtual bool updateJoint(const Timestamp& timestamp, JointLockCallback& callback);
|
||||
virtual void updateKinematics(const Timestamp& timestamp);
|
||||
virtual void pushCache(const Timestamp& timestamp);
|
||||
virtual void updateControlOutput(const Timestamp& timestamp);
|
||||
virtual bool setControlParameter(unsigned int constraintId, unsigned int valueId, ConstraintAction action, double value, double timestep=0.0);
|
||||
virtual void initCache(Cache *_cache);
|
||||
virtual bool setJointArray(const KDL::JntArray& joints);
|
||||
virtual const KDL::JntArray& getJointArray();
|
||||
|
||||
virtual double getArmLength()
|
||||
{
|
||||
return m_armlength;
|
||||
}
|
||||
virtual double getArmLength()
|
||||
{
|
||||
return m_armlength;
|
||||
}
|
||||
|
||||
struct Effector_struct {
|
||||
std::string name;
|
||||
Frame oldpose;
|
||||
Frame pose;
|
||||
Effector_struct(const std::string &_name)
|
||||
{
|
||||
name = _name;
|
||||
oldpose = pose = F_identity;
|
||||
}
|
||||
};
|
||||
typedef std::vector<Effector_struct> EffectorList;
|
||||
struct Effector_struct {
|
||||
std::string name;
|
||||
Frame oldpose;
|
||||
Frame pose;
|
||||
Effector_struct(const std::string& _name) {name = _name; oldpose = pose = F_identity;}
|
||||
};
|
||||
typedef std::vector<Effector_struct> EffectorList;
|
||||
|
||||
enum ID {
|
||||
ID_JOINT = 1,
|
||||
ID_JOINT_RX = 2,
|
||||
ID_JOINT_RY = 3,
|
||||
ID_JOINT_RZ = 4,
|
||||
ID_JOINT_TX = 2,
|
||||
ID_JOINT_TY = 3,
|
||||
ID_JOINT_TZ = 4,
|
||||
};
|
||||
struct JointConstraint_struct {
|
||||
SegmentMap::const_iterator segment;
|
||||
ConstraintSingleValue value[3];
|
||||
ConstraintValues values[3];
|
||||
ConstraintCallback function;
|
||||
unsigned int v_nr;
|
||||
unsigned int y_nr; // first coordinate of constraint in Y vector
|
||||
void *param;
|
||||
bool freeParam;
|
||||
bool substep;
|
||||
JointConstraint_struct(SegmentMap::const_iterator _segment,
|
||||
unsigned int _y_nr,
|
||||
ConstraintCallback _function,
|
||||
void *_param,
|
||||
bool _freeParam,
|
||||
bool _substep);
|
||||
~JointConstraint_struct();
|
||||
};
|
||||
typedef std::vector<JointConstraint_struct *> JointConstraintList;
|
||||
enum ID {
|
||||
ID_JOINT=1,
|
||||
ID_JOINT_RX=2,
|
||||
ID_JOINT_RY=3,
|
||||
ID_JOINT_RZ=4,
|
||||
ID_JOINT_TX=2,
|
||||
ID_JOINT_TY=3,
|
||||
ID_JOINT_TZ=4,
|
||||
};
|
||||
struct JointConstraint_struct {
|
||||
SegmentMap::const_iterator segment;
|
||||
ConstraintSingleValue value[3];
|
||||
ConstraintValues values[3];
|
||||
ConstraintCallback function;
|
||||
unsigned int v_nr;
|
||||
unsigned int y_nr; // first coordinate of constraint in Y vector
|
||||
void* param;
|
||||
bool freeParam;
|
||||
bool substep;
|
||||
JointConstraint_struct(SegmentMap::const_iterator _segment, unsigned int _y_nr, ConstraintCallback _function, void* _param, bool _freeParam, bool _substep);
|
||||
~JointConstraint_struct();
|
||||
};
|
||||
typedef std::vector<JointConstraint_struct*> JointConstraintList;
|
||||
|
||||
struct Joint_struct {
|
||||
KDL::Joint::JointType type;
|
||||
unsigned short ndof;
|
||||
bool useLimit;
|
||||
bool locked;
|
||||
double rest;
|
||||
double min;
|
||||
double max;
|
||||
struct Joint_struct {
|
||||
KDL::Joint::JointType type;
|
||||
unsigned short ndof;
|
||||
bool useLimit;
|
||||
bool locked;
|
||||
double rest;
|
||||
double min;
|
||||
double max;
|
||||
|
||||
Joint_struct(KDL::Joint::JointType _type, unsigned int _ndof, double _rest)
|
||||
: type(_type), ndof(_ndof), rest(_rest)
|
||||
{
|
||||
useLimit = locked = false;
|
||||
min = 0.0;
|
||||
max = 0.0;
|
||||
}
|
||||
};
|
||||
typedef std::vector<Joint_struct> JointList;
|
||||
Joint_struct(KDL::Joint::JointType _type, unsigned int _ndof, double _rest) :
|
||||
type(_type), ndof(_ndof), rest(_rest) { useLimit=locked=false; min=0.0; max=0.0; }
|
||||
};
|
||||
typedef std::vector<Joint_struct> JointList;
|
||||
|
||||
protected:
|
||||
virtual void updateJacobian();
|
||||
|
||||
protected:
|
||||
virtual void updateJacobian();
|
||||
|
||||
private:
|
||||
static std::string m_root;
|
||||
Tree m_tree;
|
||||
unsigned int m_njoint;
|
||||
unsigned int m_nconstraint;
|
||||
unsigned int m_noutput;
|
||||
unsigned int m_neffector;
|
||||
bool m_finalized;
|
||||
Cache *m_cache;
|
||||
double *m_buf;
|
||||
int m_qCCh;
|
||||
CacheTS m_qCTs;
|
||||
int m_yCCh;
|
||||
private:
|
||||
static std::string m_root;
|
||||
Tree m_tree;
|
||||
unsigned int m_njoint;
|
||||
unsigned int m_nconstraint;
|
||||
unsigned int m_noutput;
|
||||
unsigned int m_neffector;
|
||||
bool m_finalized;
|
||||
Cache* m_cache;
|
||||
double *m_buf;
|
||||
int m_qCCh;
|
||||
CacheTS m_qCTs;
|
||||
int m_yCCh;
|
||||
#if 0
|
||||
CacheTS m_yCTs;
|
||||
#endif
|
||||
JntArray m_qKdl;
|
||||
JntArray m_oldqKdl;
|
||||
JntArray m_newqKdl;
|
||||
JntArray m_qdotKdl;
|
||||
Jacobian *m_jac;
|
||||
double m_armlength;
|
||||
JntArray m_qKdl;
|
||||
JntArray m_oldqKdl;
|
||||
JntArray m_newqKdl;
|
||||
JntArray m_qdotKdl;
|
||||
Jacobian* m_jac;
|
||||
double m_armlength;
|
||||
|
||||
KDL::TreeJntToJacSolver *m_jacsolver;
|
||||
KDL::TreeFkSolverPos_recursive *m_fksolver;
|
||||
EffectorList m_effectors;
|
||||
JointConstraintList m_constraints;
|
||||
JointList m_joints;
|
||||
KDL::TreeJntToJacSolver* m_jacsolver;
|
||||
KDL::TreeFkSolverPos_recursive* m_fksolver;
|
||||
EffectorList m_effectors;
|
||||
JointConstraintList m_constraints;
|
||||
JointList m_joints;
|
||||
|
||||
void pushQ(CacheTS timestamp);
|
||||
bool popQ(CacheTS timestamp);
|
||||
//void pushConstraints(CacheTS timestamp);
|
||||
//bool popConstraints(CacheTS timestamp);
|
||||
|
||||
void pushQ(CacheTS timestamp);
|
||||
bool popQ(CacheTS timestamp);
|
||||
// void pushConstraints(CacheTS timestamp);
|
||||
// bool popConstraints(CacheTS timestamp);
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* ARMATURE_HPP_ */
|
||||
|
||||
@@ -6,647 +6,619 @@
|
||||
* \ingroup intern_itasc
|
||||
*/
|
||||
|
||||
#include "Cache.hpp"
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "Cache.hpp"
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
CacheEntry::~CacheEntry()
|
||||
{
|
||||
for (unsigned int id = 0; id < m_count; id++)
|
||||
m_channelArray[id].clear();
|
||||
if (m_channelArray)
|
||||
free(m_channelArray);
|
||||
for (unsigned int id=0; id < m_count; id++)
|
||||
m_channelArray[id].clear();
|
||||
if (m_channelArray)
|
||||
free(m_channelArray);
|
||||
}
|
||||
|
||||
CacheItem *CacheChannel::_findBlock(CacheBuffer *buffer,
|
||||
unsigned short timeOffset,
|
||||
unsigned int *retBlock)
|
||||
CacheItem *CacheChannel::_findBlock(CacheBuffer *buffer, unsigned short timeOffset, unsigned int *retBlock)
|
||||
{
|
||||
// the timestamp is necessarily in this buffer
|
||||
unsigned int lowBlock, highBlock, midBlock;
|
||||
if (timeOffset <= buffer->lookup[0].m_timeOffset) {
|
||||
// special case: the item is in the first block, search from start
|
||||
*retBlock = 0;
|
||||
return &buffer->m_firstItem;
|
||||
}
|
||||
// general case, the item is in the middle of the buffer
|
||||
// before doing a dycotomic search, we will assume that timestamp
|
||||
// are regularly spaced so that we can try to locate the block directly
|
||||
highBlock = buffer->m_lastItemPositionW >> m_positionToBlockShiftW;
|
||||
lowBlock = midBlock = (timeOffset * highBlock) /
|
||||
(buffer->m_lastTimestamp - buffer->m_firstTimestamp);
|
||||
// give some space for security
|
||||
if (lowBlock > 0)
|
||||
lowBlock--;
|
||||
if (timeOffset <= buffer->lookup[lowBlock].m_timeOffset) {
|
||||
// bad guess, but we know this block is a good high block, just use it
|
||||
highBlock = lowBlock;
|
||||
lowBlock = 0;
|
||||
}
|
||||
else {
|
||||
// ok, good guess, now check the high block, give some space
|
||||
if (midBlock < highBlock)
|
||||
midBlock++;
|
||||
if (timeOffset <= buffer->lookup[midBlock].m_timeOffset) {
|
||||
// good guess, keep that block as the high block
|
||||
highBlock = midBlock;
|
||||
}
|
||||
}
|
||||
// the item is in a different block, do a dycotomic search
|
||||
// the timestamp is alway > lowBlock and <= highBlock
|
||||
while (1) {
|
||||
midBlock = (lowBlock + highBlock) / 2;
|
||||
if (midBlock == lowBlock) {
|
||||
// low block and high block are contigous, we can start search from the low block
|
||||
break;
|
||||
}
|
||||
else if (timeOffset <= buffer->lookup[midBlock].m_timeOffset) {
|
||||
highBlock = midBlock;
|
||||
}
|
||||
else {
|
||||
lowBlock = midBlock;
|
||||
}
|
||||
}
|
||||
assert(lowBlock != highBlock);
|
||||
*retBlock = highBlock;
|
||||
return CACHE_BLOCK_ITEM_ADDR(this, buffer, lowBlock);
|
||||
// the timestamp is necessarily in this buffer
|
||||
unsigned int lowBlock, highBlock, midBlock;
|
||||
if (timeOffset <= buffer->lookup[0].m_timeOffset) {
|
||||
// special case: the item is in the first block, search from start
|
||||
*retBlock = 0;
|
||||
return &buffer->m_firstItem;
|
||||
}
|
||||
// general case, the item is in the middle of the buffer
|
||||
// before doing a dycotomic search, we will assume that timestamp
|
||||
// are regularly spaced so that we can try to locate the block directly
|
||||
highBlock = buffer->m_lastItemPositionW>>m_positionToBlockShiftW;
|
||||
lowBlock = midBlock = (timeOffset*highBlock)/(buffer->m_lastTimestamp-buffer->m_firstTimestamp);
|
||||
// give some space for security
|
||||
if (lowBlock > 0)
|
||||
lowBlock--;
|
||||
if (timeOffset <= buffer->lookup[lowBlock].m_timeOffset) {
|
||||
// bad guess, but we know this block is a good high block, just use it
|
||||
highBlock = lowBlock;
|
||||
lowBlock = 0;
|
||||
} else {
|
||||
// ok, good guess, now check the high block, give some space
|
||||
if (midBlock < highBlock)
|
||||
midBlock++;
|
||||
if (timeOffset <= buffer->lookup[midBlock].m_timeOffset) {
|
||||
// good guess, keep that block as the high block
|
||||
highBlock = midBlock;
|
||||
}
|
||||
}
|
||||
// the item is in a different block, do a dycotomic search
|
||||
// the timestamp is alway > lowBlock and <= highBlock
|
||||
while (1) {
|
||||
midBlock = (lowBlock+highBlock)/2;
|
||||
if (midBlock == lowBlock) {
|
||||
// low block and high block are contigous, we can start search from the low block
|
||||
break;
|
||||
} else if (timeOffset <= buffer->lookup[midBlock].m_timeOffset) {
|
||||
highBlock = midBlock;
|
||||
} else {
|
||||
lowBlock = midBlock;
|
||||
}
|
||||
}
|
||||
assert (lowBlock != highBlock);
|
||||
*retBlock = highBlock;
|
||||
return CACHE_BLOCK_ITEM_ADDR(this,buffer,lowBlock);
|
||||
}
|
||||
|
||||
void CacheChannel::clear()
|
||||
{
|
||||
CacheBuffer *buffer, *next;
|
||||
for (buffer = m_firstBuffer; buffer != 0; buffer = next) {
|
||||
next = buffer->m_next;
|
||||
free(buffer);
|
||||
}
|
||||
m_firstBuffer = NULL;
|
||||
m_lastBuffer = NULL;
|
||||
if (initItem) {
|
||||
free(initItem);
|
||||
initItem = NULL;
|
||||
}
|
||||
CacheBuffer *buffer, *next;
|
||||
for (buffer=m_firstBuffer; buffer != 0; buffer = next) {
|
||||
next = buffer->m_next;
|
||||
free(buffer);
|
||||
}
|
||||
m_firstBuffer = NULL;
|
||||
m_lastBuffer = NULL;
|
||||
if (initItem) {
|
||||
free(initItem);
|
||||
initItem = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CacheBuffer *CacheChannel::allocBuffer()
|
||||
CacheBuffer* CacheChannel::allocBuffer()
|
||||
{
|
||||
CacheBuffer *buffer;
|
||||
if (!m_busy)
|
||||
return NULL;
|
||||
buffer = (CacheBuffer *)malloc(CACHE_BUFFER_HEADER_SIZE + (m_bufferSizeW << 2));
|
||||
if (buffer) {
|
||||
memset(buffer, 0, CACHE_BUFFER_HEADER_SIZE);
|
||||
}
|
||||
return buffer;
|
||||
CacheBuffer* buffer;
|
||||
if (!m_busy)
|
||||
return NULL;
|
||||
buffer = (CacheBuffer*)malloc(CACHE_BUFFER_HEADER_SIZE+(m_bufferSizeW<<2));
|
||||
if (buffer) {
|
||||
memset(buffer, 0, CACHE_BUFFER_HEADER_SIZE);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
CacheItem *CacheChannel::findItemOrLater(unsigned int timestamp, CacheBuffer **rBuffer)
|
||||
CacheItem* CacheChannel::findItemOrLater(unsigned int timestamp, CacheBuffer **rBuffer)
|
||||
{
|
||||
CacheBuffer *buffer;
|
||||
CacheItem *item, *limit;
|
||||
if (!m_busy)
|
||||
return NULL;
|
||||
if (timestamp == 0 && initItem) {
|
||||
*rBuffer = NULL;
|
||||
return initItem;
|
||||
}
|
||||
for (buffer = m_firstBuffer; buffer; buffer = buffer->m_next) {
|
||||
if (buffer->m_firstFreePositionW == 0)
|
||||
// buffer is empty, this must be the last and we didn't find the timestamp
|
||||
return NULL;
|
||||
if (timestamp < buffer->m_firstTimestamp) {
|
||||
*rBuffer = buffer;
|
||||
return &buffer->m_firstItem;
|
||||
}
|
||||
if (timestamp <= buffer->m_lastTimestamp) {
|
||||
// the timestamp is necessarily in this buffer
|
||||
unsigned short timeOffset = (unsigned short)(timestamp - buffer->m_firstTimestamp);
|
||||
unsigned int highBlock;
|
||||
item = _findBlock(buffer, timeOffset, &highBlock);
|
||||
// now we do a linear search until we find a timestamp that is equal or higher
|
||||
// we should normally always find an item but let's put a limit just in case
|
||||
limit = CACHE_BLOCK_ITEM_ADDR(this, buffer, highBlock);
|
||||
while (item <= limit && item->m_timeOffset < timeOffset)
|
||||
item = CACHE_NEXT_ITEM(item);
|
||||
assert(item <= limit);
|
||||
*rBuffer = buffer;
|
||||
return item;
|
||||
}
|
||||
// search in next buffer
|
||||
}
|
||||
return NULL;
|
||||
CacheBuffer* buffer;
|
||||
CacheItem *item, *limit;
|
||||
if (!m_busy)
|
||||
return NULL;
|
||||
if (timestamp == 0 && initItem) {
|
||||
*rBuffer = NULL;
|
||||
return initItem;
|
||||
}
|
||||
for (buffer=m_firstBuffer; buffer; buffer = buffer->m_next) {
|
||||
if (buffer->m_firstFreePositionW == 0)
|
||||
// buffer is empty, this must be the last and we didn't find the timestamp
|
||||
return NULL;
|
||||
if (timestamp < buffer->m_firstTimestamp) {
|
||||
*rBuffer = buffer;
|
||||
return &buffer->m_firstItem;
|
||||
}
|
||||
if (timestamp <= buffer->m_lastTimestamp) {
|
||||
// the timestamp is necessarily in this buffer
|
||||
unsigned short timeOffset = (unsigned short)(timestamp-buffer->m_firstTimestamp);
|
||||
unsigned int highBlock;
|
||||
item = _findBlock(buffer, timeOffset, &highBlock);
|
||||
// now we do a linear search until we find a timestamp that is equal or higher
|
||||
// we should normally always find an item but let's put a limit just in case
|
||||
limit = CACHE_BLOCK_ITEM_ADDR(this,buffer,highBlock);
|
||||
while (item<=limit && item->m_timeOffset < timeOffset )
|
||||
item = CACHE_NEXT_ITEM(item);
|
||||
assert(item<=limit);
|
||||
*rBuffer = buffer;
|
||||
return item;
|
||||
}
|
||||
// search in next buffer
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CacheItem *CacheChannel::findItemEarlier(unsigned int timestamp, CacheBuffer **rBuffer)
|
||||
CacheItem* CacheChannel::findItemEarlier(unsigned int timestamp, CacheBuffer **rBuffer)
|
||||
{
|
||||
CacheBuffer *buffer, *prevBuffer;
|
||||
CacheItem *item, *limit, *prevItem;
|
||||
if (!m_busy)
|
||||
return NULL;
|
||||
if (timestamp == 0)
|
||||
return NULL;
|
||||
for (prevBuffer = NULL, buffer = m_firstBuffer; buffer;
|
||||
prevBuffer = buffer, buffer = buffer->m_next)
|
||||
{
|
||||
if (buffer->m_firstFreePositionW == 0)
|
||||
// buffer is empty, this must be the last and we didn't find the timestamp
|
||||
return NULL;
|
||||
if (timestamp <= buffer->m_firstTimestamp) {
|
||||
if (prevBuffer == NULL) {
|
||||
// no item before, except the initial item
|
||||
*rBuffer = NULL;
|
||||
return initItem;
|
||||
}
|
||||
// the item is necessarily the last one of previous buffer
|
||||
*rBuffer = prevBuffer;
|
||||
return CACHE_ITEM_ADDR(prevBuffer, prevBuffer->m_lastItemPositionW);
|
||||
}
|
||||
if (timestamp <= buffer->m_lastTimestamp) {
|
||||
// the timestamp is necessarily in this buffer
|
||||
unsigned short timeOffset = (unsigned short)(timestamp - buffer->m_firstTimestamp);
|
||||
unsigned int highBlock;
|
||||
item = _findBlock(buffer, timeOffset, &highBlock);
|
||||
// now we do a linear search until we find a timestamp that is equal or higher
|
||||
// we should normally always find an item but let's put a limit just in case
|
||||
limit = CACHE_BLOCK_ITEM_ADDR(this, buffer, highBlock);
|
||||
prevItem = NULL;
|
||||
while (item <= limit && item->m_timeOffset < timeOffset) {
|
||||
prevItem = item;
|
||||
item = CACHE_NEXT_ITEM(item);
|
||||
}
|
||||
assert(item <= limit && prevItem != NULL);
|
||||
*rBuffer = buffer;
|
||||
return prevItem;
|
||||
}
|
||||
// search in next buffer
|
||||
}
|
||||
// pass all buffer, the last item is the last item of the last buffer
|
||||
if (prevBuffer == NULL) {
|
||||
// no item before, except the initial item
|
||||
*rBuffer = NULL;
|
||||
return initItem;
|
||||
}
|
||||
// the item is necessarily the last one of previous buffer
|
||||
*rBuffer = prevBuffer;
|
||||
return CACHE_ITEM_ADDR(prevBuffer, prevBuffer->m_lastItemPositionW);
|
||||
CacheBuffer *buffer, *prevBuffer;
|
||||
CacheItem *item, *limit, *prevItem;
|
||||
if (!m_busy)
|
||||
return NULL;
|
||||
if (timestamp == 0)
|
||||
return NULL;
|
||||
for (prevBuffer=NULL, buffer=m_firstBuffer; buffer; prevBuffer = buffer, buffer = buffer->m_next) {
|
||||
if (buffer->m_firstFreePositionW == 0)
|
||||
// buffer is empty, this must be the last and we didn't find the timestamp
|
||||
return NULL;
|
||||
if (timestamp <= buffer->m_firstTimestamp) {
|
||||
if (prevBuffer == NULL) {
|
||||
// no item before, except the initial item
|
||||
*rBuffer = NULL;
|
||||
return initItem;
|
||||
}
|
||||
// the item is necessarily the last one of previous buffer
|
||||
*rBuffer = prevBuffer;
|
||||
return CACHE_ITEM_ADDR(prevBuffer,prevBuffer->m_lastItemPositionW);
|
||||
}
|
||||
if (timestamp <= buffer->m_lastTimestamp) {
|
||||
// the timestamp is necessarily in this buffer
|
||||
unsigned short timeOffset = (unsigned short)(timestamp-buffer->m_firstTimestamp);
|
||||
unsigned int highBlock;
|
||||
item = _findBlock(buffer, timeOffset, &highBlock);
|
||||
// now we do a linear search until we find a timestamp that is equal or higher
|
||||
// we should normally always find an item but let's put a limit just in case
|
||||
limit = CACHE_BLOCK_ITEM_ADDR(this,buffer,highBlock);
|
||||
prevItem = NULL;
|
||||
while (item<=limit && item->m_timeOffset < timeOffset) {
|
||||
prevItem = item;
|
||||
item = CACHE_NEXT_ITEM(item);
|
||||
}
|
||||
assert(item<=limit && prevItem!=NULL);
|
||||
*rBuffer = buffer;
|
||||
return prevItem;
|
||||
}
|
||||
// search in next buffer
|
||||
}
|
||||
// pass all buffer, the last item is the last item of the last buffer
|
||||
if (prevBuffer == NULL) {
|
||||
// no item before, except the initial item
|
||||
*rBuffer = NULL;
|
||||
return initItem;
|
||||
}
|
||||
// the item is necessarily the last one of previous buffer
|
||||
*rBuffer = prevBuffer;
|
||||
return CACHE_ITEM_ADDR(prevBuffer,prevBuffer->m_lastItemPositionW);
|
||||
}
|
||||
|
||||
Cache::Cache() {}
|
||||
|
||||
Cache::Cache()
|
||||
{
|
||||
}
|
||||
|
||||
Cache::~Cache()
|
||||
{
|
||||
CacheMap::iterator it;
|
||||
for (it = m_cache.begin(); it != m_cache.end(); it = m_cache.begin()) {
|
||||
deleteDevice(it->first);
|
||||
}
|
||||
CacheMap::iterator it;
|
||||
for (it=m_cache.begin(); it!=m_cache.end(); it=m_cache.begin()) {
|
||||
deleteDevice(it->first);
|
||||
}
|
||||
}
|
||||
|
||||
int Cache::addChannel(const void *device, const char *name, unsigned int maxItemSize)
|
||||
{
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
unsigned int id;
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
unsigned int id;
|
||||
|
||||
if (maxItemSize > 0x3FFF0)
|
||||
return -1;
|
||||
if (maxItemSize > 0x3FFF0)
|
||||
return -1;
|
||||
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist yet, create a new entry
|
||||
entry = new CacheEntry();
|
||||
if (entry == NULL)
|
||||
return -1;
|
||||
if (!m_cache.insert(CacheMap::value_type(device, entry)).second) {
|
||||
delete entry;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
entry = it->second;
|
||||
}
|
||||
// locate a channel with the same name and reuse
|
||||
for (channel = entry->m_channelArray, id = 0; id < entry->m_count; id++, channel++) {
|
||||
if (channel->m_busy && !strcmp(name, channel->m_name)) {
|
||||
// make this channel free again
|
||||
deleteChannel(device, id);
|
||||
// there can only be one channel with the same name
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (channel = entry->m_channelArray, id = 0; id < entry->m_count; id++, channel++) {
|
||||
// locate a free channel
|
||||
if (!channel->m_busy)
|
||||
break;
|
||||
}
|
||||
if (id == entry->m_count) {
|
||||
// no channel free, create new channels
|
||||
int newcount = entry->m_count + CACHE_CHANNEL_EXTEND_SIZE;
|
||||
channel = (CacheChannel *)realloc(entry->m_channelArray, newcount * sizeof(CacheChannel));
|
||||
if (channel == NULL)
|
||||
return -1;
|
||||
entry->m_channelArray = channel;
|
||||
memset(&entry->m_channelArray[entry->m_count],
|
||||
0,
|
||||
CACHE_CHANNEL_EXTEND_SIZE * sizeof(CacheChannel));
|
||||
entry->m_count = newcount;
|
||||
channel = &entry->m_channelArray[id];
|
||||
}
|
||||
// compute the optimal buffer size
|
||||
// The buffer size must be selected so that
|
||||
// - it does not contain more than 1630 items (=1s of cache assuming 25 items per second)
|
||||
// - it contains at least one item
|
||||
// - it's not bigger than 256kb and preferably around 32kb
|
||||
// - it a multiple of 4
|
||||
unsigned int bufSize = 1630 * (maxItemSize + 4);
|
||||
if (bufSize >= CACHE_DEFAULT_BUFFER_SIZE)
|
||||
bufSize = CACHE_DEFAULT_BUFFER_SIZE;
|
||||
if (bufSize < maxItemSize + 16)
|
||||
bufSize = maxItemSize + 16;
|
||||
bufSize = (bufSize + 3) & ~0x3;
|
||||
// compute block size and offset bit mask
|
||||
// the block size is computed so that
|
||||
// - it is a power of 2
|
||||
// - there is at least one item per block
|
||||
// - there is no more than CACHE_LOOKUP_TABLE_SIZE blocks per buffer
|
||||
unsigned int blockSize = bufSize / CACHE_LOOKUP_TABLE_SIZE;
|
||||
if (blockSize < maxItemSize + 12)
|
||||
blockSize = maxItemSize + 12;
|
||||
// find the power of 2 that is immediately larger than blockSize
|
||||
unsigned int m;
|
||||
unsigned int pwr2Size = blockSize;
|
||||
while ((m = (pwr2Size & (pwr2Size - 1))) != 0)
|
||||
pwr2Size = m;
|
||||
blockSize = (pwr2Size < blockSize) ? pwr2Size << 1 : pwr2Size;
|
||||
// convert byte size to word size because all positions and size are expressed in 32 bit words
|
||||
blockSize >>= 2;
|
||||
channel->m_blockSizeW = blockSize;
|
||||
channel->m_bufferSizeW = bufSize >> 2;
|
||||
channel->m_firstBuffer = NULL;
|
||||
channel->m_lastBuffer = NULL;
|
||||
channel->m_busy = 1;
|
||||
channel->initItem = NULL;
|
||||
channel->m_maxItemSizeB = maxItemSize;
|
||||
strncpy(channel->m_name, name, sizeof(channel->m_name));
|
||||
channel->m_name[sizeof(channel->m_name) - 1] = 0;
|
||||
channel->m_positionToOffsetMaskW = (blockSize - 1);
|
||||
for (m = 0; blockSize != 1; m++, blockSize >>= 1)
|
||||
;
|
||||
channel->m_positionToBlockShiftW = m;
|
||||
return (int)id;
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist yet, create a new entry
|
||||
entry = new CacheEntry();
|
||||
if (entry == NULL)
|
||||
return -1;
|
||||
if (!m_cache.insert(CacheMap::value_type(device,entry)).second) {
|
||||
delete entry;
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
entry = it->second;
|
||||
}
|
||||
// locate a channel with the same name and reuse
|
||||
for (channel=entry->m_channelArray, id=0; id<entry->m_count; id++, channel++) {
|
||||
if (channel->m_busy && !strcmp(name, channel->m_name)) {
|
||||
// make this channel free again
|
||||
deleteChannel(device, id);
|
||||
// there can only be one channel with the same name
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (channel=entry->m_channelArray, id=0; id<entry->m_count; id++, channel++) {
|
||||
// locate a free channel
|
||||
if (!channel->m_busy)
|
||||
break;
|
||||
}
|
||||
if (id == entry->m_count) {
|
||||
// no channel free, create new channels
|
||||
int newcount = entry->m_count + CACHE_CHANNEL_EXTEND_SIZE;
|
||||
channel = (CacheChannel*)realloc(entry->m_channelArray, newcount*sizeof(CacheChannel));
|
||||
if (channel == NULL)
|
||||
return -1;
|
||||
entry->m_channelArray = channel;
|
||||
memset(&entry->m_channelArray[entry->m_count], 0, CACHE_CHANNEL_EXTEND_SIZE*sizeof(CacheChannel));
|
||||
entry->m_count = newcount;
|
||||
channel = &entry->m_channelArray[id];
|
||||
}
|
||||
// compute the optimal buffer size
|
||||
// The buffer size must be selected so that
|
||||
// - it does not contain more than 1630 items (=1s of cache assuming 25 items per second)
|
||||
// - it contains at least one item
|
||||
// - it's not bigger than 256kb and preferably around 32kb
|
||||
// - it a multiple of 4
|
||||
unsigned int bufSize = 1630*(maxItemSize+4);
|
||||
if (bufSize >= CACHE_DEFAULT_BUFFER_SIZE)
|
||||
bufSize = CACHE_DEFAULT_BUFFER_SIZE;
|
||||
if (bufSize < maxItemSize+16)
|
||||
bufSize = maxItemSize+16;
|
||||
bufSize = (bufSize + 3) & ~0x3;
|
||||
// compute block size and offset bit mask
|
||||
// the block size is computed so that
|
||||
// - it is a power of 2
|
||||
// - there is at least one item per block
|
||||
// - there is no more than CACHE_LOOKUP_TABLE_SIZE blocks per buffer
|
||||
unsigned int blockSize = bufSize/CACHE_LOOKUP_TABLE_SIZE;
|
||||
if (blockSize < maxItemSize+12)
|
||||
blockSize = maxItemSize+12;
|
||||
// find the power of 2 that is immediately larger than blockSize
|
||||
unsigned int m;
|
||||
unsigned int pwr2Size = blockSize;
|
||||
while ((m = (pwr2Size & (pwr2Size-1))) != 0)
|
||||
pwr2Size = m;
|
||||
blockSize = (pwr2Size < blockSize) ? pwr2Size<<1 : pwr2Size;
|
||||
// convert byte size to word size because all positions and size are expressed in 32 bit words
|
||||
blockSize >>= 2;
|
||||
channel->m_blockSizeW = blockSize;
|
||||
channel->m_bufferSizeW = bufSize>>2;
|
||||
channel->m_firstBuffer = NULL;
|
||||
channel->m_lastBuffer = NULL;
|
||||
channel->m_busy = 1;
|
||||
channel->initItem = NULL;
|
||||
channel->m_maxItemSizeB = maxItemSize;
|
||||
strncpy(channel->m_name, name, sizeof(channel->m_name));
|
||||
channel->m_name[sizeof(channel->m_name)-1] = 0;
|
||||
channel->m_positionToOffsetMaskW = (blockSize-1);
|
||||
for (m=0; blockSize!=1; m++, blockSize>>=1);
|
||||
channel->m_positionToBlockShiftW = m;
|
||||
return (int)id;
|
||||
}
|
||||
|
||||
int Cache::deleteChannel(const void *device, int id)
|
||||
{
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return -1;
|
||||
}
|
||||
entry = it->second;
|
||||
if (id < 0 || id >= (int)entry->m_count || !entry->m_channelArray[id].m_busy)
|
||||
return -1;
|
||||
entry->m_channelArray[id].clear();
|
||||
entry->m_channelArray[id].m_busy = 0;
|
||||
return 0;
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return -1;
|
||||
}
|
||||
entry = it->second;
|
||||
if (id < 0 || id >= (int)entry->m_count || !entry->m_channelArray[id].m_busy)
|
||||
return -1;
|
||||
entry->m_channelArray[id].clear();
|
||||
entry->m_channelArray[id].m_busy = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Cache::deleteDevice(const void *device)
|
||||
{
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return -1;
|
||||
}
|
||||
entry = it->second;
|
||||
delete entry;
|
||||
m_cache.erase(it);
|
||||
return 0;
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return -1;
|
||||
}
|
||||
entry = it->second;
|
||||
delete entry;
|
||||
m_cache.erase(it);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Cache::clearCacheFrom(const void *device, CacheTS timestamp)
|
||||
{
|
||||
CacheMap::iterator it = (device) ? m_cache.find(device) : m_cache.begin();
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
CacheBuffer *buffer, *nextBuffer, *prevBuffer;
|
||||
CacheItem *item, *prevItem, *nextItem;
|
||||
unsigned int positionW, block;
|
||||
CacheMap::iterator it = (device) ? m_cache.find(device) : m_cache.begin();
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
CacheBuffer *buffer, *nextBuffer, *prevBuffer;
|
||||
CacheItem *item, *prevItem, *nextItem;
|
||||
unsigned int positionW, block;
|
||||
|
||||
while (it != m_cache.end()) {
|
||||
entry = it->second;
|
||||
for (unsigned int ch = 0; ch < entry->m_count; ch++) {
|
||||
channel = &entry->m_channelArray[ch];
|
||||
if (channel->m_busy) {
|
||||
item = channel->findItemOrLater(timestamp, &buffer);
|
||||
if (item) {
|
||||
if (!buffer) {
|
||||
// this is possible if we return the special timestamp=0 item, delete all buffers
|
||||
channel->clear();
|
||||
}
|
||||
else {
|
||||
// this item and all later items will be removed, clear any later buffer
|
||||
while ((nextBuffer = buffer->m_next) != NULL) {
|
||||
buffer->m_next = nextBuffer->m_next;
|
||||
free(nextBuffer);
|
||||
}
|
||||
positionW = CACHE_ITEM_POSITIONW(buffer, item);
|
||||
if (positionW == 0) {
|
||||
// this item is the first one of the buffer, remove the buffer completely
|
||||
// first find the buffer just before it
|
||||
nextBuffer = channel->m_firstBuffer;
|
||||
prevBuffer = NULL;
|
||||
while (nextBuffer != buffer) {
|
||||
prevBuffer = nextBuffer;
|
||||
nextBuffer = nextBuffer->m_next;
|
||||
// we must quit this loop before reaching the end of the list
|
||||
assert(nextBuffer);
|
||||
}
|
||||
free(buffer);
|
||||
buffer = prevBuffer;
|
||||
if (buffer == NULL)
|
||||
// this was also the first buffer
|
||||
channel->m_firstBuffer = NULL;
|
||||
}
|
||||
else {
|
||||
// removing this item means finding the previous item to make it the last one
|
||||
block = positionW >> channel->m_positionToBlockShiftW;
|
||||
if (block == 0) {
|
||||
// start from first item, we know it is not our item because positionW > 0
|
||||
prevItem = &buffer->m_firstItem;
|
||||
}
|
||||
else {
|
||||
// no need to check the current block, it will point to our item or a later one
|
||||
// but the previous block will be a good start for sure.
|
||||
block--;
|
||||
prevItem = CACHE_BLOCK_ITEM_ADDR(channel, buffer, block);
|
||||
}
|
||||
while ((nextItem = CACHE_NEXT_ITEM(prevItem)) < item)
|
||||
prevItem = nextItem;
|
||||
// we must have found our item
|
||||
assert(nextItem == item);
|
||||
// now set the buffer
|
||||
buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer, prevItem);
|
||||
buffer->m_firstFreePositionW = positionW;
|
||||
buffer->m_lastTimestamp = buffer->m_firstTimestamp + prevItem->m_timeOffset;
|
||||
block = buffer->m_lastItemPositionW >> channel->m_positionToBlockShiftW;
|
||||
buffer->lookup[block].m_offsetW = buffer->m_lastItemPositionW &
|
||||
channel->m_positionToOffsetMaskW;
|
||||
buffer->lookup[block].m_timeOffset = prevItem->m_timeOffset;
|
||||
}
|
||||
// set the channel
|
||||
channel->m_lastBuffer = buffer;
|
||||
if (buffer) {
|
||||
channel->m_lastTimestamp = buffer->m_lastTimestamp;
|
||||
channel->m_lastItemPositionW = buffer->m_lastItemPositionW;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (device)
|
||||
break;
|
||||
++it;
|
||||
}
|
||||
while (it != m_cache.end()) {
|
||||
entry = it->second;
|
||||
for (unsigned int ch=0; ch<entry->m_count; ch++) {
|
||||
channel = &entry->m_channelArray[ch];
|
||||
if (channel->m_busy) {
|
||||
item = channel->findItemOrLater(timestamp, &buffer);
|
||||
if (item ) {
|
||||
if (!buffer) {
|
||||
// this is possible if we return the special timestamp=0 item, delete all buffers
|
||||
channel->clear();
|
||||
} else {
|
||||
// this item and all later items will be removed, clear any later buffer
|
||||
while ((nextBuffer = buffer->m_next) != NULL) {
|
||||
buffer->m_next = nextBuffer->m_next;
|
||||
free(nextBuffer);
|
||||
}
|
||||
positionW = CACHE_ITEM_POSITIONW(buffer,item);
|
||||
if (positionW == 0) {
|
||||
// this item is the first one of the buffer, remove the buffer completely
|
||||
// first find the buffer just before it
|
||||
nextBuffer = channel->m_firstBuffer;
|
||||
prevBuffer = NULL;
|
||||
while (nextBuffer != buffer) {
|
||||
prevBuffer = nextBuffer;
|
||||
nextBuffer = nextBuffer->m_next;
|
||||
// we must quit this loop before reaching the end of the list
|
||||
assert(nextBuffer);
|
||||
}
|
||||
free(buffer);
|
||||
buffer = prevBuffer;
|
||||
if (buffer == NULL)
|
||||
// this was also the first buffer
|
||||
channel->m_firstBuffer = NULL;
|
||||
} else {
|
||||
// removing this item means finding the previous item to make it the last one
|
||||
block = positionW>>channel->m_positionToBlockShiftW;
|
||||
if (block == 0) {
|
||||
// start from first item, we know it is not our item because positionW > 0
|
||||
prevItem = &buffer->m_firstItem;
|
||||
} else {
|
||||
// no need to check the current block, it will point to our item or a later one
|
||||
// but the previous block will be a good start for sure.
|
||||
block--;
|
||||
prevItem = CACHE_BLOCK_ITEM_ADDR(channel,buffer,block);
|
||||
}
|
||||
while ((nextItem = CACHE_NEXT_ITEM(prevItem)) < item)
|
||||
prevItem = nextItem;
|
||||
// we must have found our item
|
||||
assert(nextItem==item);
|
||||
// now set the buffer
|
||||
buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer,prevItem);
|
||||
buffer->m_firstFreePositionW = positionW;
|
||||
buffer->m_lastTimestamp = buffer->m_firstTimestamp + prevItem->m_timeOffset;
|
||||
block = buffer->m_lastItemPositionW>>channel->m_positionToBlockShiftW;
|
||||
buffer->lookup[block].m_offsetW = buffer->m_lastItemPositionW&channel->m_positionToOffsetMaskW;
|
||||
buffer->lookup[block].m_timeOffset = prevItem->m_timeOffset;
|
||||
}
|
||||
// set the channel
|
||||
channel->m_lastBuffer = buffer;
|
||||
if (buffer) {
|
||||
channel->m_lastTimestamp = buffer->m_lastTimestamp;
|
||||
channel->m_lastItemPositionW = buffer->m_lastItemPositionW;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (device)
|
||||
break;
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void *Cache::addCacheItem(
|
||||
const void *device, int id, unsigned int timestamp, void *data, unsigned int length)
|
||||
void *Cache::addCacheItem(const void *device, int id, unsigned int timestamp, void *data, unsigned int length)
|
||||
{
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
CacheBuffer *buffer, *next;
|
||||
CacheItem *item;
|
||||
unsigned int positionW, sizeW, block;
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
CacheBuffer *buffer, *next;
|
||||
CacheItem *item;
|
||||
unsigned int positionW, sizeW, block;
|
||||
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return NULL;
|
||||
}
|
||||
entry = it->second;
|
||||
if (id < 0 || id >= (int)entry->m_count || !entry->m_channelArray[id].m_busy)
|
||||
return NULL;
|
||||
channel = &entry->m_channelArray[id];
|
||||
if (length > channel->m_maxItemSizeB)
|
||||
return NULL;
|
||||
if (timestamp == 0) {
|
||||
// initial item, delete all buffers
|
||||
channel->clear();
|
||||
// and create initial item
|
||||
item = NULL;
|
||||
// we will allocate the memory, which is always pointer aligned => compute size
|
||||
// with NULL will give same result.
|
||||
sizeW = CACHE_ITEM_SIZEW(item, length);
|
||||
item = (CacheItem *)calloc(sizeW, 4);
|
||||
item->m_sizeW = sizeW;
|
||||
channel->initItem = item;
|
||||
}
|
||||
else {
|
||||
if (!channel->m_lastBuffer) {
|
||||
// no item in buffer, insert item at first position of first buffer
|
||||
positionW = 0;
|
||||
if ((buffer = channel->m_firstBuffer) == NULL) {
|
||||
buffer = channel->allocBuffer();
|
||||
channel->m_firstBuffer = buffer;
|
||||
}
|
||||
}
|
||||
else if (timestamp > channel->m_lastTimestamp) {
|
||||
// this is the normal case: we are writing past lastest timestamp
|
||||
buffer = channel->m_lastBuffer;
|
||||
positionW = buffer->m_firstFreePositionW;
|
||||
}
|
||||
else if (timestamp == channel->m_lastTimestamp) {
|
||||
// common case, rewriting the last timestamp, just reuse the last position
|
||||
buffer = channel->m_lastBuffer;
|
||||
positionW = channel->m_lastItemPositionW;
|
||||
}
|
||||
else {
|
||||
// general case, write in the middle of the buffer, locate the timestamp
|
||||
// (or the timestamp just after), clear this item and all future items,
|
||||
// and write at that position
|
||||
item = channel->findItemOrLater(timestamp, &buffer);
|
||||
if (item == NULL) {
|
||||
// this should not happen
|
||||
return NULL;
|
||||
}
|
||||
// this item will become the last one of this channel, clear any later buffer
|
||||
while ((next = buffer->m_next) != NULL) {
|
||||
buffer->m_next = next->m_next;
|
||||
free(next);
|
||||
}
|
||||
// no need to update the buffer, this will be done when the item is written
|
||||
positionW = CACHE_ITEM_POSITIONW(buffer, item);
|
||||
}
|
||||
item = CACHE_ITEM_ADDR(buffer, positionW);
|
||||
sizeW = CACHE_ITEM_SIZEW(item, length);
|
||||
// we have positionW pointing where we can put the item
|
||||
// before we do that we have to check if we can:
|
||||
// - enough room
|
||||
// - timestamp not too late
|
||||
if ((positionW + sizeW > channel->m_bufferSizeW) ||
|
||||
(positionW > 0 && timestamp >= buffer->m_firstTimestamp + 0x10000))
|
||||
{
|
||||
// we must allocate a new buffer to store this item
|
||||
// but before we must make sure that the current buffer is consistent
|
||||
if (positionW != buffer->m_firstFreePositionW) {
|
||||
// This means that we were trying to write in the middle of the buffer.
|
||||
// We must set the buffer right with positionW being the last position
|
||||
// and find the item before positionW to make it the last.
|
||||
block = positionW >> channel->m_positionToBlockShiftW;
|
||||
CacheItem *previousItem, *nextItem;
|
||||
if (block == 0) {
|
||||
// start from first item, we know it is not our item because positionW > 0
|
||||
previousItem = &buffer->m_firstItem;
|
||||
}
|
||||
else {
|
||||
// no need to check the current block, it will point to our item or a later one
|
||||
// but the previous block will be a good start for sure.
|
||||
block--;
|
||||
previousItem = CACHE_BLOCK_ITEM_ADDR(channel, buffer, block);
|
||||
}
|
||||
while ((nextItem = CACHE_NEXT_ITEM(previousItem)) < item)
|
||||
previousItem = nextItem;
|
||||
// we must have found our item
|
||||
assert(nextItem == item);
|
||||
// now set the buffer
|
||||
buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer, previousItem);
|
||||
buffer->m_firstFreePositionW = positionW;
|
||||
buffer->m_lastTimestamp = buffer->m_firstTimestamp + previousItem->m_timeOffset;
|
||||
block = buffer->m_lastItemPositionW >> channel->m_positionToBlockShiftW;
|
||||
buffer->lookup[block].m_offsetW = buffer->m_lastItemPositionW &
|
||||
channel->m_positionToOffsetMaskW;
|
||||
buffer->lookup[block].m_timeOffset = previousItem->m_timeOffset;
|
||||
// and also the channel, just in case
|
||||
channel->m_lastBuffer = buffer;
|
||||
channel->m_lastTimestamp = buffer->m_lastTimestamp;
|
||||
channel->m_lastItemPositionW = buffer->m_lastItemPositionW;
|
||||
}
|
||||
// now allocate a new buffer
|
||||
buffer->m_next = channel->allocBuffer();
|
||||
if (buffer->m_next == NULL)
|
||||
return NULL;
|
||||
buffer = buffer->m_next;
|
||||
positionW = 0;
|
||||
item = &buffer->m_firstItem;
|
||||
sizeW = CACHE_ITEM_SIZEW(item, length);
|
||||
}
|
||||
// all check passed, ready to write the item
|
||||
item->m_sizeW = sizeW;
|
||||
if (positionW == 0) {
|
||||
item->m_timeOffset = 0;
|
||||
buffer->m_firstTimestamp = timestamp;
|
||||
}
|
||||
else {
|
||||
item->m_timeOffset = (unsigned short)(timestamp - buffer->m_firstTimestamp);
|
||||
}
|
||||
buffer->m_lastItemPositionW = positionW;
|
||||
buffer->m_firstFreePositionW = positionW + sizeW;
|
||||
buffer->m_lastTimestamp = timestamp;
|
||||
block = positionW >> channel->m_positionToBlockShiftW;
|
||||
buffer->lookup[block].m_offsetW = positionW & channel->m_positionToOffsetMaskW;
|
||||
buffer->lookup[block].m_timeOffset = item->m_timeOffset;
|
||||
buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer, item);
|
||||
buffer->m_firstFreePositionW = buffer->m_lastItemPositionW + item->m_sizeW;
|
||||
channel->m_lastBuffer = buffer;
|
||||
channel->m_lastItemPositionW = positionW;
|
||||
channel->m_lastTimestamp = timestamp;
|
||||
}
|
||||
// now copy the item
|
||||
void *itemData = CACHE_ITEM_DATA_POINTER(item);
|
||||
if (data)
|
||||
memcpy(itemData, data, length);
|
||||
return itemData;
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return NULL;
|
||||
}
|
||||
entry = it->second;
|
||||
if (id < 0 || id >= (int) entry->m_count || !entry->m_channelArray[id].m_busy)
|
||||
return NULL;
|
||||
channel = &entry->m_channelArray[id];
|
||||
if (length > channel->m_maxItemSizeB)
|
||||
return NULL;
|
||||
if (timestamp == 0) {
|
||||
// initial item, delete all buffers
|
||||
channel->clear();
|
||||
// and create initial item
|
||||
item = NULL;
|
||||
// we will allocate the memory, which is always pointer aligned => compute size
|
||||
// with NULL will give same result.
|
||||
sizeW = CACHE_ITEM_SIZEW(item,length);
|
||||
item = (CacheItem*)calloc(sizeW, 4);
|
||||
item->m_sizeW = sizeW;
|
||||
channel->initItem = item;
|
||||
} else {
|
||||
if (!channel->m_lastBuffer) {
|
||||
// no item in buffer, insert item at first position of first buffer
|
||||
positionW = 0;
|
||||
if ((buffer = channel->m_firstBuffer) == NULL) {
|
||||
buffer = channel->allocBuffer();
|
||||
channel->m_firstBuffer = buffer;
|
||||
}
|
||||
} else if (timestamp > channel->m_lastTimestamp) {
|
||||
// this is the normal case: we are writing past lastest timestamp
|
||||
buffer = channel->m_lastBuffer;
|
||||
positionW = buffer->m_firstFreePositionW;
|
||||
} else if (timestamp == channel->m_lastTimestamp) {
|
||||
// common case, rewriting the last timestamp, just reuse the last position
|
||||
buffer = channel->m_lastBuffer;
|
||||
positionW = channel->m_lastItemPositionW;
|
||||
} else {
|
||||
// general case, write in the middle of the buffer, locate the timestamp
|
||||
// (or the timestamp just after), clear this item and all future items,
|
||||
// and write at that position
|
||||
item = channel->findItemOrLater(timestamp, &buffer);
|
||||
if (item == NULL) {
|
||||
// this should not happen
|
||||
return NULL;
|
||||
}
|
||||
// this item will become the last one of this channel, clear any later buffer
|
||||
while ((next = buffer->m_next) != NULL) {
|
||||
buffer->m_next = next->m_next;
|
||||
free(next);
|
||||
}
|
||||
// no need to update the buffer, this will be done when the item is written
|
||||
positionW = CACHE_ITEM_POSITIONW(buffer,item);
|
||||
}
|
||||
item = CACHE_ITEM_ADDR(buffer,positionW);
|
||||
sizeW = CACHE_ITEM_SIZEW(item,length);
|
||||
// we have positionW pointing where we can put the item
|
||||
// before we do that we have to check if we can:
|
||||
// - enough room
|
||||
// - timestamp not too late
|
||||
if ((positionW+sizeW > channel->m_bufferSizeW) ||
|
||||
(positionW > 0 && timestamp >= buffer->m_firstTimestamp+0x10000)) {
|
||||
// we must allocate a new buffer to store this item
|
||||
// but before we must make sure that the current buffer is consistent
|
||||
if (positionW != buffer->m_firstFreePositionW) {
|
||||
// This means that we were trying to write in the middle of the buffer.
|
||||
// We must set the buffer right with positionW being the last position
|
||||
// and find the item before positionW to make it the last.
|
||||
block = positionW>>channel->m_positionToBlockShiftW;
|
||||
CacheItem *previousItem, *nextItem;
|
||||
if (block == 0) {
|
||||
// start from first item, we know it is not our item because positionW > 0
|
||||
previousItem = &buffer->m_firstItem;
|
||||
} else {
|
||||
// no need to check the current block, it will point to our item or a later one
|
||||
// but the previous block will be a good start for sure.
|
||||
block--;
|
||||
previousItem = CACHE_BLOCK_ITEM_ADDR(channel,buffer,block);
|
||||
}
|
||||
while ((nextItem = CACHE_NEXT_ITEM(previousItem)) < item)
|
||||
previousItem = nextItem;
|
||||
// we must have found our item
|
||||
assert(nextItem==item);
|
||||
// now set the buffer
|
||||
buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer,previousItem);
|
||||
buffer->m_firstFreePositionW = positionW;
|
||||
buffer->m_lastTimestamp = buffer->m_firstTimestamp + previousItem->m_timeOffset;
|
||||
block = buffer->m_lastItemPositionW>>channel->m_positionToBlockShiftW;
|
||||
buffer->lookup[block].m_offsetW = buffer->m_lastItemPositionW&channel->m_positionToOffsetMaskW;
|
||||
buffer->lookup[block].m_timeOffset = previousItem->m_timeOffset;
|
||||
// and also the channel, just in case
|
||||
channel->m_lastBuffer = buffer;
|
||||
channel->m_lastTimestamp = buffer->m_lastTimestamp;
|
||||
channel->m_lastItemPositionW = buffer->m_lastItemPositionW;
|
||||
}
|
||||
// now allocate a new buffer
|
||||
buffer->m_next = channel->allocBuffer();
|
||||
if (buffer->m_next == NULL)
|
||||
return NULL;
|
||||
buffer = buffer->m_next;
|
||||
positionW = 0;
|
||||
item = &buffer->m_firstItem;
|
||||
sizeW = CACHE_ITEM_SIZEW(item,length);
|
||||
}
|
||||
// all check passed, ready to write the item
|
||||
item->m_sizeW = sizeW;
|
||||
if (positionW == 0) {
|
||||
item->m_timeOffset = 0;
|
||||
buffer->m_firstTimestamp = timestamp;
|
||||
} else {
|
||||
item->m_timeOffset = (unsigned short)(timestamp-buffer->m_firstTimestamp);
|
||||
}
|
||||
buffer->m_lastItemPositionW = positionW;
|
||||
buffer->m_firstFreePositionW = positionW+sizeW;
|
||||
buffer->m_lastTimestamp = timestamp;
|
||||
block = positionW>>channel->m_positionToBlockShiftW;
|
||||
buffer->lookup[block].m_offsetW = positionW&channel->m_positionToOffsetMaskW;
|
||||
buffer->lookup[block].m_timeOffset = item->m_timeOffset;
|
||||
buffer->m_lastItemPositionW = CACHE_ITEM_POSITIONW(buffer,item);
|
||||
buffer->m_firstFreePositionW = buffer->m_lastItemPositionW+item->m_sizeW;
|
||||
channel->m_lastBuffer = buffer;
|
||||
channel->m_lastItemPositionW = positionW;
|
||||
channel->m_lastTimestamp = timestamp;
|
||||
}
|
||||
// now copy the item
|
||||
void *itemData = CACHE_ITEM_DATA_POINTER(item);
|
||||
if (data)
|
||||
memcpy(itemData, data, length);
|
||||
return itemData;
|
||||
}
|
||||
|
||||
const void *Cache::getPreviousCacheItem(const void *device, int id, unsigned int *timestamp)
|
||||
{
|
||||
CacheMap::iterator it;
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
CacheBuffer *buffer;
|
||||
CacheItem *item;
|
||||
CacheMap::iterator it;
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
CacheBuffer *buffer;
|
||||
CacheItem *item;
|
||||
|
||||
if (device) {
|
||||
it = m_cache.find(device);
|
||||
}
|
||||
else {
|
||||
it = m_cache.begin();
|
||||
}
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return NULL;
|
||||
}
|
||||
entry = it->second;
|
||||
if (id < 0 || id >= (int)entry->m_count || !entry->m_channelArray[id].m_busy)
|
||||
return NULL;
|
||||
channel = &entry->m_channelArray[id];
|
||||
if ((item = channel->findItemEarlier(*timestamp, &buffer)) == NULL)
|
||||
return NULL;
|
||||
*timestamp = (buffer) ? buffer->m_firstTimestamp + item->m_timeOffset : 0;
|
||||
return CACHE_ITEM_DATA_POINTER(item);
|
||||
if (device) {
|
||||
it = m_cache.find(device);
|
||||
} else {
|
||||
it = m_cache.begin();
|
||||
}
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return NULL;
|
||||
}
|
||||
entry = it->second;
|
||||
if (id < 0 || id >= (int) entry->m_count || !entry->m_channelArray[id].m_busy)
|
||||
return NULL;
|
||||
channel = &entry->m_channelArray[id];
|
||||
if ((item = channel->findItemEarlier(*timestamp,&buffer)) == NULL)
|
||||
return NULL;
|
||||
*timestamp = (buffer) ? buffer->m_firstTimestamp+item->m_timeOffset : 0;
|
||||
return CACHE_ITEM_DATA_POINTER(item);
|
||||
}
|
||||
|
||||
const CacheItem *Cache::getCurrentCacheItemInternal(const void *device, int id, CacheTS timestamp)
|
||||
{
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
CacheBuffer *buffer;
|
||||
CacheItem *item;
|
||||
CacheMap::iterator it = m_cache.find(device);
|
||||
CacheEntry *entry;
|
||||
CacheChannel *channel;
|
||||
CacheBuffer *buffer;
|
||||
CacheItem *item;
|
||||
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return NULL;
|
||||
}
|
||||
entry = it->second;
|
||||
if (id < 0 || id >= (int)entry->m_count || !entry->m_channelArray[id].m_busy)
|
||||
return NULL;
|
||||
channel = &entry->m_channelArray[id];
|
||||
if ((item = channel->findItemOrLater(timestamp, &buffer)) == NULL)
|
||||
return NULL;
|
||||
if (buffer && buffer->m_firstTimestamp + item->m_timeOffset != timestamp)
|
||||
return NULL;
|
||||
return item;
|
||||
if (it == m_cache.end()) {
|
||||
// device does not exist
|
||||
return NULL;
|
||||
}
|
||||
entry = it->second;
|
||||
if (id < 0 || id >= (int) entry->m_count || !entry->m_channelArray[id].m_busy)
|
||||
return NULL;
|
||||
channel = &entry->m_channelArray[id];
|
||||
if ((item = channel->findItemOrLater(timestamp,&buffer)) == NULL)
|
||||
return NULL;
|
||||
if (buffer && buffer->m_firstTimestamp+item->m_timeOffset != timestamp)
|
||||
return NULL;
|
||||
return item;
|
||||
}
|
||||
|
||||
const void *Cache::getCurrentCacheItem(const void *device, int channel, unsigned int timestamp)
|
||||
{
|
||||
const CacheItem *item = getCurrentCacheItemInternal(device, channel, timestamp);
|
||||
return (item) ? CACHE_ITEM_DATA_POINTER(item) : NULL;
|
||||
const CacheItem *item = getCurrentCacheItemInternal(device, channel, timestamp);
|
||||
return (item) ? CACHE_ITEM_DATA_POINTER(item) : NULL;
|
||||
}
|
||||
|
||||
double *Cache::addCacheVectorIfDifferent(const void *device,
|
||||
int channel,
|
||||
CacheTS timestamp,
|
||||
double *newdata,
|
||||
unsigned int length,
|
||||
double threshold)
|
||||
double *Cache::addCacheVectorIfDifferent(const void *device, int channel, CacheTS timestamp, double *newdata, unsigned int length, double threshold)
|
||||
{
|
||||
const CacheItem *item = getCurrentCacheItemInternal(device, channel, timestamp);
|
||||
unsigned int sizeW = CACHE_ITEM_SIZEW(item, length * sizeof(double));
|
||||
if (!item || item->m_sizeW != sizeW)
|
||||
return (double *)addCacheItem(device, channel, timestamp, newdata, length * sizeof(double));
|
||||
double *olddata = (double *)CACHE_ITEM_DATA_POINTER(item);
|
||||
if (!length)
|
||||
return olddata;
|
||||
double *ref = olddata;
|
||||
double *v = newdata;
|
||||
unsigned int i;
|
||||
for (i = length; i > 0; --i) {
|
||||
if (fabs(*v - *ref) > threshold)
|
||||
break;
|
||||
*ref++ = *v++;
|
||||
}
|
||||
if (i)
|
||||
olddata = (double *)addCacheItem(device, channel, timestamp, newdata, length * sizeof(double));
|
||||
return olddata;
|
||||
const CacheItem *item = getCurrentCacheItemInternal(device, channel, timestamp);
|
||||
unsigned int sizeW = CACHE_ITEM_SIZEW(item,length*sizeof(double));
|
||||
if (!item || item->m_sizeW != sizeW)
|
||||
return (double*)addCacheItem(device, channel, timestamp, newdata, length*sizeof(double));
|
||||
double *olddata = (double*)CACHE_ITEM_DATA_POINTER(item);
|
||||
if (!length)
|
||||
return olddata;
|
||||
double *ref = olddata;
|
||||
double *v = newdata;
|
||||
unsigned int i;
|
||||
for (i=length; i>0; --i) {
|
||||
if (fabs(*v-*ref) > threshold)
|
||||
break;
|
||||
*ref++ = *v++;
|
||||
}
|
||||
if (i)
|
||||
olddata = (double*)addCacheItem(device, channel, timestamp, newdata, length*sizeof(double));
|
||||
return olddata;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
@@ -13,57 +13,51 @@
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
#define CACHE_LOOKUP_TABLE_SIZE 128
|
||||
#define CACHE_DEFAULT_BUFFER_SIZE 32768
|
||||
#define CACHE_CHANNEL_EXTEND_SIZE 10
|
||||
#define CACHE_MAX_ITEM_SIZE 0x3FFF0
|
||||
#define CACHE_LOOKUP_TABLE_SIZE 128
|
||||
#define CACHE_DEFAULT_BUFFER_SIZE 32768
|
||||
#define CACHE_CHANNEL_EXTEND_SIZE 10
|
||||
#define CACHE_MAX_ITEM_SIZE 0x3FFF0
|
||||
|
||||
/* macro to get the alignment gap after an item header */
|
||||
#define CACHE_ITEM_GAPB(item) \
|
||||
(unsigned int)(((size_t)item + sizeof(CacheItem)) & (sizeof(void *) - 1))
|
||||
#define CACHE_ITEM_GAPB(item) (unsigned int)(((size_t)item+sizeof(CacheItem))&(sizeof(void*)-1))
|
||||
/* macro to get item data position, item=CacheItem pointer */
|
||||
#define CACHE_ITEM_DATA_POINTER(item) \
|
||||
(void *)((unsigned char *)item + sizeof(CacheItem) + CACHE_ITEM_GAPB(item))
|
||||
#define CACHE_ITEM_DATA_POINTER(item) (void*)((unsigned char*)item+sizeof(CacheItem)+CACHE_ITEM_GAPB(item))
|
||||
/* macro to get item size in 32bit words from item address and length, item=CacheItem pointer */
|
||||
#define CACHE_ITEM_SIZEW(item, length) \
|
||||
(unsigned int)((sizeof(CacheItem) + CACHE_ITEM_GAPB(item) + (((length) + 3) & ~0x3)) >> 2)
|
||||
#define CACHE_ITEM_SIZEW(item,length) (unsigned int)((sizeof(CacheItem)+CACHE_ITEM_GAPB(item)+(((length)+3)&~0x3))>>2)
|
||||
/* macto to move from one item to the next, item=CacheItem pointer, updated by the macro */
|
||||
#define CACHE_NEXT_ITEM(item) ((item) + (item)->m_sizeW)
|
||||
#define CACHE_BLOCK_ITEM_ADDR(chan, buf, block) \
|
||||
(&(buf)->m_firstItem + \
|
||||
(((unsigned int)(block) << chan->m_positionToBlockShiftW) + (buf)->lookup[block].m_offsetW))
|
||||
#define CACHE_ITEM_ADDR(buf, pos) (&(buf)->m_firstItem + (pos))
|
||||
#define CACHE_ITEM_POSITIONW(buf, item) (unsigned int)(item - &buf->m_firstItem)
|
||||
#define CACHE_NEXT_ITEM(item) ((item)+(item)->m_sizeW)
|
||||
#define CACHE_BLOCK_ITEM_ADDR(chan,buf,block) (&(buf)->m_firstItem+(((unsigned int)(block)<<chan->m_positionToBlockShiftW)+(buf)->lookup[block].m_offsetW))
|
||||
#define CACHE_ITEM_ADDR(buf,pos) (&(buf)->m_firstItem+(pos))
|
||||
#define CACHE_ITEM_POSITIONW(buf,item) (unsigned int)(item-&buf->m_firstItem)
|
||||
|
||||
typedef unsigned int CacheTS;
|
||||
|
||||
struct Timestamp {
|
||||
double realTimestamp;
|
||||
double realTimestep;
|
||||
CacheTS cacheTimestamp;
|
||||
unsigned int numstep : 8;
|
||||
unsigned int substep : 1;
|
||||
unsigned int reiterate : 1;
|
||||
unsigned int cache : 1;
|
||||
unsigned int update : 1;
|
||||
unsigned int interpolate : 1;
|
||||
unsigned int dummy : 19;
|
||||
struct Timestamp
|
||||
{
|
||||
double realTimestamp;
|
||||
double realTimestep;
|
||||
CacheTS cacheTimestamp;
|
||||
unsigned int numstep:8;
|
||||
unsigned int substep:1;
|
||||
unsigned int reiterate:1;
|
||||
unsigned int cache:1;
|
||||
unsigned int update:1;
|
||||
unsigned int interpolate:1;
|
||||
unsigned int dummy:19;
|
||||
|
||||
Timestamp()
|
||||
{
|
||||
memset(this, 0, sizeof(Timestamp));
|
||||
}
|
||||
Timestamp() { memset(this, 0, sizeof(Timestamp)); }
|
||||
};
|
||||
|
||||
/* utility function to return second timestamp to millisecond */
|
||||
inline void setCacheTimestamp(Timestamp ×tamp)
|
||||
inline void setCacheTimestamp(Timestamp& timestamp)
|
||||
{
|
||||
if (timestamp.realTimestamp < 0.0 || timestamp.realTimestamp > 4294967.295)
|
||||
timestamp.cacheTimestamp = 0;
|
||||
else
|
||||
timestamp.cacheTimestamp = (CacheTS)(timestamp.realTimestamp * 1000.0 + 0.5);
|
||||
if (timestamp.realTimestamp < 0.0 || timestamp.realTimestamp > 4294967.295)
|
||||
timestamp.cacheTimestamp = 0;
|
||||
else
|
||||
timestamp.cacheTimestamp = (CacheTS)(timestamp.realTimestamp*1000.0+0.5);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
class Cache:
|
||||
Top level class, only one instance of this class should exists.
|
||||
@@ -74,13 +68,13 @@ The device must specify the largest cache item (limited to 256Kb) so that the ca
|
||||
buffer can be organized optimally.
|
||||
Cache channels are identified by small number (starting from 0) allocated by the cache system.
|
||||
Cache items are inserted into cache channels ordered by timestamp. Writing is always done
|
||||
at the end of the cache buffer: writing an item automatically clears all items with
|
||||
at the end of the cache buffer: writing an item automatically clears all items with
|
||||
higher timestamp.
|
||||
A cache item is an array of bytes provided by the device; the format of the cache item is left
|
||||
to the device.
|
||||
A cache item is an array of bytes provided by the device; the format of the cache item is left
|
||||
to the device.
|
||||
The device can retrieve a cache item associated with a certain timestamp. The cache system
|
||||
returns a pointer that points directly in the cache buffer to avoid unnecessary copy.
|
||||
The pointer is guaranteed to be pointer aligned so that direct mapping to C structure is possible
|
||||
returns a pointer that points directly in the cache buffer to avoid unnecessary copy.
|
||||
The pointer is guaranteed to be pointer aligned so that direct mapping to C structure is possible
|
||||
(=32 bit aligned on 32 systems and 64 bit aligned on 64 bits system).
|
||||
|
||||
Timestamp = rounded time in millisecond.
|
||||
@@ -91,113 +85,108 @@ struct CacheBuffer;
|
||||
struct CacheItem;
|
||||
struct CacheChannel;
|
||||
|
||||
class Cache {
|
||||
private:
|
||||
/* map between device and cache entry.
|
||||
Dynamically updated when more devices create cache channels */
|
||||
typedef std::map<const void *, struct CacheEntry *> CacheMap;
|
||||
CacheMap m_cache;
|
||||
const CacheItem *getCurrentCacheItemInternal(const void *device, int channel, CacheTS timestamp);
|
||||
class Cache
|
||||
{
|
||||
private:
|
||||
/* map between device and cache entry.
|
||||
Dynamically updated when more devices create cache channels */
|
||||
typedef std::map<const void *, struct CacheEntry*> CacheMap;
|
||||
CacheMap m_cache;
|
||||
const CacheItem *getCurrentCacheItemInternal(const void *device, int channel, CacheTS timestamp);
|
||||
|
||||
public:
|
||||
Cache();
|
||||
~Cache();
|
||||
/* add a cache channel, maxItemSize must be < 256k.
|
||||
name : channel name, truncated at 31 characters
|
||||
msxItemSize : maximum size of item in bytes, items of larger size will be rejected
|
||||
return value >= 0: channel id, -1: error */
|
||||
int addChannel(const void *device, const char *name, unsigned int maxItemSize);
|
||||
|
||||
public:
|
||||
Cache();
|
||||
~Cache();
|
||||
/* add a cache channel, maxItemSize must be < 256k.
|
||||
name : channel name, truncated at 31 characters
|
||||
msxItemSize : maximum size of item in bytes, items of larger size will be rejected
|
||||
return value >= 0: channel id, -1: error */
|
||||
int addChannel(const void *device, const char *name, unsigned int maxItemSize);
|
||||
/* delete a cache channel (and all associated buffers and items) */
|
||||
int deleteChannel(const void *device, int channel);
|
||||
/* delete all channels of a device and remove the device from the map */
|
||||
int deleteDevice(const void *device);
|
||||
/* removes all cache items, leaving the special item at timestamp=0.
|
||||
if device=NULL, apply to all devices. */
|
||||
void clearCacheFrom(const void *device, CacheTS timestamp);
|
||||
|
||||
/* delete a cache channel (and all associated buffers and items) */
|
||||
int deleteChannel(const void *device, int channel);
|
||||
/* delete all channels of a device and remove the device from the map */
|
||||
int deleteDevice(const void *device);
|
||||
/* removes all cache items, leaving the special item at timestamp=0.
|
||||
if device=NULL, apply to all devices. */
|
||||
void clearCacheFrom(const void *device, CacheTS timestamp);
|
||||
/* add a new cache item
|
||||
channel: the cache channel (as returned by AddChannel
|
||||
data, length: the cache item and length in bytes
|
||||
If data is NULL, the memory is allocated in the cache but not writen
|
||||
return: error: NULL, success: pointer to item in cache */
|
||||
void *addCacheItem(const void *device, int channel, CacheTS timestamp, void *data, unsigned int length);
|
||||
|
||||
/* add a new cache item
|
||||
channel: the cache channel (as returned by AddChannel
|
||||
data, length: the cache item and length in bytes
|
||||
If data is NULL, the memory is allocated in the cache but not writen
|
||||
return: error: NULL, success: pointer to item in cache */
|
||||
void *addCacheItem(
|
||||
const void *device, int channel, CacheTS timestamp, void *data, unsigned int length);
|
||||
/* specialized function to add a vector of double in the cache
|
||||
It will first check if a vector exist already in the cache for the same timestamp
|
||||
and compared the cached vector with the new values.
|
||||
If all values are within threshold, the vector is updated but the cache is not deleted
|
||||
for the future timestamps. */
|
||||
double *addCacheVectorIfDifferent(const void *device, int channel, CacheTS timestamp, double *data, unsigned int length, double threshold);
|
||||
|
||||
/* specialized function to add a vector of double in the cache
|
||||
It will first check if a vector exist already in the cache for the same timestamp
|
||||
and compared the cached vector with the new values.
|
||||
If all values are within threshold, the vector is updated but the cache is not deleted
|
||||
for the future timestamps. */
|
||||
double *addCacheVectorIfDifferent(const void *device,
|
||||
int channel,
|
||||
CacheTS timestamp,
|
||||
double *data,
|
||||
unsigned int length,
|
||||
double threshold);
|
||||
/* returns the cache item with timestamp that is just before the given timestamp.
|
||||
returns the data pointer or NULL if there is no cache item before timestamp.
|
||||
On return, timestamp is updated with the actual timestamp of the item being returned.
|
||||
Note that the length of the item is not returned, it is up to the device to organize
|
||||
the data so that length can be retrieved from the data if needed.
|
||||
Device can NULL, it will then just look the first channel available, useful to
|
||||
test the status of the cache. */
|
||||
const void *getPreviousCacheItem(const void *device, int channel, CacheTS *timestamp);
|
||||
|
||||
/* returns the cache item with timestamp that is just before the given timestamp.
|
||||
returns the data pointer or NULL if there is no cache item before timestamp.
|
||||
On return, timestamp is updated with the actual timestamp of the item being returned.
|
||||
Note that the length of the item is not returned, it is up to the device to organize
|
||||
the data so that length can be retrieved from the data if needed.
|
||||
Device can NULL, it will then just look the first channel available, useful to
|
||||
test the status of the cache. */
|
||||
const void *getPreviousCacheItem(const void *device, int channel, CacheTS *timestamp);
|
||||
/* returns the cache item with the timestamp that is exactly equal to the given timestamp
|
||||
If there is no cache item for this timestamp, returns NULL.*/
|
||||
const void *getCurrentCacheItem(const void *device, int channel, CacheTS timestamp);
|
||||
|
||||
/* returns the cache item with the timestamp that is exactly equal to the given timestamp
|
||||
If there is no cache item for this timestamp, returns NULL.*/
|
||||
const void *getCurrentCacheItem(const void *device, int channel, CacheTS timestamp);
|
||||
};
|
||||
|
||||
/* the following structures are not internal use only, they should not be used directly */
|
||||
|
||||
struct CacheEntry {
|
||||
CacheChannel
|
||||
*m_channelArray; // array of channels, automatically resized if more channels are created
|
||||
unsigned int m_count; // number of channel in channelArray
|
||||
CacheEntry() : m_channelArray(NULL), m_count(0) {}
|
||||
~CacheEntry();
|
||||
struct CacheEntry
|
||||
{
|
||||
CacheChannel *m_channelArray; // array of channels, automatically resized if more channels are created
|
||||
unsigned int m_count; // number of channel in channelArray
|
||||
CacheEntry() : m_channelArray(NULL), m_count(0) {}
|
||||
~CacheEntry();
|
||||
};
|
||||
|
||||
struct CacheChannel {
|
||||
CacheItem *initItem; // item corresponding to timestamp=0
|
||||
struct CacheBuffer *m_firstBuffer; // first buffer of list
|
||||
struct CacheBuffer *m_lastBuffer; // last buffer of list to which an item was written
|
||||
char m_name[32]; // channel name
|
||||
unsigned char m_busy; // =0 if channel is free, !=0 when channel is in use
|
||||
unsigned char m_positionToBlockShiftW; // number of bits to shift a position in word to get the
|
||||
// block number
|
||||
unsigned short
|
||||
m_positionToOffsetMaskW; // bit mask to apply on a position in word to get offset in a block
|
||||
unsigned int m_maxItemSizeB; // maximum item size in bytes
|
||||
unsigned int
|
||||
m_bufferSizeW; // size of item buffer in word to allocate when a new buffer must be created
|
||||
unsigned int m_blockSizeW; // block size in words of the lookup table
|
||||
unsigned int m_lastTimestamp; // timestamp of the last item that was written
|
||||
unsigned int m_lastItemPositionW; // position in words in lastBuffer of the last item written
|
||||
void clear();
|
||||
CacheBuffer *allocBuffer();
|
||||
CacheItem *findItemOrLater(unsigned int timestamp, CacheBuffer **rBuffer);
|
||||
CacheItem *findItemEarlier(unsigned int timestamp, CacheBuffer **rBuffer);
|
||||
// Internal function: finds an item in a buffer that is < timeOffset
|
||||
// timeOffset must be a valid offset for the buffer and the buffer must not be empty
|
||||
// on return highBlock contains the block with items above or equal to timeOffset
|
||||
CacheItem *_findBlock(CacheBuffer *buffer, unsigned short timeOffset, unsigned int *highBlock);
|
||||
struct CacheChannel
|
||||
{
|
||||
CacheItem* initItem; // item corresponding to timestamp=0
|
||||
struct CacheBuffer *m_firstBuffer; // first buffer of list
|
||||
struct CacheBuffer *m_lastBuffer; // last buffer of list to which an item was written
|
||||
char m_name[32]; // channel name
|
||||
unsigned char m_busy; // =0 if channel is free, !=0 when channel is in use
|
||||
unsigned char m_positionToBlockShiftW; // number of bits to shift a position in word to get the block number
|
||||
unsigned short m_positionToOffsetMaskW; // bit mask to apply on a position in word to get offset in a block
|
||||
unsigned int m_maxItemSizeB; // maximum item size in bytes
|
||||
unsigned int m_bufferSizeW; // size of item buffer in word to allocate when a new buffer must be created
|
||||
unsigned int m_blockSizeW; // block size in words of the lookup table
|
||||
unsigned int m_lastTimestamp; // timestamp of the last item that was written
|
||||
unsigned int m_lastItemPositionW; // position in words in lastBuffer of the last item written
|
||||
void clear();
|
||||
CacheBuffer* allocBuffer();
|
||||
CacheItem* findItemOrLater(unsigned int timestamp, CacheBuffer **rBuffer);
|
||||
CacheItem* findItemEarlier(unsigned int timestamp, CacheBuffer **rBuffer);
|
||||
// Internal function: finds an item in a buffer that is < timeOffset
|
||||
// timeOffset must be a valid offset for the buffer and the buffer must not be empty
|
||||
// on return highBlock contains the block with items above or equal to timeOffset
|
||||
CacheItem *_findBlock(CacheBuffer *buffer, unsigned short timeOffset, unsigned int *highBlock);
|
||||
};
|
||||
|
||||
struct CacheBlock {
|
||||
unsigned short m_timeOffset; // timestamp relative to m_firstTimestamp
|
||||
unsigned short m_offsetW; // position in words of item relative to start of block
|
||||
unsigned short m_timeOffset; // timestamp relative to m_firstTimestamp
|
||||
unsigned short m_offsetW; // position in words of item relative to start of block
|
||||
};
|
||||
|
||||
/* CacheItem is the header of each item in the buffer, must be 32bit
|
||||
Items are always 32 bits aligned and size is the number of 32 bit words until the
|
||||
next item header, including an eventual pre and post padding gap for pointer alignment */
|
||||
struct CacheItem {
|
||||
unsigned short m_timeOffset; // timestamp relative to m_firstTimestamp
|
||||
unsigned short m_sizeW; // size of item in 32 bit words
|
||||
// item data follows header immediately or after a gap if position is not pointer aligned
|
||||
struct CacheItem
|
||||
{
|
||||
unsigned short m_timeOffset; // timestamp relative to m_firstTimestamp
|
||||
unsigned short m_sizeW; // size of item in 32 bit words
|
||||
// item data follows header immediately or after a gap if position is not pointer aligned
|
||||
};
|
||||
|
||||
// Buffer header
|
||||
@@ -209,29 +198,31 @@ struct CacheItem {
|
||||
// m_lastItemPositionW position in word of last item written
|
||||
// m_firstFreePositionW position in word where a new item can be written, 0 if buffer is empty
|
||||
// lookup lookup table for fast access to item by timestamp
|
||||
// The buffer is divided in blocks of 2**n bytes with n chosen so that
|
||||
// there are no more than CACHE_LOOKUP_TABLE_SIZE blocks and that each
|
||||
// block will contain at least one item.
|
||||
// Each element of the lookup table gives the timestamp and offset
|
||||
// The buffer is divided in blocks of 2**n bytes with n chosen so that
|
||||
// there are no more than CACHE_LOOKUP_TABLE_SIZE blocks and that each
|
||||
// block will contain at least one item.
|
||||
// Each element of the lookup table gives the timestamp and offset
|
||||
// of the last cache item occupying (=starting in) the corresponding block.
|
||||
#define CACHE_HEADER \
|
||||
struct CacheBuffer *m_next; \
|
||||
unsigned int m_firstTimestamp; \
|
||||
unsigned int m_lastTimestamp; \
|
||||
\
|
||||
unsigned int m_lastItemPositionW; \
|
||||
unsigned int m_firstFreePositionW; \
|
||||
struct CacheBlock lookup[CACHE_LOOKUP_TABLE_SIZE]
|
||||
struct CacheBuffer *m_next; \
|
||||
unsigned int m_firstTimestamp; \
|
||||
unsigned int m_lastTimestamp; \
|
||||
\
|
||||
unsigned int m_lastItemPositionW; \
|
||||
unsigned int m_firstFreePositionW;\
|
||||
struct CacheBlock lookup[CACHE_LOOKUP_TABLE_SIZE]
|
||||
|
||||
struct CacheBufferHeader {
|
||||
CACHE_HEADER;
|
||||
CACHE_HEADER;
|
||||
};
|
||||
#define CACHE_BUFFER_HEADER_SIZE (sizeof(struct CacheBufferHeader))
|
||||
struct CacheBuffer {
|
||||
CACHE_HEADER;
|
||||
struct CacheItem m_firstItem; // the address of this field marks the start of the buffer
|
||||
#define CACHE_BUFFER_HEADER_SIZE (sizeof(struct CacheBufferHeader))
|
||||
struct CacheBuffer
|
||||
{
|
||||
CACHE_HEADER;
|
||||
struct CacheItem m_firstItem; // the address of this field marks the start of the buffer
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
|
||||
}
|
||||
|
||||
#endif /* CACHE_HPP_ */
|
||||
|
||||
@@ -11,179 +11,164 @@
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
ConstraintSet::ConstraintSet(unsigned int _nc, double accuracy, unsigned int maximum_iterations)
|
||||
: m_nc(_nc),
|
||||
m_Cf(e_zero_matrix(m_nc, 6)),
|
||||
m_Wy(e_scalar_vector(m_nc, 1.0)),
|
||||
m_y(m_nc),
|
||||
m_ydot(e_zero_vector(m_nc)),
|
||||
m_chi(e_zero_vector(6)),
|
||||
m_S(6),
|
||||
m_temp(6),
|
||||
m_tdelta(6),
|
||||
m_Jf(e_identity_matrix(6, 6)),
|
||||
m_U(e_identity_matrix(6, 6)),
|
||||
m_V(e_identity_matrix(6, 6)),
|
||||
m_B(e_zero_matrix(6, 6)),
|
||||
m_Jf_inv(e_zero_matrix(6, 6)),
|
||||
m_internalPose(F_identity),
|
||||
m_externalPose(F_identity),
|
||||
m_constraintCallback(NULL),
|
||||
m_constraintParam(NULL),
|
||||
m_toggle(false),
|
||||
m_substep(false),
|
||||
m_threshold(accuracy),
|
||||
m_maxIter(maximum_iterations)
|
||||
ConstraintSet::ConstraintSet(unsigned int _nc,double accuracy,unsigned int maximum_iterations):
|
||||
m_nc(_nc),
|
||||
m_Cf(e_zero_matrix(m_nc,6)),
|
||||
m_Wy(e_scalar_vector(m_nc,1.0)),
|
||||
m_y(m_nc),m_ydot(e_zero_vector(m_nc)),m_chi(e_zero_vector(6)),
|
||||
m_S(6),m_temp(6),m_tdelta(6),
|
||||
m_Jf(e_identity_matrix(6,6)),
|
||||
m_U(e_identity_matrix(6,6)),m_V(e_identity_matrix(6,6)),m_B(e_zero_matrix(6,6)),
|
||||
m_Jf_inv(e_zero_matrix(6,6)),
|
||||
m_internalPose(F_identity), m_externalPose(F_identity),
|
||||
m_constraintCallback(NULL), m_constraintParam(NULL),
|
||||
m_toggle(false),m_substep(false),
|
||||
m_threshold(accuracy),m_maxIter(maximum_iterations)
|
||||
{
|
||||
m_maxDeltaChi = e_scalar(0.52);
|
||||
m_maxDeltaChi = e_scalar(0.52);
|
||||
}
|
||||
|
||||
ConstraintSet::ConstraintSet()
|
||||
: m_nc(0),
|
||||
m_internalPose(F_identity),
|
||||
m_externalPose(F_identity),
|
||||
m_constraintCallback(NULL),
|
||||
m_constraintParam(NULL),
|
||||
m_toggle(false),
|
||||
m_substep(false),
|
||||
m_threshold(0.0),
|
||||
m_maxIter(0)
|
||||
ConstraintSet::ConstraintSet():
|
||||
m_nc(0),
|
||||
m_internalPose(F_identity), m_externalPose(F_identity),
|
||||
m_constraintCallback(NULL), m_constraintParam(NULL),
|
||||
m_toggle(false),m_substep(false),
|
||||
m_threshold(0.0),m_maxIter(0)
|
||||
{
|
||||
m_maxDeltaChi = e_scalar(0.52);
|
||||
m_maxDeltaChi = e_scalar(0.52);
|
||||
}
|
||||
|
||||
void ConstraintSet::reset(unsigned int _nc, double accuracy, unsigned int maximum_iterations)
|
||||
void ConstraintSet::reset(unsigned int _nc,double accuracy,unsigned int maximum_iterations)
|
||||
{
|
||||
m_nc = _nc;
|
||||
m_Jf = e_identity_matrix(6, 6);
|
||||
m_Cf = e_zero_matrix(m_nc, 6);
|
||||
m_U = e_identity_matrix(6, 6);
|
||||
m_V = e_identity_matrix(6, 6);
|
||||
m_B = e_zero_matrix(6, 6);
|
||||
m_Jf_inv = e_zero_matrix(6, 6), m_Wy = e_scalar_vector(m_nc, 1.0), m_chi = e_zero_vector(6);
|
||||
m_chidot = e_zero_vector(6);
|
||||
m_y = e_zero_vector(m_nc);
|
||||
m_ydot = e_zero_vector(m_nc);
|
||||
m_S = e_zero_vector(6);
|
||||
m_temp = e_zero_vector(6);
|
||||
m_tdelta = e_zero_vector(6);
|
||||
m_threshold = accuracy;
|
||||
m_maxIter = maximum_iterations;
|
||||
m_nc = _nc;
|
||||
m_Jf = e_identity_matrix(6,6);
|
||||
m_Cf = e_zero_matrix(m_nc,6);
|
||||
m_U = e_identity_matrix(6,6);
|
||||
m_V = e_identity_matrix(6,6);
|
||||
m_B = e_zero_matrix(6,6);
|
||||
m_Jf_inv = e_zero_matrix(6,6),
|
||||
m_Wy = e_scalar_vector(m_nc,1.0),
|
||||
m_chi = e_zero_vector(6);
|
||||
m_chidot = e_zero_vector(6);
|
||||
m_y = e_zero_vector(m_nc);
|
||||
m_ydot = e_zero_vector(m_nc);
|
||||
m_S = e_zero_vector(6);
|
||||
m_temp = e_zero_vector(6);
|
||||
m_tdelta = e_zero_vector(6);
|
||||
m_threshold = accuracy;
|
||||
m_maxIter = maximum_iterations;
|
||||
}
|
||||
|
||||
ConstraintSet::~ConstraintSet() {}
|
||||
ConstraintSet::~ConstraintSet() {
|
||||
|
||||
void ConstraintSet::modelUpdate(Frame &_external_pose, const Timestamp ×tamp)
|
||||
{
|
||||
m_chi += m_chidot * timestamp.realTimestep;
|
||||
m_externalPose = _external_pose;
|
||||
|
||||
// update the internal pose and Jf
|
||||
updateJacobian();
|
||||
// check if loop is already closed, if not update the pose and Jf
|
||||
unsigned int iter = 0;
|
||||
while (iter < 5 && !closeLoop())
|
||||
iter++;
|
||||
}
|
||||
|
||||
double ConstraintSet::getMaxTimestep(double ×tep)
|
||||
void ConstraintSet::modelUpdate(Frame& _external_pose,const Timestamp& timestamp)
|
||||
{
|
||||
e_scalar maxChidot = m_chidot.array().abs().maxCoeff();
|
||||
if (timestep * maxChidot > m_maxDeltaChi) {
|
||||
timestep = m_maxDeltaChi / maxChidot;
|
||||
}
|
||||
return timestep;
|
||||
m_chi+=m_chidot*timestamp.realTimestep;
|
||||
m_externalPose = _external_pose;
|
||||
|
||||
//update the internal pose and Jf
|
||||
updateJacobian();
|
||||
//check if loop is already closed, if not update the pose and Jf
|
||||
unsigned int iter=0;
|
||||
while(iter<5&&!closeLoop())
|
||||
iter++;
|
||||
}
|
||||
|
||||
bool ConstraintSet::initialise(Frame &init_pose)
|
||||
double ConstraintSet::getMaxTimestep(double& timestep)
|
||||
{
|
||||
m_externalPose = init_pose;
|
||||
// get current Jf
|
||||
updateJacobian();
|
||||
|
||||
unsigned int iter = 0;
|
||||
while (iter < m_maxIter && !closeLoop()) {
|
||||
iter++;
|
||||
}
|
||||
if (iter < m_maxIter)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
e_scalar maxChidot = m_chidot.array().abs().maxCoeff();
|
||||
if (timestep*maxChidot > m_maxDeltaChi) {
|
||||
timestep = m_maxDeltaChi/maxChidot;
|
||||
}
|
||||
return timestep;
|
||||
}
|
||||
|
||||
bool ConstraintSet::setControlParameter(int id,
|
||||
ConstraintAction action,
|
||||
double data,
|
||||
double timestep)
|
||||
{
|
||||
ConstraintValues values;
|
||||
ConstraintSingleValue value;
|
||||
values.values = &value;
|
||||
values.number = 0;
|
||||
values.action = action;
|
||||
values.id = id;
|
||||
value.action = action;
|
||||
value.id = id;
|
||||
switch (action) {
|
||||
case ACT_NONE:
|
||||
return true;
|
||||
case ACT_VALUE:
|
||||
value.yd = data;
|
||||
values.number = 1;
|
||||
break;
|
||||
case ACT_VELOCITY:
|
||||
value.yddot = data;
|
||||
values.number = 1;
|
||||
break;
|
||||
case ACT_TOLERANCE:
|
||||
values.tolerance = data;
|
||||
break;
|
||||
case ACT_FEEDBACK:
|
||||
values.feedback = data;
|
||||
break;
|
||||
case ACT_ALPHA:
|
||||
values.alpha = data;
|
||||
break;
|
||||
default:
|
||||
assert(action == ACT_NONE);
|
||||
break;
|
||||
}
|
||||
return setControlParameters(&values, 1, timestep);
|
||||
}
|
||||
bool ConstraintSet::initialise(Frame& init_pose){
|
||||
m_externalPose=init_pose;
|
||||
// get current Jf
|
||||
updateJacobian();
|
||||
|
||||
bool ConstraintSet::closeLoop()
|
||||
{
|
||||
// Invert Jf
|
||||
// TODO: svd_boost_Macie has problems if Jf contains zero-rows
|
||||
// toggle=!toggle;
|
||||
// svd_boost_Macie(Jf,U,S,V,B,temp,1e-3*threshold,toggle);
|
||||
int ret = KDL::svd_eigen_HH(m_Jf, m_U, m_S, m_V, m_temp);
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
// the reference point and frame of the jacobian is the base frame
|
||||
// m_externalPose-m_internalPose is the twist to extend the end effector
|
||||
// to get the required pose => change the reference point to the base frame
|
||||
Twist twist_delta(diff(m_internalPose, m_externalPose));
|
||||
twist_delta = twist_delta.RefPoint(-m_internalPose.p);
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
m_tdelta(i) = twist_delta(i);
|
||||
// TODO: use damping in constraintset inversion?
|
||||
for (unsigned int i = 0; i < 6; i++) {
|
||||
if (m_S(i) < m_threshold) {
|
||||
m_B.row(i).setConstant(0.0);
|
||||
unsigned int iter=0;
|
||||
while(iter<m_maxIter&&!closeLoop()){
|
||||
iter++;
|
||||
}
|
||||
else {
|
||||
m_B.row(i) = m_U.col(i) / m_S(i);
|
||||
}
|
||||
}
|
||||
|
||||
m_Jf_inv.noalias() = m_V * m_B;
|
||||
|
||||
m_chi.noalias() += m_Jf_inv * m_tdelta;
|
||||
updateJacobian();
|
||||
// m_externalPose-m_internalPose in end effector frame
|
||||
// this is just to compare the pose, a different formula would work too
|
||||
return Equal(m_internalPose.Inverse() * m_externalPose, F_identity, m_threshold);
|
||||
if (iter<m_maxIter)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ConstraintSet::setControlParameter(int id, ConstraintAction action, double data, double timestep)
|
||||
{
|
||||
ConstraintValues values;
|
||||
ConstraintSingleValue value;
|
||||
values.values = &value;
|
||||
values.number = 0;
|
||||
values.action = action;
|
||||
values.id = id;
|
||||
value.action = action;
|
||||
value.id = id;
|
||||
switch (action) {
|
||||
case ACT_NONE:
|
||||
return true;
|
||||
case ACT_VALUE:
|
||||
value.yd = data;
|
||||
values.number = 1;
|
||||
break;
|
||||
case ACT_VELOCITY:
|
||||
value.yddot = data;
|
||||
values.number = 1;
|
||||
break;
|
||||
case ACT_TOLERANCE:
|
||||
values.tolerance = data;
|
||||
break;
|
||||
case ACT_FEEDBACK:
|
||||
values.feedback = data;
|
||||
break;
|
||||
case ACT_ALPHA:
|
||||
values.alpha = data;
|
||||
break;
|
||||
default:
|
||||
assert(action==ACT_NONE);
|
||||
break;
|
||||
}
|
||||
return setControlParameters(&values, 1, timestep);
|
||||
}
|
||||
|
||||
bool ConstraintSet::closeLoop(){
|
||||
//Invert Jf
|
||||
//TODO: svd_boost_Macie has problems if Jf contains zero-rows
|
||||
//toggle=!toggle;
|
||||
//svd_boost_Macie(Jf,U,S,V,B,temp,1e-3*threshold,toggle);
|
||||
int ret = KDL::svd_eigen_HH(m_Jf,m_U,m_S,m_V,m_temp);
|
||||
if(ret<0)
|
||||
return false;
|
||||
|
||||
// the reference point and frame of the jacobian is the base frame
|
||||
// m_externalPose-m_internalPose is the twist to extend the end effector
|
||||
// to get the required pose => change the reference point to the base frame
|
||||
Twist twist_delta(diff(m_internalPose,m_externalPose));
|
||||
twist_delta=twist_delta.RefPoint(-m_internalPose.p);
|
||||
for(unsigned int i=0;i<6;i++)
|
||||
m_tdelta(i)=twist_delta(i);
|
||||
//TODO: use damping in constraintset inversion?
|
||||
for(unsigned int i=0;i<6;i++) {
|
||||
if(m_S(i)<m_threshold){
|
||||
m_B.row(i).setConstant(0.0);
|
||||
} else {
|
||||
m_B.row(i) = m_U.col(i)/m_S(i);
|
||||
}
|
||||
}
|
||||
|
||||
m_Jf_inv.noalias()=m_V*m_B;
|
||||
|
||||
m_chi.noalias()+=m_Jf_inv*m_tdelta;
|
||||
updateJacobian();
|
||||
// m_externalPose-m_internalPose in end effector frame
|
||||
// this is just to compare the pose, a different formula would work too
|
||||
return Equal(m_internalPose.Inverse()*m_externalPose,F_identity,m_threshold);
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace iTaSC
|
||||
|
||||
@@ -9,143 +9,108 @@
|
||||
#ifndef CONSTRAINTSET_HPP_
|
||||
#define CONSTRAINTSET_HPP_
|
||||
|
||||
#include "Cache.hpp"
|
||||
#include "eigen_types.hpp"
|
||||
#include "kdl/frames.hpp"
|
||||
#include "eigen_types.hpp"
|
||||
#include "Cache.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
enum ConstraintAction {
|
||||
ACT_NONE = 0,
|
||||
ACT_VALUE = 1,
|
||||
ACT_VELOCITY = 2,
|
||||
ACT_TOLERANCE = 4,
|
||||
ACT_FEEDBACK = 8,
|
||||
ACT_ALPHA = 16
|
||||
ACT_NONE= 0,
|
||||
ACT_VALUE= 1,
|
||||
ACT_VELOCITY= 2,
|
||||
ACT_TOLERANCE= 4,
|
||||
ACT_FEEDBACK= 8,
|
||||
ACT_ALPHA= 16
|
||||
};
|
||||
|
||||
struct ConstraintSingleValue {
|
||||
unsigned int id; // identifier of constraint value, depends on constraint
|
||||
unsigned int action; // action performed, compbination of ACT_..., set on return
|
||||
const double y; // actual constraint value
|
||||
const double ydot; // actual constraint velocity
|
||||
double yd; // current desired constraint value, changed on return
|
||||
double yddot; // current desired constraint velocity, changed on return
|
||||
ConstraintSingleValue() : id(0), action(0), y(0.0), ydot(0.0) {}
|
||||
unsigned int id; // identifier of constraint value, depends on constraint
|
||||
unsigned int action;// action performed, compbination of ACT_..., set on return
|
||||
const double y; // actual constraint value
|
||||
const double ydot; // actual constraint velocity
|
||||
double yd; // current desired constraint value, changed on return
|
||||
double yddot; // current desired constraint velocity, changed on return
|
||||
ConstraintSingleValue(): id(0), action(0), y(0.0), ydot(0.0) {}
|
||||
};
|
||||
|
||||
struct ConstraintValues {
|
||||
unsigned int id; // identifier of group of constraint values, depend on constraint
|
||||
unsigned short number; // number of constraints in list
|
||||
unsigned short action; // action performed, ACT_..., set on return
|
||||
double alpha; // constraint activation coefficient, should be [0..1]
|
||||
double
|
||||
tolerance; // current desired tolerance on constraint, same unit than yd, changed on return
|
||||
double feedback; // current desired feedback on error, in 1/sec, changed on return
|
||||
struct ConstraintSingleValue *values;
|
||||
ConstraintValues() : id(0), number(0), action(0), values(NULL) {}
|
||||
unsigned int id; // identifier of group of constraint values, depend on constraint
|
||||
unsigned short number; // number of constraints in list
|
||||
unsigned short action; // action performed, ACT_..., set on return
|
||||
double alpha; // constraint activation coefficient, should be [0..1]
|
||||
double tolerance; // current desired tolerance on constraint, same unit than yd, changed on return
|
||||
double feedback; // current desired feedback on error, in 1/sec, changed on return
|
||||
struct ConstraintSingleValue* values;
|
||||
ConstraintValues(): id(0), number(0), action(0), values(NULL) {}
|
||||
};
|
||||
|
||||
class ConstraintSet;
|
||||
typedef bool (*ConstraintCallback)(const Timestamp ×tamp,
|
||||
struct ConstraintValues *const _values,
|
||||
unsigned int _nvalues,
|
||||
void *_param);
|
||||
typedef bool (*ConstraintCallback)(const Timestamp& timestamp, struct ConstraintValues* const _values, unsigned int _nvalues, void* _param);
|
||||
|
||||
class ConstraintSet {
|
||||
protected:
|
||||
unsigned int m_nc;
|
||||
e_scalar m_maxDeltaChi;
|
||||
e_matrix m_Cf;
|
||||
e_vector m_Wy, m_y, m_ydot;
|
||||
e_vector6 m_chi, m_chidot, m_S, m_temp, m_tdelta;
|
||||
e_matrix6 m_Jf, m_U, m_V, m_B, m_Jf_inv;
|
||||
KDL::Frame m_internalPose, m_externalPose;
|
||||
ConstraintCallback m_constraintCallback;
|
||||
void *m_constraintParam;
|
||||
void *m_poseParam;
|
||||
bool m_toggle;
|
||||
bool m_substep;
|
||||
double m_threshold;
|
||||
unsigned int m_maxIter;
|
||||
protected:
|
||||
unsigned int m_nc;
|
||||
e_scalar m_maxDeltaChi;
|
||||
e_matrix m_Cf;
|
||||
e_vector m_Wy,m_y,m_ydot;
|
||||
e_vector6 m_chi,m_chidot,m_S,m_temp,m_tdelta;
|
||||
e_matrix6 m_Jf,m_U,m_V,m_B,m_Jf_inv;
|
||||
KDL::Frame m_internalPose,m_externalPose;
|
||||
ConstraintCallback m_constraintCallback;
|
||||
void* m_constraintParam;
|
||||
void* m_poseParam;
|
||||
bool m_toggle;
|
||||
bool m_substep;
|
||||
double m_threshold;
|
||||
unsigned int m_maxIter;
|
||||
|
||||
friend class Scene;
|
||||
virtual void modelUpdate(KDL::Frame &_external_pose, const Timestamp ×tamp);
|
||||
virtual void updateKinematics(const Timestamp ×tamp) = 0;
|
||||
virtual void pushCache(const Timestamp ×tamp) = 0;
|
||||
virtual void updateJacobian() = 0;
|
||||
virtual void updateControlOutput(const Timestamp ×tamp) = 0;
|
||||
virtual void initCache(Cache *_cache) = 0;
|
||||
virtual bool initialise(KDL::Frame &init_pose);
|
||||
virtual void reset(unsigned int nc, double accuracy, unsigned int maximum_iterations);
|
||||
virtual bool closeLoop();
|
||||
virtual double getMaxTimestep(double ×tep);
|
||||
friend class Scene;
|
||||
virtual void modelUpdate(KDL::Frame& _external_pose,const Timestamp& timestamp);
|
||||
virtual void updateKinematics(const Timestamp& timestamp)=0;
|
||||
virtual void pushCache(const Timestamp& timestamp)=0;
|
||||
virtual void updateJacobian()=0;
|
||||
virtual void updateControlOutput(const Timestamp& timestamp)=0;
|
||||
virtual void initCache(Cache *_cache) = 0;
|
||||
virtual bool initialise(KDL::Frame& init_pose);
|
||||
virtual void reset(unsigned int nc,double accuracy,unsigned int maximum_iterations);
|
||||
virtual bool closeLoop();
|
||||
virtual double getMaxTimestep(double& timestep);
|
||||
|
||||
public:
|
||||
ConstraintSet(unsigned int nc, double accuracy, unsigned int maximum_iterations);
|
||||
ConstraintSet();
|
||||
virtual ~ConstraintSet();
|
||||
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
public:
|
||||
ConstraintSet(unsigned int nc,double accuracy,unsigned int maximum_iterations);
|
||||
ConstraintSet();
|
||||
virtual ~ConstraintSet();
|
||||
|
||||
virtual bool registerCallback(ConstraintCallback _function, void *_param)
|
||||
{
|
||||
m_constraintCallback = _function;
|
||||
m_constraintParam = _param;
|
||||
return true;
|
||||
}
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
|
||||
virtual const e_vector &getControlOutput() const
|
||||
{
|
||||
return m_ydot;
|
||||
};
|
||||
virtual const ConstraintValues *getControlParameters(unsigned int *_nvalues) = 0;
|
||||
virtual bool setControlParameters(ConstraintValues *_values,
|
||||
unsigned int _nvalues,
|
||||
double timestep = 0.0) = 0;
|
||||
bool setControlParameter(int id, ConstraintAction action, double value, double timestep = 0.0);
|
||||
virtual bool registerCallback(ConstraintCallback _function, void* _param)
|
||||
{
|
||||
m_constraintCallback = _function;
|
||||
m_constraintParam = _param;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual const e_matrix6 &getJf() const
|
||||
{
|
||||
return m_Jf;
|
||||
};
|
||||
virtual const KDL::Frame &getPose() const
|
||||
{
|
||||
return m_internalPose;
|
||||
};
|
||||
virtual const e_matrix &getCf() const
|
||||
{
|
||||
return m_Cf;
|
||||
};
|
||||
virtual const e_vector& getControlOutput()const{return m_ydot;};
|
||||
virtual const ConstraintValues* getControlParameters(unsigned int* _nvalues) = 0;
|
||||
virtual bool setControlParameters(ConstraintValues* _values, unsigned int _nvalues, double timestep=0.0) = 0;
|
||||
bool setControlParameter(int id, ConstraintAction action, double value, double timestep=0.0);
|
||||
|
||||
virtual const e_vector &getWy() const
|
||||
{
|
||||
return m_Wy;
|
||||
};
|
||||
virtual void setWy(const e_vector &Wy_in)
|
||||
{
|
||||
m_Wy = Wy_in;
|
||||
};
|
||||
virtual void setJointVelocity(const e_vector chidot_in)
|
||||
{
|
||||
m_chidot = chidot_in;
|
||||
};
|
||||
virtual const e_matrix6& getJf() const{return m_Jf;};
|
||||
virtual const KDL::Frame& getPose() const{return m_internalPose;};
|
||||
virtual const e_matrix& getCf() const{return m_Cf;};
|
||||
|
||||
virtual unsigned int getNrOfConstraints()
|
||||
{
|
||||
return m_nc;
|
||||
};
|
||||
void substep(bool _substep)
|
||||
{
|
||||
m_substep = _substep;
|
||||
}
|
||||
bool substep()
|
||||
{
|
||||
return m_substep;
|
||||
}
|
||||
virtual const e_vector& getWy() const {return m_Wy;};
|
||||
virtual void setWy(const e_vector& Wy_in){m_Wy = Wy_in;};
|
||||
virtual void setJointVelocity(const e_vector chidot_in){m_chidot = chidot_in;};
|
||||
|
||||
virtual unsigned int getNrOfConstraints(){return m_nc;};
|
||||
void substep(bool _substep) {m_substep=_substep;}
|
||||
bool substep() {return m_substep;}
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* CONSTRAINTSET_HPP_ */
|
||||
|
||||
@@ -8,51 +8,55 @@
|
||||
|
||||
#include "ControlledObject.hpp"
|
||||
|
||||
|
||||
namespace iTaSC {
|
||||
ControlledObject::ControlledObject() : Object(Controlled), m_nq(0), m_nc(0), m_nee(0)
|
||||
ControlledObject::ControlledObject():
|
||||
Object(Controlled),m_nq(0),m_nc(0),m_nee(0)
|
||||
{
|
||||
// max joint variable = 0.52 radian or 0.52 meter in one timestep
|
||||
m_maxDeltaQ = e_scalar(0.52);
|
||||
// max joint variable = 0.52 radian or 0.52 meter in one timestep
|
||||
m_maxDeltaQ = e_scalar(0.52);
|
||||
}
|
||||
|
||||
void ControlledObject::initialize(unsigned int _nq, unsigned int _nc, unsigned int _nee)
|
||||
void ControlledObject::initialize(unsigned int _nq,unsigned int _nc, unsigned int _nee)
|
||||
{
|
||||
assert(_nee >= 1);
|
||||
m_nq = _nq;
|
||||
m_nc = _nc;
|
||||
m_nee = _nee;
|
||||
if (m_nq > 0) {
|
||||
m_Wq = e_identity_matrix(m_nq, m_nq);
|
||||
m_qdot = e_zero_vector(m_nq);
|
||||
}
|
||||
if (m_nc > 0) {
|
||||
m_Wy = e_scalar_vector(m_nc, 1.0);
|
||||
m_ydot = e_zero_vector(m_nc);
|
||||
}
|
||||
if (m_nc > 0 && m_nq > 0)
|
||||
m_Cq = e_zero_matrix(m_nc, m_nq);
|
||||
// clear all Jacobian if any
|
||||
m_JqArray.clear();
|
||||
// reserve one more to have a zero matrix handy
|
||||
if (m_nq > 0)
|
||||
m_JqArray.resize(m_nee + 1, e_zero_matrix(6, m_nq));
|
||||
assert(_nee >= 1);
|
||||
m_nq = _nq;
|
||||
m_nc = _nc;
|
||||
m_nee = _nee;
|
||||
if (m_nq > 0) {
|
||||
m_Wq = e_identity_matrix(m_nq,m_nq);
|
||||
m_qdot = e_zero_vector(m_nq);
|
||||
}
|
||||
if (m_nc > 0) {
|
||||
m_Wy = e_scalar_vector(m_nc,1.0);
|
||||
m_ydot = e_zero_vector(m_nc);
|
||||
}
|
||||
if (m_nc > 0 && m_nq > 0)
|
||||
m_Cq = e_zero_matrix(m_nc,m_nq);
|
||||
// clear all Jacobian if any
|
||||
m_JqArray.clear();
|
||||
// reserve one more to have a zero matrix handy
|
||||
if (m_nq > 0)
|
||||
m_JqArray.resize(m_nee+1, e_zero_matrix(6,m_nq));
|
||||
}
|
||||
|
||||
ControlledObject::~ControlledObject() {}
|
||||
|
||||
const e_matrix &ControlledObject::getJq(unsigned int ee) const
|
||||
|
||||
|
||||
const e_matrix& ControlledObject::getJq(unsigned int ee) const
|
||||
{
|
||||
assert(m_nq > 0);
|
||||
return m_JqArray[(ee > m_nee) ? m_nee : ee];
|
||||
assert(m_nq > 0);
|
||||
return m_JqArray[(ee>m_nee)?m_nee:ee];
|
||||
}
|
||||
|
||||
double ControlledObject::getMaxTimestep(double ×tep)
|
||||
double ControlledObject::getMaxTimestep(double& timestep)
|
||||
{
|
||||
e_scalar maxQdot = m_qdot.array().abs().maxCoeff();
|
||||
if (timestep * maxQdot > m_maxDeltaQ) {
|
||||
timestep = m_maxDeltaQ / maxQdot;
|
||||
}
|
||||
return timestep;
|
||||
e_scalar maxQdot = m_qdot.array().abs().maxCoeff();
|
||||
if (timestep*maxQdot > m_maxDeltaQ) {
|
||||
timestep = m_maxDeltaQ/maxQdot;
|
||||
}
|
||||
return timestep;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
@@ -9,92 +9,63 @@
|
||||
#ifndef CONTROLLEDOBJECT_HPP_
|
||||
#define CONTROLLEDOBJECT_HPP_
|
||||
|
||||
#include "eigen_types.hpp"
|
||||
#include "kdl/frames.hpp"
|
||||
#include "eigen_types.hpp"
|
||||
|
||||
#include "ConstraintSet.hpp"
|
||||
#include "Object.hpp"
|
||||
#include "ConstraintSet.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
#define CONSTRAINT_ID_ALL ((unsigned int)-1)
|
||||
#define CONSTRAINT_ID_ALL ((unsigned int)-1)
|
||||
|
||||
class ControlledObject : public Object {
|
||||
protected:
|
||||
e_scalar m_maxDeltaQ;
|
||||
unsigned int m_nq, m_nc, m_nee;
|
||||
e_matrix m_Wq, m_Cq;
|
||||
e_vector m_Wy, m_ydot, m_qdot;
|
||||
std::vector<e_matrix> m_JqArray;
|
||||
protected:
|
||||
e_scalar m_maxDeltaQ;
|
||||
unsigned int m_nq,m_nc,m_nee;
|
||||
e_matrix m_Wq,m_Cq;
|
||||
e_vector m_Wy,m_ydot,m_qdot;
|
||||
std::vector<e_matrix> m_JqArray;
|
||||
public:
|
||||
ControlledObject();
|
||||
virtual ~ControlledObject();
|
||||
|
||||
public:
|
||||
ControlledObject();
|
||||
virtual ~ControlledObject();
|
||||
class JointLockCallback {
|
||||
public:
|
||||
JointLockCallback() {}
|
||||
virtual ~JointLockCallback() {}
|
||||
|
||||
class JointLockCallback {
|
||||
public:
|
||||
JointLockCallback() {}
|
||||
virtual ~JointLockCallback() {}
|
||||
// lock a joint, no need to update output
|
||||
virtual void lockJoint(unsigned int q_nr, unsigned int ndof) = 0;
|
||||
// lock a joint and update output in view of reiteration
|
||||
virtual void lockJoint(unsigned int q_nr, unsigned int ndof, double* qdot) = 0;
|
||||
};
|
||||
|
||||
// lock a joint, no need to update output
|
||||
virtual void lockJoint(unsigned int q_nr, unsigned int ndof) = 0;
|
||||
// lock a joint and update output in view of reiteration
|
||||
virtual void lockJoint(unsigned int q_nr, unsigned int ndof, double *qdot) = 0;
|
||||
};
|
||||
virtual void initialize(unsigned int _nq,unsigned int _nc, unsigned int _nee);
|
||||
|
||||
virtual void initialize(unsigned int _nq, unsigned int _nc, unsigned int _nee);
|
||||
// returns true when a joint has been locked via the callback and the solver must run again
|
||||
virtual bool updateJoint(const Timestamp& timestamp, JointLockCallback& callback) = 0;
|
||||
virtual void updateControlOutput(const Timestamp& timestamp)=0;
|
||||
virtual void setJointVelocity(const e_vector qdot_in){m_qdot = qdot_in;};
|
||||
virtual double getMaxTimestep(double& timestep);
|
||||
virtual bool setControlParameter(unsigned int constraintId, unsigned int valueId, ConstraintAction action, e_scalar value, double timestep=0.0)=0;
|
||||
|
||||
// returns true when a joint has been locked via the callback and the solver must run again
|
||||
virtual bool updateJoint(const Timestamp ×tamp, JointLockCallback &callback) = 0;
|
||||
virtual void updateControlOutput(const Timestamp ×tamp) = 0;
|
||||
virtual void setJointVelocity(const e_vector qdot_in)
|
||||
{
|
||||
m_qdot = qdot_in;
|
||||
};
|
||||
virtual double getMaxTimestep(double ×tep);
|
||||
virtual bool setControlParameter(unsigned int constraintId,
|
||||
unsigned int valueId,
|
||||
ConstraintAction action,
|
||||
e_scalar value,
|
||||
double timestep = 0.0) = 0;
|
||||
virtual const e_vector& getControlOutput() const{return m_ydot;}
|
||||
|
||||
virtual const e_vector &getControlOutput() const
|
||||
{
|
||||
return m_ydot;
|
||||
}
|
||||
virtual const e_matrix& getJq(unsigned int ee) const;
|
||||
|
||||
virtual const e_matrix &getJq(unsigned int ee) const;
|
||||
virtual const e_matrix& getCq() const{return m_Cq;};
|
||||
|
||||
virtual const e_matrix &getCq() const
|
||||
{
|
||||
return m_Cq;
|
||||
};
|
||||
virtual e_matrix& getWq() {return m_Wq;};
|
||||
virtual void setWq(const e_matrix& Wq_in){m_Wq = Wq_in;};
|
||||
|
||||
virtual e_matrix &getWq()
|
||||
{
|
||||
return m_Wq;
|
||||
};
|
||||
virtual void setWq(const e_matrix &Wq_in)
|
||||
{
|
||||
m_Wq = Wq_in;
|
||||
};
|
||||
virtual const e_vector& getWy() const {return m_Wy;};
|
||||
|
||||
virtual const e_vector &getWy() const
|
||||
{
|
||||
return m_Wy;
|
||||
};
|
||||
|
||||
virtual const unsigned int getNrOfCoordinates()
|
||||
{
|
||||
return m_nq;
|
||||
};
|
||||
virtual const unsigned int getNrOfConstraints()
|
||||
{
|
||||
return m_nc;
|
||||
};
|
||||
virtual const unsigned int getNrOfCoordinates(){return m_nq;};
|
||||
virtual const unsigned int getNrOfConstraints(){return m_nc;};
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* CONTROLLEDOBJECT_HPP_ */
|
||||
|
||||
@@ -11,500 +11,471 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
const unsigned int maxPoseCacheSize = (2 * (3 + 3 * 2));
|
||||
CopyPose::CopyPose(unsigned int control_output,
|
||||
unsigned int dynamic_output,
|
||||
double armlength,
|
||||
double accuracy,
|
||||
unsigned int maximum_iterations)
|
||||
: ConstraintSet(), m_cache(NULL), m_poseCCh(-1), m_poseCTs(0)
|
||||
namespace iTaSC
|
||||
{
|
||||
m_maxerror = armlength / 2.0;
|
||||
m_outputControl = (control_output & CTL_ALL);
|
||||
unsigned int _nc = nBitsOn(m_outputControl);
|
||||
if (!_nc)
|
||||
return;
|
||||
// reset the constraint set
|
||||
reset(_nc, accuracy, maximum_iterations);
|
||||
_nc = 0;
|
||||
m_nvalues = 0;
|
||||
int nrot = 0, npos = 0;
|
||||
int nposCache = 0, nrotCache = 0;
|
||||
m_outputDynamic = (dynamic_output & m_outputControl);
|
||||
memset(m_values, 0, sizeof(m_values));
|
||||
memset(m_posData, 0, sizeof(m_posData));
|
||||
memset(m_rotData, 0, sizeof(m_rotData));
|
||||
memset(&m_rot, 0, sizeof(m_rot));
|
||||
memset(&m_pos, 0, sizeof(m_pos));
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
m_pos.alpha = 1.0;
|
||||
m_pos.K = 20.0;
|
||||
m_pos.tolerance = 0.05;
|
||||
m_values[m_nvalues].alpha = m_pos.alpha;
|
||||
m_values[m_nvalues].feedback = m_pos.K;
|
||||
m_values[m_nvalues].tolerance = m_pos.tolerance;
|
||||
m_values[m_nvalues].id = ID_POSITION;
|
||||
if (m_outputControl & CTL_POSITIONX) {
|
||||
m_Wy(_nc) = m_pos.alpha /*/(m_pos.tolerance*m_pos.K)*/;
|
||||
m_Cf(_nc++, 0) = 1.0;
|
||||
m_posData[npos++].id = ID_POSITIONX;
|
||||
if (m_outputDynamic & CTL_POSITIONX)
|
||||
nposCache++;
|
||||
}
|
||||
if (m_outputControl & CTL_POSITIONY) {
|
||||
m_Wy(_nc) = m_pos.alpha /*/(m_pos.tolerance*m_pos.K)*/;
|
||||
m_Cf(_nc++, 1) = 1.0;
|
||||
m_posData[npos++].id = ID_POSITIONY;
|
||||
if (m_outputDynamic & CTL_POSITIONY)
|
||||
nposCache++;
|
||||
}
|
||||
if (m_outputControl & CTL_POSITIONZ) {
|
||||
m_Wy(_nc) = m_pos.alpha /*/(m_pos.tolerance*m_pos.K)*/;
|
||||
m_Cf(_nc++, 2) = 1.0;
|
||||
m_posData[npos++].id = ID_POSITIONZ;
|
||||
if (m_outputDynamic & CTL_POSITIONZ)
|
||||
nposCache++;
|
||||
}
|
||||
m_values[m_nvalues].number = npos;
|
||||
m_values[m_nvalues++].values = m_posData;
|
||||
m_pos.firsty = 0;
|
||||
m_pos.ny = npos;
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
m_rot.alpha = 1.0;
|
||||
m_rot.K = 20.0;
|
||||
m_rot.tolerance = 0.05;
|
||||
m_values[m_nvalues].alpha = m_rot.alpha;
|
||||
m_values[m_nvalues].feedback = m_rot.K;
|
||||
m_values[m_nvalues].tolerance = m_rot.tolerance;
|
||||
m_values[m_nvalues].id = ID_ROTATION;
|
||||
if (m_outputControl & CTL_ROTATIONX) {
|
||||
m_Wy(_nc) = m_rot.alpha /*/(m_rot.tolerance*m_rot.K)*/;
|
||||
m_Cf(_nc++, 3) = 1.0;
|
||||
m_rotData[nrot++].id = ID_ROTATIONX;
|
||||
if (m_outputDynamic & CTL_ROTATIONX)
|
||||
nrotCache++;
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATIONY) {
|
||||
m_Wy(_nc) = m_rot.alpha /*/(m_rot.tolerance*m_rot.K)*/;
|
||||
m_Cf(_nc++, 4) = 1.0;
|
||||
m_rotData[nrot++].id = ID_ROTATIONY;
|
||||
if (m_outputDynamic & CTL_ROTATIONY)
|
||||
nrotCache++;
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATIONZ) {
|
||||
m_Wy(_nc) = m_rot.alpha /*/(m_rot.tolerance*m_rot.K)*/;
|
||||
m_Cf(_nc++, 5) = 1.0;
|
||||
m_rotData[nrot++].id = ID_ROTATIONZ;
|
||||
if (m_outputDynamic & CTL_ROTATIONZ)
|
||||
nrotCache++;
|
||||
}
|
||||
m_values[m_nvalues].number = nrot;
|
||||
m_values[m_nvalues++].values = m_rotData;
|
||||
m_rot.firsty = npos;
|
||||
m_rot.ny = nrot;
|
||||
}
|
||||
assert(_nc == m_nc);
|
||||
m_Jf = e_identity_matrix(6, 6);
|
||||
m_poseCacheSize = ((nrotCache) ? (3 + nrotCache * 2) : 0) +
|
||||
((nposCache) ? (3 + nposCache * 2) : 0);
|
||||
|
||||
const unsigned int maxPoseCacheSize = (2*(3+3*2));
|
||||
CopyPose::CopyPose(unsigned int control_output, unsigned int dynamic_output, double armlength, double accuracy, unsigned int maximum_iterations):
|
||||
ConstraintSet(),
|
||||
m_cache(NULL),
|
||||
m_poseCCh(-1),m_poseCTs(0)
|
||||
{
|
||||
m_maxerror = armlength/2.0;
|
||||
m_outputControl = (control_output & CTL_ALL);
|
||||
unsigned int _nc = nBitsOn(m_outputControl);
|
||||
if (!_nc)
|
||||
return;
|
||||
// reset the constraint set
|
||||
reset(_nc, accuracy, maximum_iterations);
|
||||
_nc = 0;
|
||||
m_nvalues = 0;
|
||||
int nrot = 0, npos = 0;
|
||||
int nposCache = 0, nrotCache = 0;
|
||||
m_outputDynamic = (dynamic_output & m_outputControl);
|
||||
memset(m_values, 0, sizeof(m_values));
|
||||
memset(m_posData, 0, sizeof(m_posData));
|
||||
memset(m_rotData, 0, sizeof(m_rotData));
|
||||
memset(&m_rot, 0, sizeof(m_rot));
|
||||
memset(&m_pos, 0, sizeof(m_pos));
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
m_pos.alpha = 1.0;
|
||||
m_pos.K = 20.0;
|
||||
m_pos.tolerance = 0.05;
|
||||
m_values[m_nvalues].alpha = m_pos.alpha;
|
||||
m_values[m_nvalues].feedback = m_pos.K;
|
||||
m_values[m_nvalues].tolerance = m_pos.tolerance;
|
||||
m_values[m_nvalues].id = ID_POSITION;
|
||||
if (m_outputControl & CTL_POSITIONX) {
|
||||
m_Wy(_nc) = m_pos.alpha/*/(m_pos.tolerance*m_pos.K)*/;
|
||||
m_Cf(_nc++,0)=1.0;
|
||||
m_posData[npos++].id = ID_POSITIONX;
|
||||
if (m_outputDynamic & CTL_POSITIONX)
|
||||
nposCache++;
|
||||
}
|
||||
if (m_outputControl & CTL_POSITIONY) {
|
||||
m_Wy(_nc) = m_pos.alpha/*/(m_pos.tolerance*m_pos.K)*/;
|
||||
m_Cf(_nc++,1)=1.0;
|
||||
m_posData[npos++].id = ID_POSITIONY;
|
||||
if (m_outputDynamic & CTL_POSITIONY)
|
||||
nposCache++;
|
||||
}
|
||||
if (m_outputControl & CTL_POSITIONZ) {
|
||||
m_Wy(_nc) = m_pos.alpha/*/(m_pos.tolerance*m_pos.K)*/;
|
||||
m_Cf(_nc++,2)=1.0;
|
||||
m_posData[npos++].id = ID_POSITIONZ;
|
||||
if (m_outputDynamic & CTL_POSITIONZ)
|
||||
nposCache++;
|
||||
}
|
||||
m_values[m_nvalues].number = npos;
|
||||
m_values[m_nvalues++].values = m_posData;
|
||||
m_pos.firsty = 0;
|
||||
m_pos.ny = npos;
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
m_rot.alpha = 1.0;
|
||||
m_rot.K = 20.0;
|
||||
m_rot.tolerance = 0.05;
|
||||
m_values[m_nvalues].alpha = m_rot.alpha;
|
||||
m_values[m_nvalues].feedback = m_rot.K;
|
||||
m_values[m_nvalues].tolerance = m_rot.tolerance;
|
||||
m_values[m_nvalues].id = ID_ROTATION;
|
||||
if (m_outputControl & CTL_ROTATIONX) {
|
||||
m_Wy(_nc) = m_rot.alpha/*/(m_rot.tolerance*m_rot.K)*/;
|
||||
m_Cf(_nc++,3)=1.0;
|
||||
m_rotData[nrot++].id = ID_ROTATIONX;
|
||||
if (m_outputDynamic & CTL_ROTATIONX)
|
||||
nrotCache++;
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATIONY) {
|
||||
m_Wy(_nc) = m_rot.alpha/*/(m_rot.tolerance*m_rot.K)*/;
|
||||
m_Cf(_nc++,4)=1.0;
|
||||
m_rotData[nrot++].id = ID_ROTATIONY;
|
||||
if (m_outputDynamic & CTL_ROTATIONY)
|
||||
nrotCache++;
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATIONZ) {
|
||||
m_Wy(_nc) = m_rot.alpha/*/(m_rot.tolerance*m_rot.K)*/;
|
||||
m_Cf(_nc++,5)=1.0;
|
||||
m_rotData[nrot++].id = ID_ROTATIONZ;
|
||||
if (m_outputDynamic & CTL_ROTATIONZ)
|
||||
nrotCache++;
|
||||
}
|
||||
m_values[m_nvalues].number = nrot;
|
||||
m_values[m_nvalues++].values = m_rotData;
|
||||
m_rot.firsty = npos;
|
||||
m_rot.ny = nrot;
|
||||
}
|
||||
assert(_nc == m_nc);
|
||||
m_Jf=e_identity_matrix(6,6);
|
||||
m_poseCacheSize = ((nrotCache)?(3+nrotCache*2):0)+((nposCache)?(3+nposCache*2):0);
|
||||
}
|
||||
|
||||
CopyPose::~CopyPose() {}
|
||||
|
||||
bool CopyPose::initialise(Frame &init_pose)
|
||||
CopyPose::~CopyPose()
|
||||
{
|
||||
m_externalPose = m_internalPose = init_pose;
|
||||
updateJacobian();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyPose::modelUpdate(Frame &_external_pose, const Timestamp ×tamp)
|
||||
bool CopyPose::initialise(Frame& init_pose)
|
||||
{
|
||||
m_internalPose = m_externalPose = _external_pose;
|
||||
updateJacobian();
|
||||
m_externalPose = m_internalPose = init_pose;
|
||||
updateJacobian();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyPose::modelUpdate(Frame& _external_pose,const Timestamp& timestamp)
|
||||
{
|
||||
m_internalPose = m_externalPose = _external_pose;
|
||||
updateJacobian();
|
||||
}
|
||||
|
||||
void CopyPose::initCache(Cache *_cache)
|
||||
{
|
||||
m_cache = _cache;
|
||||
m_poseCCh = -1;
|
||||
if (m_cache) {
|
||||
// create one channel for the coordinates
|
||||
m_poseCCh = m_cache->addChannel(this, "Xf", m_poseCacheSize * sizeof(double));
|
||||
// don't save initial value, it will be recomputed from external pose
|
||||
// pushPose(0);
|
||||
}
|
||||
m_cache = _cache;
|
||||
m_poseCCh = -1;
|
||||
if (m_cache) {
|
||||
// create one channel for the coordinates
|
||||
m_poseCCh = m_cache->addChannel(this, "Xf", m_poseCacheSize*sizeof(double));
|
||||
// don't save initial value, it will be recomputed from external pose
|
||||
//pushPose(0);
|
||||
}
|
||||
}
|
||||
|
||||
double *CopyPose::pushValues(double *item, ControlState *_state, unsigned int mask)
|
||||
double* CopyPose::pushValues(double* item, ControlState* _state, unsigned int mask)
|
||||
{
|
||||
ControlState::ControlValue *_yval;
|
||||
int i;
|
||||
ControlState::ControlValue* _yval;
|
||||
int i;
|
||||
|
||||
*item++ = _state->alpha;
|
||||
*item++ = _state->K;
|
||||
*item++ = _state->tolerance;
|
||||
*item++ = _state->alpha;
|
||||
*item++ = _state->K;
|
||||
*item++ = _state->tolerance;
|
||||
|
||||
for (i = 0, _yval = _state->output; i < _state->ny; mask <<= 1) {
|
||||
if (m_outputControl & mask) {
|
||||
if (m_outputDynamic & mask) {
|
||||
*item++ = _yval->yd;
|
||||
*item++ = _yval->yddot;
|
||||
}
|
||||
_yval++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
for (i=0, _yval=_state->output; i<_state->ny; mask<<=1) {
|
||||
if (m_outputControl & mask) {
|
||||
if (m_outputDynamic & mask) {
|
||||
*item++ = _yval->yd;
|
||||
*item++ = _yval->yddot;
|
||||
}
|
||||
_yval++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
void CopyPose::pushPose(CacheTS timestamp)
|
||||
{
|
||||
if (m_poseCCh >= 0) {
|
||||
if (m_poseCacheSize) {
|
||||
double buf[maxPoseCacheSize];
|
||||
double *item = buf;
|
||||
if (m_outputDynamic & CTL_POSITION)
|
||||
item = pushValues(item, &m_pos, CTL_POSITIONX);
|
||||
if (m_outputDynamic & CTL_ROTATION)
|
||||
item = pushValues(item, &m_rot, CTL_ROTATIONX);
|
||||
m_cache->addCacheVectorIfDifferent(
|
||||
this, m_poseCCh, timestamp, buf, m_poseCacheSize, KDL::epsilon);
|
||||
if (m_poseCCh >= 0) {
|
||||
if (m_poseCacheSize) {
|
||||
double buf[maxPoseCacheSize];
|
||||
double *item = buf;
|
||||
if (m_outputDynamic & CTL_POSITION)
|
||||
item = pushValues(item, &m_pos, CTL_POSITIONX);
|
||||
if (m_outputDynamic & CTL_ROTATION)
|
||||
item = pushValues(item, &m_rot, CTL_ROTATIONX);
|
||||
m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, buf, m_poseCacheSize, KDL::epsilon);
|
||||
} else
|
||||
m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, NULL, 0, KDL::epsilon);
|
||||
m_poseCTs = timestamp;
|
||||
}
|
||||
else
|
||||
m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, NULL, 0, KDL::epsilon);
|
||||
m_poseCTs = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
double *CopyPose::restoreValues(double *item,
|
||||
ConstraintValues *_values,
|
||||
ControlState *_state,
|
||||
unsigned int mask)
|
||||
double* CopyPose::restoreValues(double* item, ConstraintValues* _values, ControlState* _state, unsigned int mask)
|
||||
{
|
||||
ConstraintSingleValue *_data;
|
||||
ControlState::ControlValue *_yval;
|
||||
int i, j;
|
||||
ConstraintSingleValue* _data;
|
||||
ControlState::ControlValue* _yval;
|
||||
int i, j;
|
||||
|
||||
_values->alpha = _state->alpha = *item++;
|
||||
_values->feedback = _state->K = *item++;
|
||||
_values->tolerance = _state->tolerance = *item++;
|
||||
_values->alpha = _state->alpha = *item++;
|
||||
_values->feedback = _state->K = *item++;
|
||||
_values->tolerance = _state->tolerance = *item++;
|
||||
|
||||
for (i = _state->firsty, j = i + _state->ny, _yval = _state->output, _data = _values->values;
|
||||
i < j;
|
||||
mask <<= 1)
|
||||
{
|
||||
if (m_outputControl & mask) {
|
||||
m_Wy(i) = _state->alpha /*/(_state->tolerance*_state->K)*/;
|
||||
if (m_outputDynamic & mask) {
|
||||
_data->yd = _yval->yd = *item++;
|
||||
_data->yddot = _yval->yddot = *item++;
|
||||
}
|
||||
_data++;
|
||||
_yval++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
for (i=_state->firsty, j=i+_state->ny, _yval=_state->output, _data=_values->values; i<j; mask<<=1) {
|
||||
if (m_outputControl & mask) {
|
||||
m_Wy(i) = _state->alpha/*/(_state->tolerance*_state->K)*/;
|
||||
if (m_outputDynamic & mask) {
|
||||
_data->yd = _yval->yd = *item++;
|
||||
_data->yddot = _yval->yddot = *item++;
|
||||
}
|
||||
_data++;
|
||||
_yval++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
bool CopyPose::popPose(CacheTS timestamp)
|
||||
{
|
||||
bool found = false;
|
||||
if (m_poseCCh >= 0) {
|
||||
double *item = (double *)m_cache->getPreviousCacheItem(this, m_poseCCh, ×tamp);
|
||||
if (item) {
|
||||
found = true;
|
||||
if (timestamp != m_poseCTs) {
|
||||
int i = 0;
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
if (m_outputDynamic & CTL_POSITION) {
|
||||
item = restoreValues(item, &m_values[i], &m_pos, CTL_POSITIONX);
|
||||
}
|
||||
i++;
|
||||
bool found = false;
|
||||
if (m_poseCCh >= 0) {
|
||||
double *item = (double*)m_cache->getPreviousCacheItem(this, m_poseCCh, ×tamp);
|
||||
if (item) {
|
||||
found = true;
|
||||
if (timestamp != m_poseCTs) {
|
||||
int i=0;
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
if (m_outputDynamic & CTL_POSITION) {
|
||||
item = restoreValues(item, &m_values[i], &m_pos, CTL_POSITIONX);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
if (m_outputDynamic & CTL_ROTATION) {
|
||||
item = restoreValues(item, &m_values[i], &m_rot, CTL_ROTATIONX);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
m_poseCTs = timestamp;
|
||||
item = NULL;
|
||||
}
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
if (m_outputDynamic & CTL_ROTATION) {
|
||||
item = restoreValues(item, &m_values[i], &m_rot, CTL_ROTATIONX);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
m_poseCTs = timestamp;
|
||||
item = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
return found;
|
||||
}
|
||||
|
||||
void CopyPose::interpolateOutput(ControlState *_state,
|
||||
unsigned int mask,
|
||||
const Timestamp ×tamp)
|
||||
void CopyPose::interpolateOutput(ControlState* _state, unsigned int mask, const Timestamp& timestamp)
|
||||
{
|
||||
ControlState::ControlValue *_yval;
|
||||
int i;
|
||||
ControlState::ControlValue* _yval;
|
||||
int i;
|
||||
|
||||
for (i = 0, _yval = _state->output; i < _state->ny; mask <<= 1) {
|
||||
if (m_outputControl & mask) {
|
||||
if (m_outputDynamic & mask) {
|
||||
if (timestamp.substep && timestamp.interpolate) {
|
||||
_yval->yd += _yval->yddot * timestamp.realTimestep;
|
||||
}
|
||||
else {
|
||||
_yval->yd = _yval->nextyd;
|
||||
_yval->yddot = _yval->nextyddot;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
_yval++;
|
||||
}
|
||||
}
|
||||
for (i=0, _yval=_state->output; i<_state->ny; mask <<= 1) {
|
||||
if (m_outputControl & mask) {
|
||||
if (m_outputDynamic & mask) {
|
||||
if (timestamp.substep && timestamp.interpolate) {
|
||||
_yval->yd += _yval->yddot*timestamp.realTimestep;
|
||||
} else {
|
||||
_yval->yd = _yval->nextyd;
|
||||
_yval->yddot = _yval->nextyddot;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
_yval++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyPose::pushCache(const Timestamp ×tamp)
|
||||
void CopyPose::pushCache(const Timestamp& timestamp)
|
||||
{
|
||||
if (!timestamp.substep && timestamp.cache) {
|
||||
pushPose(timestamp.cacheTimestamp);
|
||||
}
|
||||
if (!timestamp.substep && timestamp.cache) {
|
||||
pushPose(timestamp.cacheTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
void CopyPose::updateKinematics(const Timestamp ×tamp)
|
||||
void CopyPose::updateKinematics(const Timestamp& timestamp)
|
||||
{
|
||||
if (timestamp.interpolate) {
|
||||
if (m_outputDynamic & CTL_POSITION)
|
||||
interpolateOutput(&m_pos, CTL_POSITIONX, timestamp);
|
||||
if (m_outputDynamic & CTL_ROTATION)
|
||||
interpolateOutput(&m_rot, CTL_ROTATIONX, timestamp);
|
||||
}
|
||||
pushCache(timestamp);
|
||||
if (timestamp.interpolate) {
|
||||
if (m_outputDynamic & CTL_POSITION)
|
||||
interpolateOutput(&m_pos, CTL_POSITIONX, timestamp);
|
||||
if (m_outputDynamic & CTL_ROTATION)
|
||||
interpolateOutput(&m_rot, CTL_ROTATIONX, timestamp);
|
||||
}
|
||||
pushCache(timestamp);
|
||||
}
|
||||
|
||||
void CopyPose::updateJacobian()
|
||||
{
|
||||
// Jacobian is always identity at the start of the constraint chain
|
||||
// instead of going through complicated jacobian operation, implemented direct formula
|
||||
// m_Jf(1,3) = m_internalPose.p.z();
|
||||
// m_Jf(2,3) = -m_internalPose.p.y();
|
||||
// m_Jf(0,4) = -m_internalPose.p.z();
|
||||
// m_Jf(2,4) = m_internalPose.p.x();
|
||||
// m_Jf(0,5) = m_internalPose.p.y();
|
||||
// m_Jf(1,5) = -m_internalPose.p.x();
|
||||
//Jacobian is always identity at the start of the constraint chain
|
||||
//instead of going through complicated jacobian operation, implemented direct formula
|
||||
//m_Jf(1,3) = m_internalPose.p.z();
|
||||
//m_Jf(2,3) = -m_internalPose.p.y();
|
||||
//m_Jf(0,4) = -m_internalPose.p.z();
|
||||
//m_Jf(2,4) = m_internalPose.p.x();
|
||||
//m_Jf(0,5) = m_internalPose.p.y();
|
||||
//m_Jf(1,5) = -m_internalPose.p.x();
|
||||
}
|
||||
|
||||
void CopyPose::updateState(ConstraintValues *_values,
|
||||
ControlState *_state,
|
||||
unsigned int mask,
|
||||
double timestep)
|
||||
void CopyPose::updateState(ConstraintValues* _values, ControlState* _state, unsigned int mask, double timestep)
|
||||
{
|
||||
unsigned int id = (mask == CTL_ROTATIONX) ? ID_ROTATIONX : ID_POSITIONX;
|
||||
ControlState::ControlValue *_yval;
|
||||
ConstraintSingleValue *_data;
|
||||
int i, j, k;
|
||||
int action = 0;
|
||||
unsigned int id = (mask == CTL_ROTATIONX) ? ID_ROTATIONX : ID_POSITIONX;
|
||||
ControlState::ControlValue* _yval;
|
||||
ConstraintSingleValue* _data;
|
||||
int i, j, k;
|
||||
int action = 0;
|
||||
|
||||
if ((_values->action & ACT_ALPHA) && _values->alpha >= 0.0) {
|
||||
_state->alpha = _values->alpha;
|
||||
action |= ACT_ALPHA;
|
||||
}
|
||||
if ((_values->action & ACT_TOLERANCE) && _values->tolerance > KDL::epsilon) {
|
||||
_state->tolerance = _values->tolerance;
|
||||
action |= ACT_TOLERANCE;
|
||||
}
|
||||
if ((_values->action & ACT_FEEDBACK) && _values->feedback > KDL::epsilon) {
|
||||
_state->K = _values->feedback;
|
||||
action |= ACT_FEEDBACK;
|
||||
}
|
||||
for (i = _state->firsty, j = _state->firsty + _state->ny, _yval = _state->output; i < j;
|
||||
mask <<= 1, id++)
|
||||
{
|
||||
if (m_outputControl & mask) {
|
||||
if (action)
|
||||
m_Wy(i) = _state->alpha /*/(_state->tolerance*_state->K)*/;
|
||||
// check if this controlled output is provided
|
||||
for (k = 0, _data = _values->values; k < _values->number; k++, _data++) {
|
||||
if (_data->id == id) {
|
||||
switch (_data->action & (ACT_VALUE | ACT_VELOCITY)) {
|
||||
case 0:
|
||||
// no indication, keep current values
|
||||
break;
|
||||
case ACT_VELOCITY:
|
||||
// only the velocity is given estimate the new value by integration
|
||||
_data->yd = _yval->yd + _data->yddot * timestep;
|
||||
// walkthrough
|
||||
case ACT_VALUE:
|
||||
_yval->nextyd = _data->yd;
|
||||
// if the user sets the value, we assume future velocity is zero
|
||||
// (until the user changes the value again)
|
||||
_yval->nextyddot = (_data->action & ACT_VALUE) ? 0.0 : _data->yddot;
|
||||
if (timestep > 0.0) {
|
||||
_yval->yddot = (_data->yd - _yval->yd) / timestep;
|
||||
}
|
||||
else {
|
||||
// allow the user to change target instantenously when this function
|
||||
// if called from setControlParameter with timestep = 0
|
||||
_yval->yd = _yval->nextyd;
|
||||
_yval->yddot = _yval->nextyddot;
|
||||
}
|
||||
break;
|
||||
case (ACT_VALUE | ACT_VELOCITY):
|
||||
// the user should not set the value and velocity at the same time.
|
||||
// In this case, we will assume that he wants to set the future value
|
||||
// and we compute the current value to match the velocity
|
||||
_yval->yd = _data->yd - _data->yddot * timestep;
|
||||
_yval->nextyd = _data->yd;
|
||||
_yval->nextyddot = _data->yddot;
|
||||
if (timestep > 0.0) {
|
||||
_yval->yddot = (_data->yd - _yval->yd) / timestep;
|
||||
}
|
||||
else {
|
||||
_yval->yd = _yval->nextyd;
|
||||
_yval->yddot = _yval->nextyddot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_yval++;
|
||||
i++;
|
||||
if ((_values->action & ACT_ALPHA) && _values->alpha >= 0.0) {
|
||||
_state->alpha = _values->alpha;
|
||||
action |= ACT_ALPHA;
|
||||
}
|
||||
}
|
||||
if ((_values->action & ACT_TOLERANCE) && _values->tolerance > KDL::epsilon) {
|
||||
_state->tolerance = _values->tolerance;
|
||||
action |= ACT_TOLERANCE;
|
||||
}
|
||||
if ((_values->action & ACT_FEEDBACK) && _values->feedback > KDL::epsilon) {
|
||||
_state->K = _values->feedback;
|
||||
action |= ACT_FEEDBACK;
|
||||
}
|
||||
for (i=_state->firsty, j=_state->firsty+_state->ny, _yval=_state->output; i<j; mask <<= 1, id++) {
|
||||
if (m_outputControl & mask) {
|
||||
if (action)
|
||||
m_Wy(i) = _state->alpha/*/(_state->tolerance*_state->K)*/;
|
||||
// check if this controlled output is provided
|
||||
for (k=0, _data=_values->values; k<_values->number; k++, _data++) {
|
||||
if (_data->id == id) {
|
||||
switch (_data->action & (ACT_VALUE|ACT_VELOCITY)) {
|
||||
case 0:
|
||||
// no indication, keep current values
|
||||
break;
|
||||
case ACT_VELOCITY:
|
||||
// only the velocity is given estimate the new value by integration
|
||||
_data->yd = _yval->yd+_data->yddot*timestep;
|
||||
// walkthrough
|
||||
case ACT_VALUE:
|
||||
_yval->nextyd = _data->yd;
|
||||
// if the user sets the value, we assume future velocity is zero
|
||||
// (until the user changes the value again)
|
||||
_yval->nextyddot = (_data->action & ACT_VALUE) ? 0.0 : _data->yddot;
|
||||
if (timestep>0.0) {
|
||||
_yval->yddot = (_data->yd-_yval->yd)/timestep;
|
||||
} else {
|
||||
// allow the user to change target instantenously when this function
|
||||
// if called from setControlParameter with timestep = 0
|
||||
_yval->yd = _yval->nextyd;
|
||||
_yval->yddot = _yval->nextyddot;
|
||||
}
|
||||
break;
|
||||
case (ACT_VALUE|ACT_VELOCITY):
|
||||
// the user should not set the value and velocity at the same time.
|
||||
// In this case, we will assume that he wants to set the future value
|
||||
// and we compute the current value to match the velocity
|
||||
_yval->yd = _data->yd - _data->yddot*timestep;
|
||||
_yval->nextyd = _data->yd;
|
||||
_yval->nextyddot = _data->yddot;
|
||||
if (timestep>0.0) {
|
||||
_yval->yddot = (_data->yd-_yval->yd)/timestep;
|
||||
} else {
|
||||
_yval->yd = _yval->nextyd;
|
||||
_yval->yddot = _yval->nextyddot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
_yval++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CopyPose::setControlParameters(struct ConstraintValues *_values,
|
||||
unsigned int _nvalues,
|
||||
double timestep)
|
||||
|
||||
bool CopyPose::setControlParameters(struct ConstraintValues* _values, unsigned int _nvalues, double timestep)
|
||||
{
|
||||
while (_nvalues > 0) {
|
||||
if (_values->id >= ID_POSITION && _values->id <= ID_POSITIONZ &&
|
||||
(m_outputControl & CTL_POSITION))
|
||||
{
|
||||
updateState(_values, &m_pos, CTL_POSITIONX, timestep);
|
||||
}
|
||||
if (_values->id >= ID_ROTATION && _values->id <= ID_ROTATIONZ &&
|
||||
(m_outputControl & CTL_ROTATION))
|
||||
{
|
||||
updateState(_values, &m_rot, CTL_ROTATIONX, timestep);
|
||||
}
|
||||
_values++;
|
||||
_nvalues--;
|
||||
}
|
||||
return true;
|
||||
while (_nvalues > 0) {
|
||||
if (_values->id >= ID_POSITION && _values->id <= ID_POSITIONZ && (m_outputControl & CTL_POSITION)) {
|
||||
updateState(_values, &m_pos, CTL_POSITIONX, timestep);
|
||||
}
|
||||
if (_values->id >= ID_ROTATION && _values->id <= ID_ROTATIONZ && (m_outputControl & CTL_ROTATION)) {
|
||||
updateState(_values, &m_rot, CTL_ROTATIONX, timestep);
|
||||
}
|
||||
_values++;
|
||||
_nvalues--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CopyPose::updateValues(Vector &vel,
|
||||
ConstraintValues *_values,
|
||||
ControlState *_state,
|
||||
unsigned int mask)
|
||||
void CopyPose::updateValues(Vector& vel, ConstraintValues* _values, ControlState* _state, unsigned int mask)
|
||||
{
|
||||
ConstraintSingleValue *_data;
|
||||
ControlState::ControlValue *_yval;
|
||||
int i, j;
|
||||
ConstraintSingleValue* _data;
|
||||
ControlState::ControlValue* _yval;
|
||||
int i, j;
|
||||
|
||||
_values->action = 0;
|
||||
_values->action = 0;
|
||||
|
||||
for (i = _state->firsty, j = 0, _yval = _state->output, _data = _values->values; j < 3;
|
||||
j++, mask <<= 1)
|
||||
{
|
||||
if (m_outputControl & mask) {
|
||||
*(double *)&_data->y = vel(j);
|
||||
*(double *)&_data->ydot = m_ydot(i);
|
||||
_data->yd = _yval->yd;
|
||||
_data->yddot = _yval->yddot;
|
||||
_data->action = 0;
|
||||
i++;
|
||||
_data++;
|
||||
_yval++;
|
||||
}
|
||||
}
|
||||
for (i=_state->firsty, j=0, _yval=_state->output, _data=_values->values; j<3; j++, mask<<=1) {
|
||||
if (m_outputControl & mask) {
|
||||
*(double*)&_data->y = vel(j);
|
||||
*(double*)&_data->ydot = m_ydot(i);
|
||||
_data->yd = _yval->yd;
|
||||
_data->yddot = _yval->yddot;
|
||||
_data->action = 0;
|
||||
i++;
|
||||
_data++;
|
||||
_yval++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyPose::updateOutput(Vector &vel, ControlState *_state, unsigned int mask)
|
||||
void CopyPose::updateOutput(Vector& vel, ControlState* _state, unsigned int mask)
|
||||
{
|
||||
ControlState::ControlValue *_yval;
|
||||
int i, j;
|
||||
double coef = 1.0;
|
||||
if (mask & CTL_POSITION) {
|
||||
// put a limit on position error
|
||||
double len = 0.0;
|
||||
for (j = 0, _yval = _state->output; j < 3; j++) {
|
||||
if (m_outputControl & (mask << j)) {
|
||||
len += KDL::sqr(_yval->yd - vel(j));
|
||||
_yval++;
|
||||
}
|
||||
}
|
||||
len = KDL::sqrt(len);
|
||||
if (len > m_maxerror)
|
||||
coef = m_maxerror / len;
|
||||
}
|
||||
for (i = _state->firsty, j = 0, _yval = _state->output; j < 3; j++) {
|
||||
if (m_outputControl & (mask << j)) {
|
||||
m_ydot(i) = _yval->yddot + _state->K * coef * (_yval->yd - vel(j));
|
||||
_yval++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
ControlState::ControlValue* _yval;
|
||||
int i, j;
|
||||
double coef=1.0;
|
||||
if (mask & CTL_POSITION) {
|
||||
// put a limit on position error
|
||||
double len=0.0;
|
||||
for (j=0, _yval=_state->output; j<3; j++) {
|
||||
if (m_outputControl & (mask<<j)) {
|
||||
len += KDL::sqr(_yval->yd-vel(j));
|
||||
_yval++;
|
||||
}
|
||||
}
|
||||
len = KDL::sqrt(len);
|
||||
if (len > m_maxerror)
|
||||
coef = m_maxerror/len;
|
||||
}
|
||||
for (i=_state->firsty, j=0, _yval=_state->output; j<3; j++) {
|
||||
if (m_outputControl & (mask<<j)) {
|
||||
m_ydot(i)=_yval->yddot+_state->K*coef*(_yval->yd-vel(j));
|
||||
_yval++;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CopyPose::updateControlOutput(const Timestamp ×tamp)
|
||||
void CopyPose::updateControlOutput(const Timestamp& timestamp)
|
||||
{
|
||||
// IMO this should be done, no idea if it is enough (wrt Distance impl)
|
||||
Twist y = diff(F_identity, m_internalPose);
|
||||
bool found = true;
|
||||
if (!timestamp.substep) {
|
||||
if (!timestamp.reiterate) {
|
||||
found = popPose(timestamp.cacheTimestamp);
|
||||
}
|
||||
}
|
||||
if (m_constraintCallback && (m_substep || (!timestamp.reiterate && !timestamp.substep))) {
|
||||
// initialize first callback the application to get the current values
|
||||
int i = 0;
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
updateValues(y.vel, &m_values[i++], &m_pos, CTL_POSITIONX);
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
updateValues(y.rot, &m_values[i++], &m_rot, CTL_ROTATIONX);
|
||||
}
|
||||
if ((*m_constraintCallback)(timestamp, m_values, m_nvalues, m_constraintParam)) {
|
||||
setControlParameters(
|
||||
m_values, m_nvalues, (found && timestamp.interpolate) ? timestamp.realTimestep : 0.0);
|
||||
}
|
||||
}
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
updateOutput(y.vel, &m_pos, CTL_POSITIONX);
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
updateOutput(y.rot, &m_rot, CTL_ROTATIONX);
|
||||
}
|
||||
//IMO this should be done, no idea if it is enough (wrt Distance impl)
|
||||
Twist y = diff(F_identity, m_internalPose);
|
||||
bool found = true;
|
||||
if (!timestamp.substep) {
|
||||
if (!timestamp.reiterate) {
|
||||
found = popPose(timestamp.cacheTimestamp);
|
||||
}
|
||||
}
|
||||
if (m_constraintCallback && (m_substep || (!timestamp.reiterate && !timestamp.substep))) {
|
||||
// initialize first callback the application to get the current values
|
||||
int i=0;
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
updateValues(y.vel, &m_values[i++], &m_pos, CTL_POSITIONX);
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
updateValues(y.rot, &m_values[i++], &m_rot, CTL_ROTATIONX);
|
||||
}
|
||||
if ((*m_constraintCallback)(timestamp, m_values, m_nvalues, m_constraintParam)) {
|
||||
setControlParameters(m_values, m_nvalues, (found && timestamp.interpolate)?timestamp.realTimestep:0.0);
|
||||
}
|
||||
}
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
updateOutput(y.vel, &m_pos, CTL_POSITIONX);
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
updateOutput(y.rot, &m_rot, CTL_ROTATIONX);
|
||||
}
|
||||
}
|
||||
|
||||
const ConstraintValues *CopyPose::getControlParameters(unsigned int *_nvalues)
|
||||
const ConstraintValues* CopyPose::getControlParameters(unsigned int* _nvalues)
|
||||
{
|
||||
Twist y = diff(m_internalPose, F_identity);
|
||||
int i = 0;
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
updateValues(y.vel, &m_values[i++], &m_pos, CTL_POSITIONX);
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
updateValues(y.rot, &m_values[i++], &m_rot, CTL_ROTATIONX);
|
||||
}
|
||||
if (_nvalues)
|
||||
*_nvalues = m_nvalues;
|
||||
return m_values;
|
||||
Twist y = diff(m_internalPose,F_identity);
|
||||
int i=0;
|
||||
if (m_outputControl & CTL_POSITION) {
|
||||
updateValues(y.vel, &m_values[i++], &m_pos, CTL_POSITIONX);
|
||||
}
|
||||
if (m_outputControl & CTL_ROTATION) {
|
||||
updateValues(y.rot, &m_values[i++], &m_rot, CTL_ROTATIONX);
|
||||
}
|
||||
if (_nvalues)
|
||||
*_nvalues=m_nvalues;
|
||||
return m_values;
|
||||
}
|
||||
|
||||
double CopyPose::getMaxTimestep(double ×tep)
|
||||
double CopyPose::getMaxTimestep(double& timestep)
|
||||
{
|
||||
// CopyPose should not have any limit on linear velocity:
|
||||
// in case the target is out of reach, this can be very high.
|
||||
// We will simply limit on rotation
|
||||
e_scalar maxChidot = m_chidot.block(3, 0, 3, 1).array().abs().maxCoeff();
|
||||
if (timestep * maxChidot > m_maxDeltaChi) {
|
||||
timestep = m_maxDeltaChi / maxChidot;
|
||||
}
|
||||
return timestep;
|
||||
// CopyPose should not have any limit on linear velocity:
|
||||
// in case the target is out of reach, this can be very high.
|
||||
// We will simply limit on rotation
|
||||
e_scalar maxChidot = m_chidot.block(3,0,3,1).array().abs().maxCoeff();
|
||||
if (timestep*maxChidot > m_maxDeltaChi) {
|
||||
timestep = m_maxDeltaChi/maxChidot;
|
||||
}
|
||||
return timestep;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
@@ -10,114 +10,91 @@
|
||||
#define COPYPOSE_H_
|
||||
|
||||
#include "ConstraintSet.hpp"
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
using namespace KDL;
|
||||
|
||||
class CopyPose : public iTaSC::ConstraintSet {
|
||||
protected:
|
||||
virtual void updateKinematics(const Timestamp ×tamp);
|
||||
virtual void pushCache(const Timestamp ×tamp);
|
||||
virtual void updateJacobian();
|
||||
virtual bool initialise(Frame &init_pose);
|
||||
virtual void initCache(Cache *_cache);
|
||||
virtual void updateControlOutput(const Timestamp ×tamp);
|
||||
virtual void modelUpdate(Frame &_external_pose, const Timestamp ×tamp);
|
||||
virtual double getMaxTimestep(double ×tep);
|
||||
class CopyPose: public iTaSC::ConstraintSet
|
||||
{
|
||||
protected:
|
||||
virtual void updateKinematics(const Timestamp& timestamp);
|
||||
virtual void pushCache(const Timestamp& timestamp);
|
||||
virtual void updateJacobian();
|
||||
virtual bool initialise(Frame& init_pose);
|
||||
virtual void initCache(Cache *_cache);
|
||||
virtual void updateControlOutput(const Timestamp& timestamp);
|
||||
virtual void modelUpdate(Frame& _external_pose,const Timestamp& timestamp);
|
||||
virtual double getMaxTimestep(double& timestep);
|
||||
|
||||
public:
|
||||
enum ID { // constraint ID in callback and setControlParameter
|
||||
ID_POSITION = 0,
|
||||
ID_POSITIONX = 1,
|
||||
ID_POSITIONY = 2,
|
||||
ID_POSITIONZ = 3,
|
||||
ID_ROTATION = 4,
|
||||
ID_ROTATIONX = 5,
|
||||
ID_ROTATIONY = 6,
|
||||
ID_ROTATIONZ = 7,
|
||||
};
|
||||
enum CTL { // control ID in constructor to specify which output is constrainted
|
||||
CTL_NONE = 0x00,
|
||||
CTL_POSITIONX = 0x01, // the bit order is important: it matches the y output order
|
||||
CTL_POSITIONY = 0x02,
|
||||
CTL_POSITIONZ = 0x04,
|
||||
CTL_POSITION = 0x07,
|
||||
CTL_ROTATIONX = 0x08,
|
||||
CTL_ROTATIONY = 0x10,
|
||||
CTL_ROTATIONZ = 0x20,
|
||||
CTL_ROTATION = 0x38,
|
||||
CTL_ALL = 0x3F,
|
||||
};
|
||||
public:
|
||||
enum ID { // constraint ID in callback and setControlParameter
|
||||
ID_POSITION=0,
|
||||
ID_POSITIONX=1,
|
||||
ID_POSITIONY=2,
|
||||
ID_POSITIONZ=3,
|
||||
ID_ROTATION=4,
|
||||
ID_ROTATIONX=5,
|
||||
ID_ROTATIONY=6,
|
||||
ID_ROTATIONZ=7,
|
||||
};
|
||||
enum CTL { // control ID in constructor to specify which output is constrainted
|
||||
CTL_NONE=0x00,
|
||||
CTL_POSITIONX=0x01, // the bit order is important: it matches the y output order
|
||||
CTL_POSITIONY=0x02,
|
||||
CTL_POSITIONZ=0x04,
|
||||
CTL_POSITION=0x07,
|
||||
CTL_ROTATIONX=0x08,
|
||||
CTL_ROTATIONY=0x10,
|
||||
CTL_ROTATIONZ=0x20,
|
||||
CTL_ROTATION=0x38,
|
||||
CTL_ALL=0x3F,
|
||||
};
|
||||
|
||||
// use a combination of CTL_.. in control_output to specify which
|
||||
CopyPose(unsigned int control_output = CTL_ALL,
|
||||
unsigned int dynamic_output = CTL_NONE,
|
||||
double armlength = 1.0,
|
||||
double accuracy = 1e-6,
|
||||
unsigned int maximum_iterations = 100);
|
||||
virtual ~CopyPose();
|
||||
// use a combination of CTL_.. in control_output to specify which
|
||||
CopyPose(unsigned int control_output=CTL_ALL, unsigned int dynamic_output=CTL_NONE, double armlength=1.0, double accuracy=1e-6, unsigned int maximum_iterations=100);
|
||||
virtual ~CopyPose();
|
||||
|
||||
virtual bool setControlParameters(struct ConstraintValues *_values,
|
||||
unsigned int _nvalues,
|
||||
double timestep);
|
||||
virtual const ConstraintValues *getControlParameters(unsigned int *_nvalues);
|
||||
virtual bool setControlParameters(struct ConstraintValues* _values, unsigned int _nvalues, double timestep);
|
||||
virtual const ConstraintValues* getControlParameters(unsigned int* _nvalues);
|
||||
|
||||
private:
|
||||
struct ConstraintSingleValue m_posData[3]; // index = controlled output in X,Y,Z order
|
||||
struct ConstraintSingleValue m_rotData[3];
|
||||
struct ConstraintValues
|
||||
m_values[2]; // index = group of controlled output, in position, rotation order
|
||||
Cache *m_cache;
|
||||
int m_poseCCh;
|
||||
CacheTS m_poseCTs;
|
||||
unsigned int m_poseCacheSize;
|
||||
unsigned int m_outputDynamic; // combination of CTL_... determine which variables are
|
||||
// dynamically controlled by the application
|
||||
unsigned int m_outputControl; // combination of CTL_... determine which output are constrained
|
||||
unsigned int m_nvalues; // number of elements used in m_values[]
|
||||
double m_maxerror;
|
||||
private:
|
||||
struct ConstraintSingleValue m_posData[3]; // index = controlled output in X,Y,Z order
|
||||
struct ConstraintSingleValue m_rotData[3];
|
||||
struct ConstraintValues m_values[2]; // index = group of controlled output, in position, rotation order
|
||||
Cache* m_cache;
|
||||
int m_poseCCh;
|
||||
CacheTS m_poseCTs;
|
||||
unsigned int m_poseCacheSize;
|
||||
unsigned int m_outputDynamic; // combination of CTL_... determine which variables are dynamically controlled by the application
|
||||
unsigned int m_outputControl; // combination of CTL_... determine which output are constrained
|
||||
unsigned int m_nvalues; // number of elements used in m_values[]
|
||||
double m_maxerror;
|
||||
|
||||
struct ControlState {
|
||||
int firsty; // first y index
|
||||
int ny; // number of y in output
|
||||
double alpha;
|
||||
double K;
|
||||
double tolerance;
|
||||
struct ControlValue {
|
||||
double yddot;
|
||||
double yd;
|
||||
double nextyd;
|
||||
double nextyddot;
|
||||
} output[3]; // inded numbex = same as m_rotData
|
||||
} m_rot, m_pos;
|
||||
struct ControlState {
|
||||
int firsty; // first y index
|
||||
int ny; // number of y in output
|
||||
double alpha;
|
||||
double K;
|
||||
double tolerance;
|
||||
struct ControlValue {
|
||||
double yddot;
|
||||
double yd;
|
||||
double nextyd;
|
||||
double nextyddot;
|
||||
} output[3]; // inded numbex = same as m_rotData
|
||||
} m_rot, m_pos;
|
||||
|
||||
void pushPose(CacheTS timestamp);
|
||||
bool popPose(CacheTS timestamp);
|
||||
int nBitsOn(unsigned int v)
|
||||
{ int n=0; while(v) { if (v&1) n++; v>>=1; } return n; }
|
||||
double* restoreValues(double* item, ConstraintValues* _values, ControlState* _state, unsigned int mask);
|
||||
double* pushValues(double* item, ControlState* _state, unsigned int mask);
|
||||
void updateState(ConstraintValues* _values, ControlState* _state, unsigned int mask, double timestep);
|
||||
void updateValues(Vector& vel, ConstraintValues* _values, ControlState* _state, unsigned int mask);
|
||||
void updateOutput(Vector& vel, ControlState* _state, unsigned int mask);
|
||||
void interpolateOutput(ControlState* _state, unsigned int mask, const Timestamp& timestamp);
|
||||
|
||||
void pushPose(CacheTS timestamp);
|
||||
bool popPose(CacheTS timestamp);
|
||||
int nBitsOn(unsigned int v)
|
||||
{
|
||||
int n = 0;
|
||||
while (v) {
|
||||
if (v & 1)
|
||||
n++;
|
||||
v >>= 1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
double *restoreValues(double *item,
|
||||
ConstraintValues *_values,
|
||||
ControlState *_state,
|
||||
unsigned int mask);
|
||||
double *pushValues(double *item, ControlState *_state, unsigned int mask);
|
||||
void updateState(ConstraintValues *_values,
|
||||
ControlState *_state,
|
||||
unsigned int mask,
|
||||
double timestep);
|
||||
void updateValues(Vector &vel,
|
||||
ConstraintValues *_values,
|
||||
ControlState *_state,
|
||||
unsigned int mask);
|
||||
void updateOutput(Vector &vel, ControlState *_state, unsigned int mask);
|
||||
void interpolateOutput(ControlState *_state, unsigned int mask, const Timestamp ×tamp);
|
||||
};
|
||||
} // namespace iTaSC
|
||||
}
|
||||
#endif /* COPYROTATION_H_ */
|
||||
|
||||
@@ -11,322 +11,312 @@
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace iTaSC {
|
||||
// a distance constraint is characterized by 5 values: alpha, tolerance, K, yd, yddot
|
||||
static const unsigned int distanceCacheSize = sizeof(double) * 5 + sizeof(e_scalar) * 6;
|
||||
|
||||
Distance::Distance(double armlength, double accuracy, unsigned int maximum_iterations)
|
||||
: ConstraintSet(1, accuracy, maximum_iterations),
|
||||
m_chiKdl(6),
|
||||
m_jac(6),
|
||||
m_cache(NULL),
|
||||
m_distCCh(-1),
|
||||
m_distCTs(0)
|
||||
namespace iTaSC
|
||||
{
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotZ)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotX)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::TransY)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotZ)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotY)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotX)));
|
||||
// a distance constraint is characterized by 5 values: alpha, tolerance, K, yd, yddot
|
||||
static const unsigned int distanceCacheSize = sizeof(double)*5 + sizeof(e_scalar)*6;
|
||||
|
||||
m_fksolver = new KDL::ChainFkSolverPos_recursive(m_chain);
|
||||
m_jacsolver = new KDL::ChainJntToJacSolver(m_chain);
|
||||
m_Cf(0, 2) = 1.0;
|
||||
m_alpha = 1.0;
|
||||
m_tolerance = 0.05;
|
||||
m_maxerror = armlength / 2.0;
|
||||
m_K = 20.0;
|
||||
m_Wy(0) = m_alpha /*/(m_tolerance*m_K)*/;
|
||||
m_yddot = m_nextyddot = 0.0;
|
||||
m_yd = m_nextyd = KDL::epsilon;
|
||||
memset(&m_data, 0, sizeof(m_data));
|
||||
// initialize the data with normally fixed values
|
||||
m_data.id = ID_DISTANCE;
|
||||
m_values.id = ID_DISTANCE;
|
||||
m_values.number = 1;
|
||||
m_values.alpha = m_alpha;
|
||||
m_values.feedback = m_K;
|
||||
m_values.tolerance = m_tolerance;
|
||||
m_values.values = &m_data;
|
||||
Distance::Distance(double armlength, double accuracy, unsigned int maximum_iterations):
|
||||
ConstraintSet(1,accuracy,maximum_iterations),
|
||||
m_chiKdl(6),m_jac(6),m_cache(NULL),
|
||||
m_distCCh(-1),m_distCTs(0)
|
||||
{
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotZ)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotX)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::TransY)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotZ)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotY)));
|
||||
m_chain.addSegment(Segment(Joint(Joint::RotX)));
|
||||
|
||||
m_fksolver = new KDL::ChainFkSolverPos_recursive(m_chain);
|
||||
m_jacsolver = new KDL::ChainJntToJacSolver(m_chain);
|
||||
m_Cf(0,2)=1.0;
|
||||
m_alpha = 1.0;
|
||||
m_tolerance = 0.05;
|
||||
m_maxerror = armlength/2.0;
|
||||
m_K = 20.0;
|
||||
m_Wy(0) = m_alpha/*/(m_tolerance*m_K)*/;
|
||||
m_yddot = m_nextyddot = 0.0;
|
||||
m_yd = m_nextyd = KDL::epsilon;
|
||||
memset(&m_data, 0, sizeof(m_data));
|
||||
// initialize the data with normally fixed values
|
||||
m_data.id = ID_DISTANCE;
|
||||
m_values.id = ID_DISTANCE;
|
||||
m_values.number = 1;
|
||||
m_values.alpha = m_alpha;
|
||||
m_values.feedback = m_K;
|
||||
m_values.tolerance = m_tolerance;
|
||||
m_values.values = &m_data;
|
||||
}
|
||||
|
||||
Distance::~Distance()
|
||||
{
|
||||
delete m_fksolver;
|
||||
delete m_jacsolver;
|
||||
delete m_fksolver;
|
||||
delete m_jacsolver;
|
||||
}
|
||||
|
||||
bool Distance::computeChi(Frame &pose)
|
||||
bool Distance::computeChi(Frame& pose)
|
||||
{
|
||||
double dist, alpha, beta, gamma;
|
||||
dist = pose.p.Norm();
|
||||
Rotation basis;
|
||||
if (dist < KDL::epsilon) {
|
||||
// distance is almost 0, no need for initial rotation
|
||||
m_chi(0) = 0.0;
|
||||
m_chi(1) = 0.0;
|
||||
}
|
||||
else {
|
||||
// find the XZ angles that bring the Y axis to point to init_pose.p
|
||||
Vector axis(pose.p / dist);
|
||||
beta = 0.0;
|
||||
if (fabs(axis(2)) > 1 - KDL::epsilon) {
|
||||
// direction is aligned on Z axis, just rotation on X
|
||||
alpha = 0.0;
|
||||
gamma = KDL::sign(axis(2)) * KDL::PI / 2;
|
||||
}
|
||||
else {
|
||||
alpha = -KDL::atan2(axis(0), axis(1));
|
||||
gamma = KDL::atan2(axis(2), KDL::sqrt(KDL::sqr(axis(0)) + KDL::sqr(axis(1))));
|
||||
}
|
||||
// rotation after first 2 joints
|
||||
basis = Rotation::EulerZYX(alpha, beta, gamma);
|
||||
m_chi(0) = alpha;
|
||||
m_chi(1) = gamma;
|
||||
}
|
||||
m_chi(2) = dist;
|
||||
basis = basis.Inverse() * pose.M;
|
||||
basis.GetEulerZYX(alpha, beta, gamma);
|
||||
// alpha = rotation on Z
|
||||
// beta = rotation on Y
|
||||
// gamma = rotation on X in that order
|
||||
// it corresponds to the joint order, so just assign
|
||||
m_chi(3) = alpha;
|
||||
m_chi(4) = beta;
|
||||
m_chi(5) = gamma;
|
||||
return true;
|
||||
double dist, alpha, beta, gamma;
|
||||
dist = pose.p.Norm();
|
||||
Rotation basis;
|
||||
if (dist < KDL::epsilon) {
|
||||
// distance is almost 0, no need for initial rotation
|
||||
m_chi(0) = 0.0;
|
||||
m_chi(1) = 0.0;
|
||||
} else {
|
||||
// find the XZ angles that bring the Y axis to point to init_pose.p
|
||||
Vector axis(pose.p/dist);
|
||||
beta = 0.0;
|
||||
if (fabs(axis(2)) > 1-KDL::epsilon) {
|
||||
// direction is aligned on Z axis, just rotation on X
|
||||
alpha = 0.0;
|
||||
gamma = KDL::sign(axis(2))*KDL::PI/2;
|
||||
} else {
|
||||
alpha = -KDL::atan2(axis(0), axis(1));
|
||||
gamma = KDL::atan2(axis(2), KDL::sqrt(KDL::sqr(axis(0))+KDL::sqr(axis(1))));
|
||||
}
|
||||
// rotation after first 2 joints
|
||||
basis = Rotation::EulerZYX(alpha, beta, gamma);
|
||||
m_chi(0) = alpha;
|
||||
m_chi(1) = gamma;
|
||||
}
|
||||
m_chi(2) = dist;
|
||||
basis = basis.Inverse()*pose.M;
|
||||
basis.GetEulerZYX(alpha, beta, gamma);
|
||||
// alpha = rotation on Z
|
||||
// beta = rotation on Y
|
||||
// gamma = rotation on X in that order
|
||||
// it corresponds to the joint order, so just assign
|
||||
m_chi(3) = alpha;
|
||||
m_chi(4) = beta;
|
||||
m_chi(5) = gamma;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Distance::initialise(Frame &init_pose)
|
||||
bool Distance::initialise(Frame& init_pose)
|
||||
{
|
||||
// we will initialize m_chi to values that match the pose
|
||||
m_externalPose = init_pose;
|
||||
computeChi(m_externalPose);
|
||||
// get current Jf and update internal pose
|
||||
updateJacobian();
|
||||
return true;
|
||||
// we will initialize m_chi to values that match the pose
|
||||
m_externalPose=init_pose;
|
||||
computeChi(m_externalPose);
|
||||
// get current Jf and update internal pose
|
||||
updateJacobian();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Distance::closeLoop()
|
||||
{
|
||||
if (!Equal(m_internalPose.Inverse() * m_externalPose, F_identity, m_threshold)) {
|
||||
computeChi(m_externalPose);
|
||||
updateJacobian();
|
||||
}
|
||||
return true;
|
||||
if (!Equal(m_internalPose.Inverse()*m_externalPose,F_identity,m_threshold)){
|
||||
computeChi(m_externalPose);
|
||||
updateJacobian();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Distance::initCache(Cache *_cache)
|
||||
{
|
||||
m_cache = _cache;
|
||||
m_distCCh = -1;
|
||||
if (m_cache) {
|
||||
// create one channel for the coordinates
|
||||
m_distCCh = m_cache->addChannel(this, "Xf", distanceCacheSize);
|
||||
// save initial constraint in cache position 0
|
||||
pushDist(0);
|
||||
}
|
||||
m_cache = _cache;
|
||||
m_distCCh = -1;
|
||||
if (m_cache) {
|
||||
// create one channel for the coordinates
|
||||
m_distCCh = m_cache->addChannel(this, "Xf", distanceCacheSize);
|
||||
// save initial constraint in cache position 0
|
||||
pushDist(0);
|
||||
}
|
||||
}
|
||||
|
||||
void Distance::pushDist(CacheTS timestamp)
|
||||
{
|
||||
if (m_distCCh >= 0) {
|
||||
double *item = (double *)m_cache->addCacheItem(
|
||||
this, m_distCCh, timestamp, NULL, distanceCacheSize);
|
||||
if (item) {
|
||||
*item++ = m_K;
|
||||
*item++ = m_tolerance;
|
||||
*item++ = m_yd;
|
||||
*item++ = m_yddot;
|
||||
*item++ = m_alpha;
|
||||
memcpy(item, &m_chi[0], 6 * sizeof(e_scalar));
|
||||
}
|
||||
m_distCTs = timestamp;
|
||||
}
|
||||
if (m_distCCh >= 0) {
|
||||
double *item = (double*)m_cache->addCacheItem(this, m_distCCh, timestamp, NULL, distanceCacheSize);
|
||||
if (item) {
|
||||
*item++ = m_K;
|
||||
*item++ = m_tolerance;
|
||||
*item++ = m_yd;
|
||||
*item++ = m_yddot;
|
||||
*item++ = m_alpha;
|
||||
memcpy(item, &m_chi[0], 6*sizeof(e_scalar));
|
||||
}
|
||||
m_distCTs = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
bool Distance::popDist(CacheTS timestamp)
|
||||
{
|
||||
if (m_distCCh >= 0) {
|
||||
double *item = (double *)m_cache->getPreviousCacheItem(this, m_distCCh, ×tamp);
|
||||
if (item && timestamp != m_distCTs) {
|
||||
m_values.feedback = m_K = *item++;
|
||||
m_values.tolerance = m_tolerance = *item++;
|
||||
m_yd = *item++;
|
||||
m_yddot = *item++;
|
||||
m_values.alpha = m_alpha = *item++;
|
||||
memcpy(&m_chi[0], item, 6 * sizeof(e_scalar));
|
||||
m_distCTs = timestamp;
|
||||
m_Wy(0) = m_alpha /*/(m_tolerance*m_K)*/;
|
||||
updateJacobian();
|
||||
}
|
||||
return (item) ? true : false;
|
||||
}
|
||||
return true;
|
||||
if (m_distCCh >= 0) {
|
||||
double *item = (double*)m_cache->getPreviousCacheItem(this, m_distCCh, ×tamp);
|
||||
if (item && timestamp != m_distCTs) {
|
||||
m_values.feedback = m_K = *item++;
|
||||
m_values.tolerance = m_tolerance = *item++;
|
||||
m_yd = *item++;
|
||||
m_yddot = *item++;
|
||||
m_values.alpha = m_alpha = *item++;
|
||||
memcpy(&m_chi[0], item, 6*sizeof(e_scalar));
|
||||
m_distCTs = timestamp;
|
||||
m_Wy(0) = m_alpha/*/(m_tolerance*m_K)*/;
|
||||
updateJacobian();
|
||||
}
|
||||
return (item) ? true : false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Distance::pushCache(const Timestamp ×tamp)
|
||||
void Distance::pushCache(const Timestamp& timestamp)
|
||||
{
|
||||
if (!timestamp.substep && timestamp.cache)
|
||||
pushDist(timestamp.cacheTimestamp);
|
||||
if (!timestamp.substep && timestamp.cache)
|
||||
pushDist(timestamp.cacheTimestamp);
|
||||
}
|
||||
|
||||
void Distance::updateKinematics(const Timestamp ×tamp)
|
||||
void Distance::updateKinematics(const Timestamp& timestamp)
|
||||
{
|
||||
if (timestamp.interpolate) {
|
||||
// the internal pose and Jf is already up to date (see model_update)
|
||||
// update the desired output based on yddot
|
||||
if (timestamp.substep) {
|
||||
m_yd += m_yddot * timestamp.realTimestep;
|
||||
if (m_yd < KDL::epsilon)
|
||||
m_yd = KDL::epsilon;
|
||||
}
|
||||
else {
|
||||
m_yd = m_nextyd;
|
||||
m_yddot = m_nextyddot;
|
||||
}
|
||||
}
|
||||
pushCache(timestamp);
|
||||
if (timestamp.interpolate) {
|
||||
//the internal pose and Jf is already up to date (see model_update)
|
||||
//update the desired output based on yddot
|
||||
if (timestamp.substep) {
|
||||
m_yd += m_yddot*timestamp.realTimestep;
|
||||
if (m_yd < KDL::epsilon)
|
||||
m_yd = KDL::epsilon;
|
||||
} else {
|
||||
m_yd = m_nextyd;
|
||||
m_yddot = m_nextyddot;
|
||||
}
|
||||
}
|
||||
pushCache(timestamp);
|
||||
}
|
||||
|
||||
void Distance::updateJacobian()
|
||||
{
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
m_chiKdl[i] = m_chi[i];
|
||||
for(unsigned int i=0;i<6;i++)
|
||||
m_chiKdl[i]=m_chi[i];
|
||||
|
||||
m_fksolver->JntToCart(m_chiKdl, m_internalPose);
|
||||
m_jacsolver->JntToJac(m_chiKdl, m_jac);
|
||||
changeRefPoint(m_jac, -m_internalPose.p, m_jac);
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
for (unsigned int j = 0; j < 6; j++)
|
||||
m_Jf(i, j) = m_jac(i, j);
|
||||
m_fksolver->JntToCart(m_chiKdl,m_internalPose);
|
||||
m_jacsolver->JntToJac(m_chiKdl,m_jac);
|
||||
changeRefPoint(m_jac,-m_internalPose.p,m_jac);
|
||||
for(unsigned int i=0;i<6;i++)
|
||||
for(unsigned int j=0;j<6;j++)
|
||||
m_Jf(i,j)=m_jac(i,j);
|
||||
}
|
||||
|
||||
bool Distance::setControlParameters(struct ConstraintValues *_values,
|
||||
unsigned int _nvalues,
|
||||
double timestep)
|
||||
bool Distance::setControlParameters(struct ConstraintValues* _values, unsigned int _nvalues, double timestep)
|
||||
{
|
||||
int action = 0;
|
||||
int i;
|
||||
ConstraintSingleValue *_data;
|
||||
int action = 0;
|
||||
int i;
|
||||
ConstraintSingleValue* _data;
|
||||
|
||||
while (_nvalues > 0) {
|
||||
if (_values->id == ID_DISTANCE) {
|
||||
if ((_values->action & ACT_ALPHA) && _values->alpha >= 0.0) {
|
||||
m_alpha = _values->alpha;
|
||||
action |= ACT_ALPHA;
|
||||
}
|
||||
if ((_values->action & ACT_TOLERANCE) && _values->tolerance > KDL::epsilon) {
|
||||
m_tolerance = _values->tolerance;
|
||||
action |= ACT_TOLERANCE;
|
||||
}
|
||||
if ((_values->action & ACT_FEEDBACK) && _values->feedback > KDL::epsilon) {
|
||||
m_K = _values->feedback;
|
||||
action |= ACT_FEEDBACK;
|
||||
}
|
||||
for (_data = _values->values, i = 0; i < _values->number; i++, _data++) {
|
||||
if (_data->id == ID_DISTANCE) {
|
||||
switch (_data->action & (ACT_VALUE | ACT_VELOCITY)) {
|
||||
case 0:
|
||||
// no indication, keep current values
|
||||
break;
|
||||
case ACT_VELOCITY:
|
||||
// only the velocity is given estimate the new value by integration
|
||||
_data->yd = m_yd + _data->yddot * timestep;
|
||||
// walkthrough for negative value correction
|
||||
case ACT_VALUE:
|
||||
// only the value is given, estimate the velocity from previous value
|
||||
if (_data->yd < KDL::epsilon)
|
||||
_data->yd = KDL::epsilon;
|
||||
m_nextyd = _data->yd;
|
||||
// if the user sets the value, we assume future velocity is zero
|
||||
// (until the user changes the value again)
|
||||
m_nextyddot = (_data->action & ACT_VALUE) ? 0.0 : _data->yddot;
|
||||
if (timestep > 0.0) {
|
||||
m_yddot = (_data->yd - m_yd) / timestep;
|
||||
}
|
||||
else {
|
||||
// allow the user to change target instantenously when this function
|
||||
// if called from setControlParameter with timestep = 0
|
||||
m_yddot = m_nextyddot;
|
||||
m_yd = m_nextyd;
|
||||
}
|
||||
break;
|
||||
case (ACT_VALUE | ACT_VELOCITY):
|
||||
// the user should not set the value and velocity at the same time.
|
||||
// In this case, we will assume that he want to set the future value
|
||||
// and we compute the current value to match the velocity
|
||||
if (_data->yd < KDL::epsilon)
|
||||
_data->yd = KDL::epsilon;
|
||||
m_yd = _data->yd - _data->yddot * timestep;
|
||||
if (m_yd < KDL::epsilon)
|
||||
m_yd = KDL::epsilon;
|
||||
m_nextyd = _data->yd;
|
||||
m_nextyddot = _data->yddot;
|
||||
if (timestep > 0.0) {
|
||||
m_yddot = (_data->yd - m_yd) / timestep;
|
||||
}
|
||||
else {
|
||||
m_yd = m_nextyd;
|
||||
m_yddot = m_nextyddot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_nvalues--;
|
||||
_values++;
|
||||
}
|
||||
if (action & (ACT_TOLERANCE | ACT_FEEDBACK | ACT_ALPHA)) {
|
||||
// recompute the weight
|
||||
m_Wy(0) = m_alpha /*/(m_tolerance*m_K)*/;
|
||||
}
|
||||
return true;
|
||||
while (_nvalues > 0) {
|
||||
if (_values->id == ID_DISTANCE) {
|
||||
if ((_values->action & ACT_ALPHA) && _values->alpha >= 0.0) {
|
||||
m_alpha = _values->alpha;
|
||||
action |= ACT_ALPHA;
|
||||
}
|
||||
if ((_values->action & ACT_TOLERANCE) && _values->tolerance > KDL::epsilon) {
|
||||
m_tolerance = _values->tolerance;
|
||||
action |= ACT_TOLERANCE;
|
||||
}
|
||||
if ((_values->action & ACT_FEEDBACK) && _values->feedback > KDL::epsilon) {
|
||||
m_K = _values->feedback;
|
||||
action |= ACT_FEEDBACK;
|
||||
}
|
||||
for (_data = _values->values, i=0; i<_values->number; i++, _data++) {
|
||||
if (_data->id == ID_DISTANCE) {
|
||||
switch (_data->action & (ACT_VALUE|ACT_VELOCITY)) {
|
||||
case 0:
|
||||
// no indication, keep current values
|
||||
break;
|
||||
case ACT_VELOCITY:
|
||||
// only the velocity is given estimate the new value by integration
|
||||
_data->yd = m_yd+_data->yddot*timestep;
|
||||
// walkthrough for negative value correction
|
||||
case ACT_VALUE:
|
||||
// only the value is given, estimate the velocity from previous value
|
||||
if (_data->yd < KDL::epsilon)
|
||||
_data->yd = KDL::epsilon;
|
||||
m_nextyd = _data->yd;
|
||||
// if the user sets the value, we assume future velocity is zero
|
||||
// (until the user changes the value again)
|
||||
m_nextyddot = (_data->action & ACT_VALUE) ? 0.0 : _data->yddot;
|
||||
if (timestep>0.0) {
|
||||
m_yddot = (_data->yd-m_yd)/timestep;
|
||||
} else {
|
||||
// allow the user to change target instantenously when this function
|
||||
// if called from setControlParameter with timestep = 0
|
||||
m_yddot = m_nextyddot;
|
||||
m_yd = m_nextyd;
|
||||
}
|
||||
break;
|
||||
case (ACT_VALUE|ACT_VELOCITY):
|
||||
// the user should not set the value and velocity at the same time.
|
||||
// In this case, we will assume that he want to set the future value
|
||||
// and we compute the current value to match the velocity
|
||||
if (_data->yd < KDL::epsilon)
|
||||
_data->yd = KDL::epsilon;
|
||||
m_yd = _data->yd - _data->yddot*timestep;
|
||||
if (m_yd < KDL::epsilon)
|
||||
m_yd = KDL::epsilon;
|
||||
m_nextyd = _data->yd;
|
||||
m_nextyddot = _data->yddot;
|
||||
if (timestep>0.0) {
|
||||
m_yddot = (_data->yd-m_yd)/timestep;
|
||||
} else {
|
||||
m_yd = m_nextyd;
|
||||
m_yddot = m_nextyddot;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_nvalues--;
|
||||
_values++;
|
||||
}
|
||||
if (action & (ACT_TOLERANCE|ACT_FEEDBACK|ACT_ALPHA)) {
|
||||
// recompute the weight
|
||||
m_Wy(0) = m_alpha/*/(m_tolerance*m_K)*/;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const ConstraintValues *Distance::getControlParameters(unsigned int *_nvalues)
|
||||
const ConstraintValues* Distance::getControlParameters(unsigned int* _nvalues)
|
||||
{
|
||||
*(double *)&m_data.y = m_chi(2);
|
||||
*(double *)&m_data.ydot = m_ydot(0);
|
||||
m_data.yd = m_yd;
|
||||
m_data.yddot = m_yddot;
|
||||
m_data.action = 0;
|
||||
m_values.action = 0;
|
||||
if (_nvalues)
|
||||
*_nvalues = 1;
|
||||
return &m_values;
|
||||
*(double*)&m_data.y = m_chi(2);
|
||||
*(double*)&m_data.ydot = m_ydot(0);
|
||||
m_data.yd = m_yd;
|
||||
m_data.yddot = m_yddot;
|
||||
m_data.action = 0;
|
||||
m_values.action = 0;
|
||||
if (_nvalues)
|
||||
*_nvalues=1;
|
||||
return &m_values;
|
||||
}
|
||||
|
||||
void Distance::updateControlOutput(const Timestamp ×tamp)
|
||||
void Distance::updateControlOutput(const Timestamp& timestamp)
|
||||
{
|
||||
bool cacheAvail = true;
|
||||
if (!timestamp.substep) {
|
||||
if (!timestamp.reiterate)
|
||||
cacheAvail = popDist(timestamp.cacheTimestamp);
|
||||
}
|
||||
if (m_constraintCallback && (m_substep || (!timestamp.reiterate && !timestamp.substep))) {
|
||||
// initialize first callback the application to get the current values
|
||||
*(double *)&m_data.y = m_chi(2);
|
||||
*(double *)&m_data.ydot = m_ydot(0);
|
||||
m_data.yd = m_yd;
|
||||
m_data.yddot = m_yddot;
|
||||
m_data.action = 0;
|
||||
m_values.action = 0;
|
||||
if ((*m_constraintCallback)(timestamp, &m_values, 1, m_constraintParam)) {
|
||||
setControlParameters(&m_values, 1, timestamp.realTimestep);
|
||||
}
|
||||
}
|
||||
if (!cacheAvail || !timestamp.interpolate) {
|
||||
// first position in cache: set the desired output immediately as we cannot interpolate
|
||||
m_yd = m_nextyd;
|
||||
m_yddot = m_nextyddot;
|
||||
}
|
||||
double error = m_yd - m_chi(2);
|
||||
if (KDL::Norm(error) > m_maxerror)
|
||||
error = KDL::sign(error) * m_maxerror;
|
||||
m_ydot(0) = m_yddot + m_K * error;
|
||||
bool cacheAvail = true;
|
||||
if (!timestamp.substep) {
|
||||
if (!timestamp.reiterate)
|
||||
cacheAvail = popDist(timestamp.cacheTimestamp);
|
||||
}
|
||||
if (m_constraintCallback && (m_substep || (!timestamp.reiterate && !timestamp.substep))) {
|
||||
// initialize first callback the application to get the current values
|
||||
*(double*)&m_data.y = m_chi(2);
|
||||
*(double*)&m_data.ydot = m_ydot(0);
|
||||
m_data.yd = m_yd;
|
||||
m_data.yddot = m_yddot;
|
||||
m_data.action = 0;
|
||||
m_values.action = 0;
|
||||
if ((*m_constraintCallback)(timestamp, &m_values, 1, m_constraintParam)) {
|
||||
setControlParameters(&m_values, 1, timestamp.realTimestep);
|
||||
}
|
||||
}
|
||||
if (!cacheAvail || !timestamp.interpolate) {
|
||||
// first position in cache: set the desired output immediately as we cannot interpolate
|
||||
m_yd = m_nextyd;
|
||||
m_yddot = m_nextyddot;
|
||||
}
|
||||
double error = m_yd-m_chi(2);
|
||||
if (KDL::Norm(error) > m_maxerror)
|
||||
error = KDL::sign(error)*m_maxerror;
|
||||
m_ydot(0)=m_yddot+m_K*error;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
@@ -14,50 +14,50 @@
|
||||
#include "kdl/chainfksolverpos_recursive.hpp"
|
||||
#include "kdl/chainjnttojacsolver.hpp"
|
||||
|
||||
namespace iTaSC {
|
||||
namespace iTaSC
|
||||
{
|
||||
|
||||
class Distance : public iTaSC::ConstraintSet {
|
||||
protected:
|
||||
virtual void updateKinematics(const Timestamp ×tamp);
|
||||
virtual void pushCache(const Timestamp ×tamp);
|
||||
virtual void updateJacobian();
|
||||
virtual bool initialise(Frame &init_pose);
|
||||
virtual void initCache(Cache *_cache);
|
||||
virtual void updateControlOutput(const Timestamp ×tamp);
|
||||
virtual bool closeLoop();
|
||||
class Distance: public iTaSC::ConstraintSet
|
||||
{
|
||||
protected:
|
||||
virtual void updateKinematics(const Timestamp& timestamp);
|
||||
virtual void pushCache(const Timestamp& timestamp);
|
||||
virtual void updateJacobian();
|
||||
virtual bool initialise(Frame& init_pose);
|
||||
virtual void initCache(Cache *_cache);
|
||||
virtual void updateControlOutput(const Timestamp& timestamp);
|
||||
virtual bool closeLoop();
|
||||
|
||||
public:
|
||||
enum ID {
|
||||
ID_DISTANCE = 1,
|
||||
};
|
||||
Distance(double armlength = 1.0, double accuracy = 1e-6, unsigned int maximum_iterations = 100);
|
||||
virtual ~Distance();
|
||||
public:
|
||||
enum ID {
|
||||
ID_DISTANCE=1,
|
||||
};
|
||||
Distance(double armlength=1.0, double accuracy=1e-6, unsigned int maximum_iterations=100);
|
||||
virtual ~Distance();
|
||||
|
||||
virtual bool setControlParameters(struct ConstraintValues *_values,
|
||||
unsigned int _nvalues,
|
||||
double timestep);
|
||||
virtual const ConstraintValues *getControlParameters(unsigned int *_nvalues);
|
||||
virtual bool setControlParameters(struct ConstraintValues* _values, unsigned int _nvalues, double timestep);
|
||||
virtual const ConstraintValues* getControlParameters(unsigned int* _nvalues);
|
||||
|
||||
private:
|
||||
bool computeChi(Frame &pose);
|
||||
KDL::Chain m_chain;
|
||||
KDL::ChainFkSolverPos_recursive *m_fksolver;
|
||||
KDL::ChainJntToJacSolver *m_jacsolver;
|
||||
KDL::JntArray m_chiKdl;
|
||||
KDL::Jacobian m_jac;
|
||||
struct ConstraintSingleValue m_data;
|
||||
struct ConstraintValues m_values;
|
||||
Cache *m_cache;
|
||||
int m_distCCh;
|
||||
CacheTS m_distCTs;
|
||||
double m_maxerror;
|
||||
private:
|
||||
bool computeChi(Frame& pose);
|
||||
KDL::Chain m_chain;
|
||||
KDL::ChainFkSolverPos_recursive* m_fksolver;
|
||||
KDL::ChainJntToJacSolver* m_jacsolver;
|
||||
KDL::JntArray m_chiKdl;
|
||||
KDL::Jacobian m_jac;
|
||||
struct ConstraintSingleValue m_data;
|
||||
struct ConstraintValues m_values;
|
||||
Cache* m_cache;
|
||||
int m_distCCh;
|
||||
CacheTS m_distCTs;
|
||||
double m_maxerror;
|
||||
|
||||
void pushDist(CacheTS timestamp);
|
||||
bool popDist(CacheTS timestamp);
|
||||
void pushDist(CacheTS timestamp);
|
||||
bool popDist(CacheTS timestamp);
|
||||
|
||||
double m_alpha, m_yddot, m_yd, m_nextyd, m_nextyddot, m_K, m_tolerance;
|
||||
double m_alpha,m_yddot,m_yd,m_nextyd,m_nextyddot,m_K,m_tolerance;
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* DISTANCE_HPP_ */
|
||||
|
||||
@@ -8,62 +8,65 @@
|
||||
|
||||
#include "FixedObject.hpp"
|
||||
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
FixedObject::FixedObject() : UncontrolledObject(), m_finalized(false), m_nframe(0) {}
|
||||
|
||||
FixedObject::~FixedObject()
|
||||
FixedObject::FixedObject():UncontrolledObject(),
|
||||
m_finalized(false), m_nframe(0)
|
||||
{
|
||||
m_frameArray.clear();
|
||||
}
|
||||
|
||||
int FixedObject::addFrame(const std::string &name, const Frame &frame)
|
||||
FixedObject::~FixedObject()
|
||||
{
|
||||
if (m_finalized)
|
||||
return -1;
|
||||
FrameList::iterator it;
|
||||
unsigned int i;
|
||||
for (i = 0, it = m_frameArray.begin(); i < m_nframe; i++, it++) {
|
||||
if (it->first == name) {
|
||||
// this frame will replace the old frame
|
||||
it->second = frame;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
m_frameArray.push_back(FrameList::value_type(name, frame));
|
||||
return m_nframe++;
|
||||
m_frameArray.clear();
|
||||
}
|
||||
|
||||
int FixedObject::addEndEffector(const std::string &name)
|
||||
int FixedObject::addFrame(const std::string& name, const Frame& frame)
|
||||
{
|
||||
// verify that this frame name exist
|
||||
FrameList::iterator it;
|
||||
unsigned int i;
|
||||
for (i = 0, it = m_frameArray.begin(); i < m_nframe; i++, it++) {
|
||||
if (it->first == name) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
if (m_finalized)
|
||||
return -1;
|
||||
FrameList::iterator it;
|
||||
unsigned int i;
|
||||
for (i=0, it=m_frameArray.begin(); i<m_nframe; i++, it++) {
|
||||
if (it->first == name) {
|
||||
// this frame will replace the old frame
|
||||
it->second = frame;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
m_frameArray.push_back(FrameList::value_type(name,frame));
|
||||
return m_nframe++;
|
||||
}
|
||||
|
||||
int FixedObject::addEndEffector(const std::string& name)
|
||||
{
|
||||
// verify that this frame name exist
|
||||
FrameList::iterator it;
|
||||
unsigned int i;
|
||||
for (i=0, it=m_frameArray.begin(); i<m_nframe; i++, it++) {
|
||||
if (it->first == name) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool FixedObject::finalize()
|
||||
{
|
||||
if (m_finalized)
|
||||
return true;
|
||||
initialize(0, m_nframe);
|
||||
m_finalized = true;
|
||||
return true;
|
||||
if (m_finalized)
|
||||
return true;
|
||||
initialize(0, m_nframe);
|
||||
m_finalized = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
const Frame &FixedObject::getPose(const unsigned int frameIndex)
|
||||
const Frame& FixedObject::getPose(const unsigned int frameIndex)
|
||||
{
|
||||
if (frameIndex < m_nframe) {
|
||||
return m_frameArray[frameIndex].second;
|
||||
}
|
||||
else {
|
||||
return F_identity;
|
||||
}
|
||||
if (frameIndex < m_nframe) {
|
||||
return m_frameArray[frameIndex].second;
|
||||
} else {
|
||||
return F_identity;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
@@ -12,34 +12,35 @@
|
||||
#include "UncontrolledObject.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
class FixedObject : public UncontrolledObject {
|
||||
public:
|
||||
FixedObject();
|
||||
virtual ~FixedObject();
|
||||
namespace iTaSC{
|
||||
|
||||
int addFrame(const std::string &name, const Frame &frame);
|
||||
class FixedObject: public UncontrolledObject {
|
||||
public:
|
||||
FixedObject();
|
||||
virtual ~FixedObject();
|
||||
|
||||
virtual void updateCoordinates(const Timestamp ×tamp){};
|
||||
virtual int addEndEffector(const std::string &name);
|
||||
virtual bool finalize();
|
||||
virtual const Frame &getPose(const unsigned int frameIndex);
|
||||
virtual void updateKinematics(const Timestamp ×tamp){};
|
||||
virtual void pushCache(const Timestamp ×tamp){};
|
||||
virtual void initCache(Cache *_cache){};
|
||||
int addFrame(const std::string& name, const Frame& frame);
|
||||
|
||||
protected:
|
||||
virtual void updateJacobian() {}
|
||||
virtual void updateCoordinates(const Timestamp& timestamp) {};
|
||||
virtual int addEndEffector(const std::string& name);
|
||||
virtual bool finalize();
|
||||
virtual const Frame& getPose(const unsigned int frameIndex);
|
||||
virtual void updateKinematics(const Timestamp& timestamp) {};
|
||||
virtual void pushCache(const Timestamp& timestamp) {};
|
||||
virtual void initCache(Cache *_cache) {};
|
||||
|
||||
private:
|
||||
typedef std::vector<std::pair<std::string, Frame>> FrameList;
|
||||
protected:
|
||||
virtual void updateJacobian() {}
|
||||
private:
|
||||
typedef std::vector<std::pair<std::string, Frame> > FrameList;
|
||||
|
||||
bool m_finalized;
|
||||
unsigned int m_nframe;
|
||||
FrameList m_frameArray;
|
||||
|
||||
bool m_finalized;
|
||||
unsigned int m_nframe;
|
||||
FrameList m_frameArray;
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* FIXEDOBJECT_H_ */
|
||||
|
||||
@@ -8,161 +8,151 @@
|
||||
|
||||
#include "MovingFrame.hpp"
|
||||
#include <string.h>
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
static const unsigned int frameCacheSize = (sizeof(((Frame *)0)->p.data) +
|
||||
sizeof(((Frame *)0)->M.data)) /
|
||||
sizeof(double);
|
||||
static const unsigned int frameCacheSize = (sizeof(((Frame*)0)->p.data)+sizeof(((Frame*)0)->M.data))/sizeof(double);
|
||||
|
||||
MovingFrame::MovingFrame(const Frame &frame)
|
||||
: UncontrolledObject(),
|
||||
m_function(NULL),
|
||||
m_param(NULL),
|
||||
m_velocity(),
|
||||
m_poseCCh(-1),
|
||||
m_poseCTs(0)
|
||||
MovingFrame::MovingFrame(const Frame& frame):UncontrolledObject(),
|
||||
m_function(NULL), m_param(NULL), m_velocity(), m_poseCCh(-1), m_poseCTs(0)
|
||||
{
|
||||
m_internalPose = m_nextPose = frame;
|
||||
initialize(6, 1);
|
||||
e_matrix &Ju = m_JuArray[0];
|
||||
Ju = e_identity_matrix(6, 6);
|
||||
m_internalPose = m_nextPose = frame;
|
||||
initialize(6, 1);
|
||||
e_matrix& Ju = m_JuArray[0];
|
||||
Ju = e_identity_matrix(6,6);
|
||||
}
|
||||
|
||||
MovingFrame::~MovingFrame() {}
|
||||
MovingFrame::~MovingFrame()
|
||||
{
|
||||
}
|
||||
|
||||
bool MovingFrame::finalize()
|
||||
{
|
||||
updateJacobian();
|
||||
return true;
|
||||
updateJacobian();
|
||||
return true;
|
||||
}
|
||||
|
||||
void MovingFrame::initCache(Cache *_cache)
|
||||
{
|
||||
m_cache = _cache;
|
||||
m_poseCCh = -1;
|
||||
if (m_cache) {
|
||||
m_poseCCh = m_cache->addChannel(this, "pose", frameCacheSize * sizeof(double));
|
||||
// don't store the initial pose, it's causing unnecessary large velocity on the first step
|
||||
// pushInternalFrame(0);
|
||||
}
|
||||
m_cache = _cache;
|
||||
m_poseCCh = -1;
|
||||
if (m_cache) {
|
||||
m_poseCCh = m_cache->addChannel(this,"pose",frameCacheSize*sizeof(double));
|
||||
// don't store the initial pose, it's causing unnecessary large velocity on the first step
|
||||
//pushInternalFrame(0);
|
||||
}
|
||||
}
|
||||
|
||||
void MovingFrame::pushInternalFrame(CacheTS timestamp)
|
||||
{
|
||||
if (m_poseCCh >= 0) {
|
||||
double buf[frameCacheSize];
|
||||
memcpy(buf, m_internalPose.p.data, sizeof(m_internalPose.p.data));
|
||||
memcpy(&buf[sizeof(m_internalPose.p.data) / sizeof(double)],
|
||||
m_internalPose.M.data,
|
||||
sizeof(m_internalPose.M.data));
|
||||
if (m_poseCCh >= 0) {
|
||||
double buf[frameCacheSize];
|
||||
memcpy(buf, m_internalPose.p.data, sizeof(m_internalPose.p.data));
|
||||
memcpy(&buf[sizeof(m_internalPose.p.data)/sizeof(double)], m_internalPose.M.data, sizeof(m_internalPose.M.data));
|
||||
|
||||
m_cache->addCacheVectorIfDifferent(
|
||||
this, m_poseCCh, timestamp, buf, frameCacheSize, KDL::epsilon);
|
||||
m_poseCTs = timestamp;
|
||||
}
|
||||
m_cache->addCacheVectorIfDifferent(this, m_poseCCh, timestamp, buf, frameCacheSize, KDL::epsilon);
|
||||
m_poseCTs = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
// load pose just preceding timestamp
|
||||
// return false if no cache position was found
|
||||
bool MovingFrame::popInternalFrame(CacheTS timestamp)
|
||||
{
|
||||
if (m_poseCCh >= 0) {
|
||||
char *item;
|
||||
item = (char *)m_cache->getPreviousCacheItem(this, m_poseCCh, ×tamp);
|
||||
if (item && m_poseCTs != timestamp) {
|
||||
memcpy(m_internalPose.p.data, item, sizeof(m_internalPose.p.data));
|
||||
item += sizeof(m_internalPose.p.data);
|
||||
memcpy(m_internalPose.M.data, item, sizeof(m_internalPose.M.data));
|
||||
m_poseCTs = timestamp;
|
||||
// changing the starting pose, recompute the jacobian
|
||||
updateJacobian();
|
||||
}
|
||||
return (item) ? true : false;
|
||||
}
|
||||
// in case of no cache, there is always a previous position
|
||||
return true;
|
||||
if (m_poseCCh >= 0) {
|
||||
char *item;
|
||||
item = (char *)m_cache->getPreviousCacheItem(this, m_poseCCh, ×tamp);
|
||||
if (item && m_poseCTs != timestamp) {
|
||||
memcpy(m_internalPose.p.data, item, sizeof(m_internalPose.p.data));
|
||||
item += sizeof(m_internalPose.p.data);
|
||||
memcpy(m_internalPose.M.data, item, sizeof(m_internalPose.M.data));
|
||||
m_poseCTs = timestamp;
|
||||
// changing the starting pose, recompute the jacobian
|
||||
updateJacobian();
|
||||
}
|
||||
return (item) ? true : false;
|
||||
}
|
||||
// in case of no cache, there is always a previous position
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MovingFrame::setFrame(const Frame &frame)
|
||||
bool MovingFrame::setFrame(const Frame& frame)
|
||||
{
|
||||
m_internalPose = m_nextPose = frame;
|
||||
return true;
|
||||
m_internalPose = m_nextPose = frame;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MovingFrame::setCallback(MovingFrameCallback _function, void *_param)
|
||||
bool MovingFrame::setCallback(MovingFrameCallback _function, void* _param)
|
||||
{
|
||||
m_function = _function;
|
||||
m_param = _param;
|
||||
return true;
|
||||
m_function = _function;
|
||||
m_param = _param;
|
||||
return true;
|
||||
}
|
||||
|
||||
void MovingFrame::updateCoordinates(const Timestamp ×tamp)
|
||||
void MovingFrame::updateCoordinates(const Timestamp& timestamp)
|
||||
{
|
||||
// don't compute the velocity during substepping, it is assumed constant.
|
||||
if (!timestamp.substep) {
|
||||
bool cacheAvail = true;
|
||||
if (!timestamp.reiterate) {
|
||||
cacheAvail = popInternalFrame(timestamp.cacheTimestamp);
|
||||
if (m_function)
|
||||
(*m_function)(timestamp, m_internalPose, m_nextPose, m_param);
|
||||
}
|
||||
// only compute velocity if we have a previous pose
|
||||
if (cacheAvail && timestamp.interpolate) {
|
||||
unsigned int iXu;
|
||||
m_velocity = diff(m_internalPose, m_nextPose, timestamp.realTimestep);
|
||||
for (iXu = 0; iXu < 6; iXu++)
|
||||
m_xudot(iXu) = m_velocity(iXu);
|
||||
}
|
||||
else if (!timestamp.reiterate) {
|
||||
// new position is forced, no velocity as we cannot interpolate
|
||||
m_internalPose = m_nextPose;
|
||||
m_velocity = Twist::Zero();
|
||||
m_xudot = e_zero_vector(6);
|
||||
// recompute the jacobian
|
||||
updateJacobian();
|
||||
}
|
||||
}
|
||||
// don't compute the velocity during substepping, it is assumed constant.
|
||||
if (!timestamp.substep) {
|
||||
bool cacheAvail = true;
|
||||
if (!timestamp.reiterate) {
|
||||
cacheAvail = popInternalFrame(timestamp.cacheTimestamp);
|
||||
if (m_function)
|
||||
(*m_function)(timestamp, m_internalPose, m_nextPose, m_param);
|
||||
}
|
||||
// only compute velocity if we have a previous pose
|
||||
if (cacheAvail && timestamp.interpolate) {
|
||||
unsigned int iXu;
|
||||
m_velocity = diff(m_internalPose, m_nextPose, timestamp.realTimestep);
|
||||
for (iXu=0; iXu<6; iXu++)
|
||||
m_xudot(iXu) = m_velocity(iXu);
|
||||
} else if (!timestamp.reiterate) {
|
||||
// new position is forced, no velocity as we cannot interpolate
|
||||
m_internalPose = m_nextPose;
|
||||
m_velocity = Twist::Zero();
|
||||
m_xudot = e_zero_vector(6);
|
||||
// recompute the jacobian
|
||||
updateJacobian();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MovingFrame::pushCache(const Timestamp ×tamp)
|
||||
void MovingFrame::pushCache(const Timestamp& timestamp)
|
||||
{
|
||||
if (!timestamp.substep && timestamp.cache)
|
||||
pushInternalFrame(timestamp.cacheTimestamp);
|
||||
if (!timestamp.substep && timestamp.cache)
|
||||
pushInternalFrame(timestamp.cacheTimestamp);
|
||||
}
|
||||
|
||||
void MovingFrame::updateKinematics(const Timestamp ×tamp)
|
||||
void MovingFrame::updateKinematics(const Timestamp& timestamp)
|
||||
{
|
||||
if (timestamp.interpolate) {
|
||||
if (timestamp.substep) {
|
||||
// during substepping, update the internal pose from velocity information
|
||||
Twist localvel = m_internalPose.M.Inverse(m_velocity);
|
||||
m_internalPose.Integrate(localvel, 1.0 / timestamp.realTimestep);
|
||||
}
|
||||
else {
|
||||
m_internalPose = m_nextPose;
|
||||
}
|
||||
// m_internalPose is updated, recompute the jacobian
|
||||
updateJacobian();
|
||||
}
|
||||
pushCache(timestamp);
|
||||
if (timestamp.interpolate) {
|
||||
if (timestamp.substep) {
|
||||
// during substepping, update the internal pose from velocity information
|
||||
Twist localvel = m_internalPose.M.Inverse(m_velocity);
|
||||
m_internalPose.Integrate(localvel, 1.0/timestamp.realTimestep);
|
||||
} else {
|
||||
m_internalPose = m_nextPose;
|
||||
}
|
||||
// m_internalPose is updated, recompute the jacobian
|
||||
updateJacobian();
|
||||
}
|
||||
pushCache(timestamp);
|
||||
}
|
||||
|
||||
void MovingFrame::updateJacobian()
|
||||
{
|
||||
Twist m_jac;
|
||||
e_matrix &Ju = m_JuArray[0];
|
||||
Twist m_jac;
|
||||
e_matrix& Ju = m_JuArray[0];
|
||||
|
||||
// Jacobian is always identity at position on the object,
|
||||
// we ust change the reference to the world.
|
||||
// instead of going through complicated jacobian operation, implemented direct formula
|
||||
Ju(1, 3) = m_internalPose.p.z();
|
||||
Ju(2, 3) = -m_internalPose.p.y();
|
||||
Ju(0, 4) = -m_internalPose.p.z();
|
||||
Ju(2, 4) = m_internalPose.p.x();
|
||||
Ju(0, 5) = m_internalPose.p.y();
|
||||
Ju(1, 5) = -m_internalPose.p.x();
|
||||
// remember that this object has moved
|
||||
m_updated = true;
|
||||
//Jacobian is always identity at position on the object,
|
||||
//we ust change the reference to the world.
|
||||
//instead of going through complicated jacobian operation, implemented direct formula
|
||||
Ju(1,3) = m_internalPose.p.z();
|
||||
Ju(2,3) = -m_internalPose.p.y();
|
||||
Ju(0,4) = -m_internalPose.p.z();
|
||||
Ju(2,4) = m_internalPose.p.x();
|
||||
Ju(0,5) = m_internalPose.p.y();
|
||||
Ju(1,5) = -m_internalPose.p.x();
|
||||
// remember that this object has moved
|
||||
m_updated = true;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
@@ -12,41 +12,42 @@
|
||||
#include "UncontrolledObject.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
typedef bool (*MovingFrameCallback)(const Timestamp ×tamp,
|
||||
const Frame &_current,
|
||||
Frame &_next,
|
||||
void *param);
|
||||
namespace iTaSC{
|
||||
|
||||
class MovingFrame : public UncontrolledObject {
|
||||
public:
|
||||
MovingFrame(const Frame &frame = F_identity);
|
||||
virtual ~MovingFrame();
|
||||
typedef bool (*MovingFrameCallback)(
|
||||
const Timestamp& timestamp,
|
||||
const Frame& _current,
|
||||
Frame& _next,
|
||||
void *param);
|
||||
|
||||
bool setFrame(const Frame &frame);
|
||||
bool setCallback(MovingFrameCallback _function, void *_param);
|
||||
class MovingFrame: public UncontrolledObject {
|
||||
public:
|
||||
MovingFrame(const Frame& frame=F_identity);
|
||||
virtual ~MovingFrame();
|
||||
|
||||
virtual void updateCoordinates(const Timestamp ×tamp);
|
||||
virtual void updateKinematics(const Timestamp ×tamp);
|
||||
virtual void pushCache(const Timestamp ×tamp);
|
||||
virtual void initCache(Cache *_cache);
|
||||
virtual bool finalize();
|
||||
bool setFrame(const Frame& frame);
|
||||
bool setCallback(MovingFrameCallback _function, void* _param);
|
||||
|
||||
protected:
|
||||
virtual void updateJacobian();
|
||||
virtual void updateCoordinates(const Timestamp& timestamp);
|
||||
virtual void updateKinematics(const Timestamp& timestamp);
|
||||
virtual void pushCache(const Timestamp& timestamp);
|
||||
virtual void initCache(Cache *_cache);
|
||||
virtual bool finalize();
|
||||
protected:
|
||||
virtual void updateJacobian();
|
||||
|
||||
private:
|
||||
void pushInternalFrame(CacheTS timestamp);
|
||||
bool popInternalFrame(CacheTS timestamp);
|
||||
MovingFrameCallback m_function;
|
||||
void *m_param;
|
||||
Frame m_nextPose;
|
||||
Twist m_velocity;
|
||||
int m_poseCCh; // cache channel for pose
|
||||
unsigned int m_poseCTs;
|
||||
private:
|
||||
void pushInternalFrame(CacheTS timestamp);
|
||||
bool popInternalFrame(CacheTS timestamp);
|
||||
MovingFrameCallback m_function;
|
||||
void* m_param;
|
||||
Frame m_nextPose;
|
||||
Twist m_velocity;
|
||||
int m_poseCCh; // cache channel for pose
|
||||
unsigned int m_poseCTs;
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* MOVINGFRAME_H_ */
|
||||
|
||||
@@ -13,62 +13,40 @@
|
||||
#include "kdl/frames.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
class WorldObject;
|
||||
|
||||
class Object {
|
||||
public:
|
||||
enum ObjectType { Controlled, UnControlled };
|
||||
static WorldObject world;
|
||||
public:
|
||||
enum ObjectType {Controlled, UnControlled};
|
||||
static WorldObject world;
|
||||
|
||||
private:
|
||||
ObjectType m_type;
|
||||
private:
|
||||
ObjectType m_type;
|
||||
protected:
|
||||
Cache *m_cache;
|
||||
KDL::Frame m_internalPose;
|
||||
bool m_updated;
|
||||
virtual void updateJacobian()=0;
|
||||
public:
|
||||
Object(ObjectType _type):m_type(_type), m_cache(NULL), m_internalPose(F_identity), m_updated(false) {};
|
||||
virtual ~Object(){};
|
||||
|
||||
protected:
|
||||
Cache *m_cache;
|
||||
KDL::Frame m_internalPose;
|
||||
bool m_updated;
|
||||
virtual void updateJacobian() = 0;
|
||||
|
||||
public:
|
||||
Object(ObjectType _type)
|
||||
: m_type(_type), m_cache(NULL), m_internalPose(F_identity), m_updated(false){};
|
||||
virtual ~Object(){};
|
||||
|
||||
virtual int addEndEffector(const std::string & /*name*/)
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
virtual bool finalize()
|
||||
{
|
||||
return true;
|
||||
};
|
||||
virtual const KDL::Frame &getPose(const unsigned int end_effector = 0)
|
||||
{
|
||||
(void)end_effector;
|
||||
return m_internalPose;
|
||||
};
|
||||
virtual const ObjectType getType()
|
||||
{
|
||||
return m_type;
|
||||
};
|
||||
virtual const unsigned int getNrOfCoordinates()
|
||||
{
|
||||
return 0;
|
||||
};
|
||||
virtual void updateKinematics(const Timestamp & /*timestamp*/) = 0;
|
||||
virtual void pushCache(const Timestamp & /*timestamp*/) = 0;
|
||||
virtual void initCache(Cache * /*cache*/) = 0;
|
||||
bool updated()
|
||||
{
|
||||
return m_updated;
|
||||
};
|
||||
void updated(bool val)
|
||||
{
|
||||
m_updated = val;
|
||||
};
|
||||
virtual int addEndEffector(const std::string& /*name*/){return 0;};
|
||||
virtual bool finalize(){return true;};
|
||||
virtual const KDL::Frame& getPose(const unsigned int end_effector=0){
|
||||
(void)end_effector;
|
||||
return m_internalPose;
|
||||
};
|
||||
virtual const ObjectType getType(){return m_type;};
|
||||
virtual const unsigned int getNrOfCoordinates(){return 0;};
|
||||
virtual void updateKinematics(const Timestamp& /*timestamp*/)=0;
|
||||
virtual void pushCache(const Timestamp& /*timestamp*/)=0;
|
||||
virtual void initCache(Cache * /*cache*/) = 0;
|
||||
bool updated() {return m_updated;};
|
||||
void updated(bool val) {m_updated=val;};
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
#endif /* OBJECT_HPP_ */
|
||||
|
||||
@@ -19,8 +19,12 @@ class SceneLock : public ControlledObject::JointLockCallback {
|
||||
Range m_qrange;
|
||||
|
||||
public:
|
||||
SceneLock(Scene *scene) : m_scene(scene), m_qrange(0, 0) {}
|
||||
virtual ~SceneLock() {}
|
||||
SceneLock(Scene *scene) : m_scene(scene), m_qrange(0, 0)
|
||||
{
|
||||
}
|
||||
virtual ~SceneLock()
|
||||
{
|
||||
}
|
||||
|
||||
void setRange(Range &range)
|
||||
{
|
||||
@@ -371,8 +375,7 @@ bool Scene::update(double timestamp,
|
||||
}
|
||||
}
|
||||
if (os->object->getType() == Object::UnControlled &&
|
||||
((UncontrolledObject *)os->object)->getNrOfCoordinates() != 0)
|
||||
{
|
||||
((UncontrolledObject *)os->object)->getNrOfCoordinates() != 0) {
|
||||
((UncontrolledObject *)(os->object))->updateCoordinates(ts);
|
||||
if (!ts.substep) {
|
||||
// velocity of uncontrolled object remains constant during substepping
|
||||
@@ -388,8 +391,7 @@ bool Scene::update(double timestamp,
|
||||
Object_struct *ob2 = cs->object2->second;
|
||||
|
||||
if (ob1->base->updated() || ob1->object->updated() || ob2->base->updated() ||
|
||||
ob2->object->updated())
|
||||
{
|
||||
ob2->object->updated()) {
|
||||
// the object from which the constraint depends have changed position
|
||||
// recompute the constraint pose
|
||||
getConstraintPose(cs->task, cs, external_pose);
|
||||
@@ -438,8 +440,7 @@ bool Scene::update(double timestamp,
|
||||
}
|
||||
}
|
||||
else if (ob1->object->getType() == Object::UnControlled &&
|
||||
((UncontrolledObject *)ob1->object)->getNrOfCoordinates() != 0)
|
||||
{
|
||||
((UncontrolledObject *)ob1->object)->getNrOfCoordinates() != 0) {
|
||||
// object1 is uncontrolled moving object
|
||||
project(m_Ju,
|
||||
cs->featurerange,
|
||||
@@ -478,8 +479,7 @@ bool Scene::update(double timestamp,
|
||||
}
|
||||
}
|
||||
else if (ob2->object->getType() == Object::UnControlled &&
|
||||
((UncontrolledObject *)ob2->object)->getNrOfCoordinates() != 0)
|
||||
{
|
||||
((UncontrolledObject *)ob2->object)->getNrOfCoordinates() != 0) {
|
||||
if (ob2->object == ob1->base || ob2->object == ob1->object) {
|
||||
project(m_Ju, cs->featurerange, ob2->coordinaterange) -=
|
||||
((UncontrolledObject *)ob2->object)->getJu(cs->ee2index);
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
|
||||
#include "eigen_types.hpp"
|
||||
|
||||
#include "WorldObject.hpp"
|
||||
#include "ConstraintSet.hpp"
|
||||
#include "Solver.hpp"
|
||||
#include "WorldObject.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
@@ -22,110 +22,84 @@ namespace iTaSC {
|
||||
class SceneLock;
|
||||
|
||||
class Scene {
|
||||
friend class SceneLock;
|
||||
friend class SceneLock;
|
||||
public:
|
||||
enum SceneParam {
|
||||
MIN_TIMESTEP = 0,
|
||||
MAX_TIMESTEP,
|
||||
|
||||
public:
|
||||
enum SceneParam {
|
||||
MIN_TIMESTEP = 0,
|
||||
MAX_TIMESTEP,
|
||||
COUNT
|
||||
};
|
||||
|
||||
COUNT
|
||||
};
|
||||
|
||||
Scene();
|
||||
virtual ~Scene();
|
||||
Scene();
|
||||
virtual ~Scene();
|
||||
|
||||
bool addObject(const std::string &name,
|
||||
Object *object,
|
||||
UncontrolledObject *base = &Object::world,
|
||||
const std::string &baseFrame = "");
|
||||
bool addConstraintSet(const std::string &name,
|
||||
ConstraintSet *task,
|
||||
const std::string &object1,
|
||||
const std::string &object2,
|
||||
const std::string &ee1 = "",
|
||||
const std::string &ee2 = "");
|
||||
bool addSolver(Solver *_solver);
|
||||
bool addCache(Cache *_cache);
|
||||
bool initialize();
|
||||
bool update(double timestamp,
|
||||
double timestep,
|
||||
unsigned int numsubstep = 1,
|
||||
bool reiterate = false,
|
||||
bool cache = true,
|
||||
bool interpolate = true);
|
||||
bool setParam(SceneParam paramId, double value);
|
||||
bool addObject(const std::string& name, Object* object, UncontrolledObject* base=&Object::world, const std::string& baseFrame="");
|
||||
bool addConstraintSet(const std::string& name, ConstraintSet* task,const std::string& object1,const std::string& object2,const std::string& ee1="",const std::string& ee2="");
|
||||
bool addSolver(Solver* _solver);
|
||||
bool addCache(Cache* _cache);
|
||||
bool initialize();
|
||||
bool update(double timestamp, double timestep, unsigned int numsubstep=1, bool reiterate=false, bool cache=true, bool interpolate=true);
|
||||
bool setParam(SceneParam paramId, double value);
|
||||
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
|
||||
private:
|
||||
e_matrix m_A, m_B, m_Atemp, m_Wq, m_Jf, m_Jq, m_Ju, m_Cf, m_Cq, m_Jf_inv;
|
||||
e_matrix6 m_Vf, m_Uf;
|
||||
e_vector m_Wy, m_ydot, m_qdot, m_xdot;
|
||||
e_vector6 m_Sf, m_tempf;
|
||||
double m_minstep;
|
||||
double m_maxstep;
|
||||
unsigned int m_ncTotal, m_nqTotal, m_nuTotal, m_nsets;
|
||||
std::vector<bool> m_ytask;
|
||||
private:
|
||||
e_matrix m_A,m_B,m_Atemp,m_Wq,m_Jf,m_Jq,m_Ju,m_Cf,m_Cq,m_Jf_inv;
|
||||
e_matrix6 m_Vf,m_Uf;
|
||||
e_vector m_Wy,m_ydot,m_qdot,m_xdot;
|
||||
e_vector6 m_Sf,m_tempf;
|
||||
double m_minstep;
|
||||
double m_maxstep;
|
||||
unsigned int m_ncTotal,m_nqTotal,m_nuTotal,m_nsets;
|
||||
std::vector<bool> m_ytask;
|
||||
|
||||
Solver *m_solver;
|
||||
Cache *m_cache;
|
||||
Solver* m_solver;
|
||||
Cache* m_cache;
|
||||
|
||||
struct Object_struct {
|
||||
Object *object;
|
||||
UncontrolledObject *base;
|
||||
unsigned int baseFrameIndex;
|
||||
Range constraintrange;
|
||||
Range jointrange;
|
||||
Range coordinaterange; // Xu range of base when object is controlled
|
||||
// Xu range of object when object is uncontrolled
|
||||
|
||||
Object_struct(Object *_object,
|
||||
UncontrolledObject *_base,
|
||||
unsigned int _baseFrameIndex,
|
||||
Range nq_range,
|
||||
Range nc_range,
|
||||
Range nu_range)
|
||||
: object(_object),
|
||||
base(_base),
|
||||
baseFrameIndex(_baseFrameIndex),
|
||||
constraintrange(nc_range),
|
||||
jointrange(nq_range),
|
||||
coordinaterange(nu_range){};
|
||||
};
|
||||
typedef std::map<std::string, Object_struct *> ObjectMap;
|
||||
struct Object_struct{
|
||||
Object* object;
|
||||
UncontrolledObject* base;
|
||||
unsigned int baseFrameIndex;
|
||||
Range constraintrange;
|
||||
Range jointrange;
|
||||
Range coordinaterange; // Xu range of base when object is controlled
|
||||
// Xu range of object when object is uncontrolled
|
||||
|
||||
struct ConstraintSet_struct {
|
||||
ConstraintSet *task;
|
||||
ObjectMap::iterator object1;
|
||||
ObjectMap::iterator object2;
|
||||
Range constraintrange;
|
||||
Range featurerange;
|
||||
unsigned int ee1index;
|
||||
unsigned int ee2index;
|
||||
ConstraintSet_struct(ConstraintSet *_task,
|
||||
ObjectMap::iterator _object1,
|
||||
unsigned int _ee1index,
|
||||
ObjectMap::iterator _object2,
|
||||
unsigned int _ee2index,
|
||||
Range nc_range,
|
||||
Range coord_range)
|
||||
: task(_task),
|
||||
object1(_object1),
|
||||
object2(_object2),
|
||||
constraintrange(nc_range),
|
||||
featurerange(coord_range),
|
||||
ee1index(_ee1index),
|
||||
ee2index(_ee2index){};
|
||||
};
|
||||
typedef std::map<std::string, ConstraintSet_struct *> ConstraintMap;
|
||||
Object_struct(Object* _object,UncontrolledObject* _base,unsigned int _baseFrameIndex,Range nq_range,Range nc_range,Range nu_range):
|
||||
object(_object),base(_base),baseFrameIndex(_baseFrameIndex),constraintrange(nc_range),jointrange(nq_range),coordinaterange(nu_range)
|
||||
{};
|
||||
};
|
||||
typedef std::map<std::string,Object_struct*> ObjectMap;
|
||||
|
||||
ObjectMap objects;
|
||||
ConstraintMap constraints;
|
||||
struct ConstraintSet_struct{
|
||||
ConstraintSet* task;
|
||||
ObjectMap::iterator object1;
|
||||
ObjectMap::iterator object2;
|
||||
Range constraintrange;
|
||||
Range featurerange;
|
||||
unsigned int ee1index;
|
||||
unsigned int ee2index;
|
||||
ConstraintSet_struct(ConstraintSet* _task,
|
||||
ObjectMap::iterator _object1,unsigned int _ee1index,
|
||||
ObjectMap::iterator _object2,unsigned int _ee2index,
|
||||
Range nc_range,Range coord_range):
|
||||
task(_task),
|
||||
object1(_object1),object2(_object2),
|
||||
constraintrange(nc_range),featurerange(coord_range),
|
||||
ee1index(_ee1index), ee2index(_ee2index)
|
||||
{};
|
||||
};
|
||||
typedef std::map<std::string,ConstraintSet_struct*> ConstraintMap;
|
||||
|
||||
static bool getConstraintPose(ConstraintSet *constraint, void *_param, KDL::Frame &_pose);
|
||||
ObjectMap objects;
|
||||
ConstraintMap constraints;
|
||||
|
||||
static bool getConstraintPose(ConstraintSet* constraint, void *_param, KDL::Frame& _pose);
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* SCENE_HPP_ */
|
||||
|
||||
@@ -9,27 +9,26 @@
|
||||
#ifndef SOLVER_HPP_
|
||||
#define SOLVER_HPP_
|
||||
|
||||
#include "eigen_types.hpp"
|
||||
#include <vector>
|
||||
#include "eigen_types.hpp"
|
||||
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
class Solver {
|
||||
public:
|
||||
enum SolverParam { DLS_QMAX = 0, DLS_LAMBDA_MAX, DLS_EPSILON };
|
||||
virtual ~Solver(){};
|
||||
class Solver{
|
||||
public:
|
||||
enum SolverParam {
|
||||
DLS_QMAX = 0,
|
||||
DLS_LAMBDA_MAX,
|
||||
DLS_EPSILON
|
||||
};
|
||||
virtual ~Solver(){};
|
||||
|
||||
// gc = grouping of constraint output ,
|
||||
// size of vector = nc, alternance of true / false to indicate the grouping of output
|
||||
virtual bool init(unsigned int nq, unsigned int nc, const std::vector<bool> &gc) = 0;
|
||||
virtual bool solve(const e_matrix &A,
|
||||
const e_vector &Wy,
|
||||
const e_vector &ydot,
|
||||
const e_matrix &Wq,
|
||||
e_vector &qdot,
|
||||
e_scalar &nlcoef) = 0;
|
||||
virtual void setParam(SolverParam param, double value) = 0;
|
||||
// gc = grouping of constraint output ,
|
||||
// size of vector = nc, alternance of true / false to indicate the grouping of output
|
||||
virtual bool init(unsigned int nq, unsigned int nc, const std::vector<bool>& gc)=0;
|
||||
virtual bool solve(const e_matrix& A, const e_vector& Wy, const e_vector& ydot, const e_matrix& Wq, e_vector& qdot, e_scalar& nlcoef)=0;
|
||||
virtual void setParam(SolverParam param, double value)=0;
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
#endif /* SOLVER_HPP_ */
|
||||
|
||||
@@ -8,30 +8,37 @@
|
||||
|
||||
#include "UncontrolledObject.hpp"
|
||||
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
UncontrolledObject::UncontrolledObject() : Object(UnControlled), m_nu(0), m_nf(0), m_xudot() {}
|
||||
UncontrolledObject::UncontrolledObject():Object(UnControlled),
|
||||
m_nu(0), m_nf(0), m_xudot()
|
||||
{
|
||||
}
|
||||
|
||||
UncontrolledObject::~UncontrolledObject() {}
|
||||
UncontrolledObject::~UncontrolledObject()
|
||||
{
|
||||
}
|
||||
|
||||
void UncontrolledObject::initialize(unsigned int _nu, unsigned int _nf)
|
||||
{
|
||||
assert(_nf >= 1);
|
||||
m_nu = _nu;
|
||||
m_nf = _nf;
|
||||
if (_nu > 0)
|
||||
m_xudot = e_zero_vector(_nu);
|
||||
// clear all Jacobian if any
|
||||
m_JuArray.clear();
|
||||
// reserve one more to have an zero matrix handy
|
||||
if (m_nu > 0)
|
||||
m_JuArray.resize(m_nf + 1, e_zero_matrix(6, m_nu));
|
||||
assert (_nf >= 1);
|
||||
m_nu = _nu;
|
||||
m_nf = _nf;
|
||||
if (_nu > 0)
|
||||
m_xudot = e_zero_vector(_nu);
|
||||
// clear all Jacobian if any
|
||||
m_JuArray.clear();
|
||||
// reserve one more to have an zero matrix handy
|
||||
if (m_nu > 0)
|
||||
m_JuArray.resize(m_nf+1, e_zero_matrix(6,m_nu));
|
||||
}
|
||||
|
||||
const e_matrix &UncontrolledObject::getJu(unsigned int frameIndex) const
|
||||
const e_matrix& UncontrolledObject::getJu(unsigned int frameIndex) const
|
||||
{
|
||||
assert(m_nu > 0);
|
||||
return m_JuArray[(frameIndex > m_nf) ? m_nf : frameIndex];
|
||||
assert (m_nu > 0);
|
||||
return m_JuArray[(frameIndex>m_nf)?m_nf:frameIndex];
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,35 +12,27 @@
|
||||
#include "eigen_types.hpp"
|
||||
|
||||
#include "Object.hpp"
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
class UncontrolledObject : public Object {
|
||||
protected:
|
||||
unsigned int m_nu, m_nf;
|
||||
e_vector m_xudot;
|
||||
std::vector<e_matrix> m_JuArray;
|
||||
class UncontrolledObject: public Object {
|
||||
protected:
|
||||
unsigned int m_nu, m_nf;
|
||||
e_vector m_xudot;
|
||||
std::vector<e_matrix> m_JuArray;
|
||||
|
||||
public:
|
||||
UncontrolledObject();
|
||||
virtual ~UncontrolledObject();
|
||||
public:
|
||||
UncontrolledObject();
|
||||
virtual ~UncontrolledObject();
|
||||
|
||||
virtual void initialize(unsigned int _nu, unsigned int _nf);
|
||||
virtual const e_matrix& getJu(unsigned int frameIndex) const;
|
||||
virtual const e_vector& getXudot() const {return m_xudot;}
|
||||
virtual void updateCoordinates(const Timestamp& timestamp)=0;
|
||||
virtual const unsigned int getNrOfCoordinates(){return m_nu;};
|
||||
virtual const unsigned int getNrOfFrames(){return m_nf;};
|
||||
|
||||
virtual void initialize(unsigned int _nu, unsigned int _nf);
|
||||
virtual const e_matrix &getJu(unsigned int frameIndex) const;
|
||||
virtual const e_vector &getXudot() const
|
||||
{
|
||||
return m_xudot;
|
||||
}
|
||||
virtual void updateCoordinates(const Timestamp ×tamp) = 0;
|
||||
virtual const unsigned int getNrOfCoordinates()
|
||||
{
|
||||
return m_nu;
|
||||
};
|
||||
virtual const unsigned int getNrOfFrames()
|
||||
{
|
||||
return m_nf;
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* UNCONTROLLEDOBJECT_H_ */
|
||||
|
||||
@@ -11,100 +11,92 @@
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
WDLSSolver::WDLSSolver() : m_lambda(0.5), m_epsilon(0.1)
|
||||
WDLSSolver::WDLSSolver() : m_lambda(0.5), m_epsilon(0.1)
|
||||
{
|
||||
// maximum joint velocity
|
||||
m_qmax = 50.0;
|
||||
// maximum joint velocity
|
||||
m_qmax = 50.0;
|
||||
}
|
||||
|
||||
WDLSSolver::~WDLSSolver() {}
|
||||
|
||||
bool WDLSSolver::init(unsigned int nq, unsigned int nc, const std::vector<bool> &gc)
|
||||
{
|
||||
m_ns = std::min(nc, nq);
|
||||
m_AWq = e_zero_matrix(nc, nq);
|
||||
m_WyAWq = e_zero_matrix(nc, nq);
|
||||
m_WyAWqt = e_zero_matrix(nq, nc);
|
||||
m_S = e_zero_vector(std::max(nc, nq));
|
||||
m_Wy_ydot = e_zero_vector(nc);
|
||||
if (nq > nc) {
|
||||
m_transpose = true;
|
||||
m_temp = e_zero_vector(nc);
|
||||
m_U = e_zero_matrix(nc, nc);
|
||||
m_V = e_zero_matrix(nq, nc);
|
||||
m_WqV = e_zero_matrix(nq, nc);
|
||||
}
|
||||
else {
|
||||
m_transpose = false;
|
||||
m_temp = e_zero_vector(nq);
|
||||
m_U = e_zero_matrix(nc, nq);
|
||||
m_V = e_zero_matrix(nq, nq);
|
||||
m_WqV = e_zero_matrix(nq, nq);
|
||||
}
|
||||
return true;
|
||||
WDLSSolver::~WDLSSolver() {
|
||||
}
|
||||
|
||||
bool WDLSSolver::solve(const e_matrix &A,
|
||||
const e_vector &Wy,
|
||||
const e_vector &ydot,
|
||||
const e_matrix &Wq,
|
||||
e_vector &qdot,
|
||||
e_scalar &nlcoef)
|
||||
bool WDLSSolver::init(unsigned int nq, unsigned int nc, const std::vector<bool>& gc)
|
||||
{
|
||||
double alpha, vmax, norm;
|
||||
// Create the Weighted jacobian
|
||||
m_AWq = A * Wq;
|
||||
for (int i = 0; i < Wy.size(); i++)
|
||||
m_WyAWq.row(i) = Wy(i) * m_AWq.row(i);
|
||||
|
||||
// Compute the SVD of the weighted jacobian
|
||||
int ret;
|
||||
if (m_transpose) {
|
||||
m_WyAWqt = m_WyAWq.transpose();
|
||||
ret = KDL::svd_eigen_HH(m_WyAWqt, m_V, m_S, m_U, m_temp);
|
||||
}
|
||||
else {
|
||||
ret = KDL::svd_eigen_HH(m_WyAWq, m_U, m_S, m_V, m_temp);
|
||||
}
|
||||
if (ret < 0)
|
||||
return false;
|
||||
|
||||
m_WqV.noalias() = Wq * m_V;
|
||||
|
||||
// Wy*ydot
|
||||
m_Wy_ydot = Wy.array() * ydot.array();
|
||||
// S^-1*U'*Wy*ydot
|
||||
e_scalar maxDeltaS = e_scalar(0.0);
|
||||
e_scalar prevS = e_scalar(0.0);
|
||||
e_scalar maxS = e_scalar(1.0);
|
||||
e_scalar S, lambda;
|
||||
qdot.setZero();
|
||||
for (int i = 0; i < m_ns; ++i) {
|
||||
S = m_S(i);
|
||||
if (S <= KDL::epsilon)
|
||||
break;
|
||||
if (i > 0 && (prevS - S) > maxDeltaS) {
|
||||
maxDeltaS = (prevS - S);
|
||||
maxS = prevS;
|
||||
}
|
||||
lambda = (S < m_epsilon) ? (e_scalar(1.0) - KDL::sqr(S / m_epsilon)) * m_lambda * m_lambda :
|
||||
e_scalar(0.0);
|
||||
alpha = m_U.col(i).dot(m_Wy_ydot) * S / (S * S + lambda);
|
||||
vmax = m_WqV.col(i).array().abs().maxCoeff();
|
||||
norm = fabs(alpha * vmax);
|
||||
if (norm > m_qmax) {
|
||||
qdot += m_WqV.col(i) * (alpha * m_qmax / norm);
|
||||
}
|
||||
else {
|
||||
qdot += m_WqV.col(i) * alpha;
|
||||
}
|
||||
prevS = S;
|
||||
}
|
||||
if (maxDeltaS == e_scalar(0.0))
|
||||
nlcoef = e_scalar(KDL::epsilon);
|
||||
else
|
||||
nlcoef = (maxS - maxDeltaS) / maxS;
|
||||
return true;
|
||||
m_ns = std::min(nc,nq);
|
||||
m_AWq = e_zero_matrix(nc,nq);
|
||||
m_WyAWq = e_zero_matrix(nc,nq);
|
||||
m_WyAWqt = e_zero_matrix(nq,nc);
|
||||
m_S = e_zero_vector(std::max(nc,nq));
|
||||
m_Wy_ydot = e_zero_vector(nc);
|
||||
if (nq > nc) {
|
||||
m_transpose = true;
|
||||
m_temp = e_zero_vector(nc);
|
||||
m_U = e_zero_matrix(nc,nc);
|
||||
m_V = e_zero_matrix(nq,nc);
|
||||
m_WqV = e_zero_matrix(nq,nc);
|
||||
} else {
|
||||
m_transpose = false;
|
||||
m_temp = e_zero_vector(nq);
|
||||
m_U = e_zero_matrix(nc,nq);
|
||||
m_V = e_zero_matrix(nq,nq);
|
||||
m_WqV = e_zero_matrix(nq,nq);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
bool WDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& ydot, const e_matrix& Wq, e_vector& qdot, e_scalar& nlcoef)
|
||||
{
|
||||
double alpha, vmax, norm;
|
||||
// Create the Weighted jacobian
|
||||
m_AWq = A*Wq;
|
||||
for (int i=0; i<Wy.size(); i++)
|
||||
m_WyAWq.row(i) = Wy(i)*m_AWq.row(i);
|
||||
|
||||
// Compute the SVD of the weighted jacobian
|
||||
int ret;
|
||||
if (m_transpose) {
|
||||
m_WyAWqt = m_WyAWq.transpose();
|
||||
ret = KDL::svd_eigen_HH(m_WyAWqt,m_V,m_S,m_U,m_temp);
|
||||
} else {
|
||||
ret = KDL::svd_eigen_HH(m_WyAWq,m_U,m_S,m_V,m_temp);
|
||||
}
|
||||
if(ret<0)
|
||||
return false;
|
||||
|
||||
m_WqV.noalias() = Wq*m_V;
|
||||
|
||||
//Wy*ydot
|
||||
m_Wy_ydot = Wy.array() * ydot.array();
|
||||
//S^-1*U'*Wy*ydot
|
||||
e_scalar maxDeltaS = e_scalar(0.0);
|
||||
e_scalar prevS = e_scalar(0.0);
|
||||
e_scalar maxS = e_scalar(1.0);
|
||||
e_scalar S, lambda;
|
||||
qdot.setZero();
|
||||
for(int i=0;i<m_ns;++i) {
|
||||
S = m_S(i);
|
||||
if (S <= KDL::epsilon)
|
||||
break;
|
||||
if (i > 0 && (prevS-S) > maxDeltaS) {
|
||||
maxDeltaS = (prevS-S);
|
||||
maxS = prevS;
|
||||
}
|
||||
lambda = (S < m_epsilon) ? (e_scalar(1.0)-KDL::sqr(S/m_epsilon))*m_lambda*m_lambda : e_scalar(0.0);
|
||||
alpha = m_U.col(i).dot(m_Wy_ydot)*S/(S*S+lambda);
|
||||
vmax = m_WqV.col(i).array().abs().maxCoeff();
|
||||
norm = fabs(alpha*vmax);
|
||||
if (norm > m_qmax) {
|
||||
qdot += m_WqV.col(i)*(alpha*m_qmax/norm);
|
||||
} else {
|
||||
qdot += m_WqV.col(i)*alpha;
|
||||
}
|
||||
prevS = S;
|
||||
}
|
||||
if (maxDeltaS == e_scalar(0.0))
|
||||
nlcoef = e_scalar(KDL::epsilon);
|
||||
else
|
||||
nlcoef = (maxS-maxDeltaS)/maxS;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,43 +13,37 @@
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
class WDLSSolver : public iTaSC::Solver {
|
||||
private:
|
||||
e_matrix m_AWq, m_WyAWq, m_WyAWqt, m_U, m_V, m_WqV;
|
||||
e_vector m_S, m_temp, m_Wy_ydot;
|
||||
double m_lambda;
|
||||
double m_epsilon;
|
||||
double m_qmax;
|
||||
int m_ns;
|
||||
bool m_transpose;
|
||||
class WDLSSolver: public iTaSC::Solver {
|
||||
private:
|
||||
e_matrix m_AWq,m_WyAWq,m_WyAWqt,m_U,m_V,m_WqV;
|
||||
e_vector m_S,m_temp,m_Wy_ydot;
|
||||
double m_lambda;
|
||||
double m_epsilon;
|
||||
double m_qmax;
|
||||
int m_ns;
|
||||
bool m_transpose;
|
||||
public:
|
||||
WDLSSolver();
|
||||
virtual ~WDLSSolver();
|
||||
|
||||
public:
|
||||
WDLSSolver();
|
||||
virtual ~WDLSSolver();
|
||||
|
||||
virtual bool init(unsigned int nq, unsigned int nc, const std::vector<bool> &gc);
|
||||
virtual bool solve(const e_matrix &A,
|
||||
const e_vector &Wy,
|
||||
const e_vector &ydot,
|
||||
const e_matrix &Wq,
|
||||
e_vector &qdot,
|
||||
e_scalar &nlcoef);
|
||||
virtual void setParam(SolverParam param, double value)
|
||||
{
|
||||
switch (param) {
|
||||
case DLS_QMAX:
|
||||
m_qmax = value;
|
||||
break;
|
||||
case DLS_LAMBDA_MAX:
|
||||
m_lambda = value;
|
||||
break;
|
||||
case DLS_EPSILON:
|
||||
m_epsilon = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
virtual bool init(unsigned int nq, unsigned int nc, const std::vector<bool>& gc);
|
||||
virtual bool solve(const e_matrix& A, const e_vector& Wy, const e_vector& ydot, const e_matrix& Wq, e_vector& qdot, e_scalar& nlcoef);
|
||||
virtual void setParam(SolverParam param, double value)
|
||||
{
|
||||
switch (param) {
|
||||
case DLS_QMAX:
|
||||
m_qmax = value;
|
||||
break;
|
||||
case DLS_LAMBDA_MAX:
|
||||
m_lambda = value;
|
||||
break;
|
||||
case DLS_EPSILON:
|
||||
m_epsilon = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* WDLSSOLVER_HPP_ */
|
||||
|
||||
@@ -12,136 +12,128 @@
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
WSDLSSolver::WSDLSSolver() : m_ns(0), m_nc(0), m_nq(0)
|
||||
WSDLSSolver::WSDLSSolver() :
|
||||
m_ns(0), m_nc(0), m_nq(0)
|
||||
|
||||
{
|
||||
// default maximum speed: 50 rad/s
|
||||
m_qmax = 50.0;
|
||||
// default maximum speed: 50 rad/s
|
||||
m_qmax = 50.0;
|
||||
}
|
||||
|
||||
WSDLSSolver::~WSDLSSolver() {}
|
||||
WSDLSSolver::~WSDLSSolver() {
|
||||
}
|
||||
|
||||
bool WSDLSSolver::init(unsigned int _nq, unsigned int _nc, const std::vector<bool> &gc)
|
||||
bool WSDLSSolver::init(unsigned int _nq, unsigned int _nc, const std::vector<bool>& gc)
|
||||
{
|
||||
if (_nc == 0 || _nq == 0 || gc.size() != _nc)
|
||||
return false;
|
||||
m_nc = _nc;
|
||||
m_nq = _nq;
|
||||
m_ns = std::min(m_nc, m_nq);
|
||||
m_AWq = e_zero_matrix(m_nc, m_nq);
|
||||
m_WyAWq = e_zero_matrix(m_nc, m_nq);
|
||||
m_WyAWqt = e_zero_matrix(m_nq, m_nc);
|
||||
m_S = e_zero_vector(std::max(m_nc, m_nq));
|
||||
m_Wy_ydot = e_zero_vector(m_nc);
|
||||
m_ytask = gc;
|
||||
if (m_nq > m_nc) {
|
||||
m_transpose = true;
|
||||
m_temp = e_zero_vector(m_nc);
|
||||
m_U = e_zero_matrix(m_nc, m_nc);
|
||||
m_V = e_zero_matrix(m_nq, m_nc);
|
||||
m_WqV = e_zero_matrix(m_nq, m_nc);
|
||||
}
|
||||
else {
|
||||
m_transpose = false;
|
||||
m_temp = e_zero_vector(m_nq);
|
||||
m_U = e_zero_matrix(m_nc, m_nq);
|
||||
m_V = e_zero_matrix(m_nq, m_nq);
|
||||
m_WqV = e_zero_matrix(m_nq, m_nq);
|
||||
}
|
||||
return true;
|
||||
if (_nc == 0 || _nq == 0 || gc.size() != _nc)
|
||||
return false;
|
||||
m_nc = _nc;
|
||||
m_nq = _nq;
|
||||
m_ns = std::min(m_nc,m_nq);
|
||||
m_AWq = e_zero_matrix(m_nc,m_nq);
|
||||
m_WyAWq = e_zero_matrix(m_nc,m_nq);
|
||||
m_WyAWqt = e_zero_matrix(m_nq,m_nc);
|
||||
m_S = e_zero_vector(std::max(m_nc,m_nq));
|
||||
m_Wy_ydot = e_zero_vector(m_nc);
|
||||
m_ytask = gc;
|
||||
if (m_nq > m_nc) {
|
||||
m_transpose = true;
|
||||
m_temp = e_zero_vector(m_nc);
|
||||
m_U = e_zero_matrix(m_nc,m_nc);
|
||||
m_V = e_zero_matrix(m_nq,m_nc);
|
||||
m_WqV = e_zero_matrix(m_nq,m_nc);
|
||||
} else {
|
||||
m_transpose = false;
|
||||
m_temp = e_zero_vector(m_nq);
|
||||
m_U = e_zero_matrix(m_nc,m_nq);
|
||||
m_V = e_zero_matrix(m_nq,m_nq);
|
||||
m_WqV = e_zero_matrix(m_nq,m_nq);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WSDLSSolver::solve(const e_matrix &A,
|
||||
const e_vector &Wy,
|
||||
const e_vector &ydot,
|
||||
const e_matrix &Wq,
|
||||
e_vector &qdot,
|
||||
e_scalar &nlcoef)
|
||||
bool WSDLSSolver::solve(const e_matrix& A, const e_vector& Wy, const e_vector& ydot, const e_matrix& Wq, e_vector& qdot, e_scalar& nlcoef)
|
||||
{
|
||||
unsigned int i, j, l;
|
||||
e_scalar N, M;
|
||||
unsigned int i, j, l;
|
||||
e_scalar N, M;
|
||||
|
||||
// Create the Weighted jacobian
|
||||
m_AWq.noalias() = A * Wq;
|
||||
for (i = 0; i < m_nc; i++)
|
||||
m_WyAWq.row(i) = Wy(i) * m_AWq.row(i);
|
||||
// Create the Weighted jacobian
|
||||
m_AWq.noalias() = A*Wq;
|
||||
for (i=0; i<m_nc; i++)
|
||||
m_WyAWq.row(i) = Wy(i)*m_AWq.row(i);
|
||||
|
||||
// Compute the SVD of the weighted jacobian
|
||||
int ret;
|
||||
if (m_transpose) {
|
||||
m_WyAWqt = m_WyAWq.transpose();
|
||||
ret = KDL::svd_eigen_HH(m_WyAWqt, m_V, m_S, m_U, m_temp);
|
||||
}
|
||||
else {
|
||||
ret = KDL::svd_eigen_HH(m_WyAWq, m_U, m_S, m_V, m_temp);
|
||||
}
|
||||
if (ret < 0)
|
||||
return false;
|
||||
// Compute the SVD of the weighted jacobian
|
||||
int ret;
|
||||
if (m_transpose) {
|
||||
m_WyAWqt = m_WyAWq.transpose();
|
||||
ret = KDL::svd_eigen_HH(m_WyAWqt,m_V,m_S,m_U,m_temp);
|
||||
} else {
|
||||
ret = KDL::svd_eigen_HH(m_WyAWq,m_U,m_S,m_V,m_temp);
|
||||
}
|
||||
if(ret<0)
|
||||
return false;
|
||||
|
||||
m_Wy_ydot = Wy.array() * ydot.array();
|
||||
m_WqV.noalias() = Wq * m_V;
|
||||
qdot.setZero();
|
||||
e_scalar maxDeltaS = e_scalar(0.0);
|
||||
e_scalar prevS = e_scalar(0.0);
|
||||
e_scalar maxS = e_scalar(1.0);
|
||||
for (i = 0; i < m_ns; ++i) {
|
||||
e_scalar norm, mag, alpha, _qmax, Sinv, vmax, damp;
|
||||
e_scalar S = m_S(i);
|
||||
bool prev;
|
||||
if (S < KDL::epsilon)
|
||||
break;
|
||||
Sinv = e_scalar(1.) / S;
|
||||
if (i > 0) {
|
||||
if ((prevS - S) > maxDeltaS) {
|
||||
maxDeltaS = (prevS - S);
|
||||
maxS = prevS;
|
||||
}
|
||||
}
|
||||
N = M = e_scalar(0.);
|
||||
for (l = 0, prev = m_ytask[0], norm = e_scalar(0.); l < m_nc; l++) {
|
||||
if (prev == m_ytask[l]) {
|
||||
norm += m_U(l, i) * m_U(l, i);
|
||||
}
|
||||
else {
|
||||
N += std::sqrt(norm);
|
||||
norm = m_U(l, i) * m_U(l, i);
|
||||
}
|
||||
prev = m_ytask[l];
|
||||
}
|
||||
N += std::sqrt(norm);
|
||||
for (j = 0; j < m_nq; j++) {
|
||||
for (l = 0, prev = m_ytask[0], norm = e_scalar(0.), mag = e_scalar(0.); l < m_nc; l++) {
|
||||
if (prev == m_ytask[l]) {
|
||||
norm += m_WyAWq(l, j) * m_WyAWq(l, j);
|
||||
}
|
||||
else {
|
||||
mag += std::sqrt(norm);
|
||||
norm = m_WyAWq(l, j) * m_WyAWq(l, j);
|
||||
}
|
||||
prev = m_ytask[l];
|
||||
}
|
||||
mag += std::sqrt(norm);
|
||||
M += fabs(m_V(j, i)) * mag;
|
||||
}
|
||||
M *= Sinv;
|
||||
alpha = m_U.col(i).dot(m_Wy_ydot);
|
||||
_qmax = (N < M) ? m_qmax * N / M : m_qmax;
|
||||
vmax = m_WqV.col(i).array().abs().maxCoeff();
|
||||
norm = fabs(Sinv * alpha * vmax);
|
||||
if (norm > _qmax) {
|
||||
damp = Sinv * alpha * _qmax / norm;
|
||||
}
|
||||
else {
|
||||
damp = Sinv * alpha;
|
||||
}
|
||||
qdot += m_WqV.col(i) * damp;
|
||||
prevS = S;
|
||||
}
|
||||
if (maxDeltaS == e_scalar(0.0))
|
||||
nlcoef = e_scalar(KDL::epsilon);
|
||||
else
|
||||
nlcoef = (maxS - maxDeltaS) / maxS;
|
||||
return true;
|
||||
m_Wy_ydot = Wy.array() * ydot.array();
|
||||
m_WqV.noalias() = Wq*m_V;
|
||||
qdot.setZero();
|
||||
e_scalar maxDeltaS = e_scalar(0.0);
|
||||
e_scalar prevS = e_scalar(0.0);
|
||||
e_scalar maxS = e_scalar(1.0);
|
||||
for(i=0;i<m_ns;++i) {
|
||||
e_scalar norm, mag, alpha, _qmax, Sinv, vmax, damp;
|
||||
e_scalar S = m_S(i);
|
||||
bool prev;
|
||||
if (S < KDL::epsilon)
|
||||
break;
|
||||
Sinv = e_scalar(1.)/S;
|
||||
if (i > 0) {
|
||||
if ((prevS-S) > maxDeltaS) {
|
||||
maxDeltaS = (prevS-S);
|
||||
maxS = prevS;
|
||||
}
|
||||
}
|
||||
N = M = e_scalar(0.);
|
||||
for (l=0, prev=m_ytask[0], norm=e_scalar(0.); l<m_nc; l++) {
|
||||
if (prev == m_ytask[l]) {
|
||||
norm += m_U(l,i)*m_U(l,i);
|
||||
} else {
|
||||
N += std::sqrt(norm);
|
||||
norm = m_U(l,i)*m_U(l,i);
|
||||
}
|
||||
prev = m_ytask[l];
|
||||
}
|
||||
N += std::sqrt(norm);
|
||||
for (j=0; j<m_nq; j++) {
|
||||
for (l=0, prev=m_ytask[0], norm=e_scalar(0.), mag=e_scalar(0.); l<m_nc; l++) {
|
||||
if (prev == m_ytask[l]) {
|
||||
norm += m_WyAWq(l,j)*m_WyAWq(l,j);
|
||||
} else {
|
||||
mag += std::sqrt(norm);
|
||||
norm = m_WyAWq(l,j)*m_WyAWq(l,j);
|
||||
}
|
||||
prev = m_ytask[l];
|
||||
}
|
||||
mag += std::sqrt(norm);
|
||||
M += fabs(m_V(j,i))*mag;
|
||||
}
|
||||
M *= Sinv;
|
||||
alpha = m_U.col(i).dot(m_Wy_ydot);
|
||||
_qmax = (N < M) ? m_qmax*N/M : m_qmax;
|
||||
vmax = m_WqV.col(i).array().abs().maxCoeff();
|
||||
norm = fabs(Sinv*alpha*vmax);
|
||||
if (norm > _qmax) {
|
||||
damp = Sinv*alpha*_qmax/norm;
|
||||
} else {
|
||||
damp = Sinv*alpha;
|
||||
}
|
||||
qdot += m_WqV.col(i)*damp;
|
||||
prevS = S;
|
||||
}
|
||||
if (maxDeltaS == e_scalar(0.0))
|
||||
nlcoef = e_scalar(KDL::epsilon);
|
||||
else
|
||||
nlcoef = (maxS-maxDeltaS)/maxS;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
@@ -13,38 +13,32 @@
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
class WSDLSSolver : public iTaSC::Solver {
|
||||
private:
|
||||
e_matrix m_AWq, m_WyAWq, m_WyAWqt, m_U, m_V, m_WqV;
|
||||
e_vector m_S, m_temp, m_Wy_ydot;
|
||||
std::vector<bool> m_ytask;
|
||||
e_scalar m_qmax;
|
||||
unsigned int m_ns, m_nc, m_nq;
|
||||
bool m_transpose;
|
||||
class WSDLSSolver: public iTaSC::Solver {
|
||||
private:
|
||||
e_matrix m_AWq,m_WyAWq,m_WyAWqt,m_U,m_V,m_WqV;
|
||||
e_vector m_S,m_temp,m_Wy_ydot;
|
||||
std::vector<bool> m_ytask;
|
||||
e_scalar m_qmax;
|
||||
unsigned int m_ns, m_nc, m_nq;
|
||||
bool m_transpose;
|
||||
public:
|
||||
WSDLSSolver();
|
||||
virtual ~WSDLSSolver();
|
||||
|
||||
public:
|
||||
WSDLSSolver();
|
||||
virtual ~WSDLSSolver();
|
||||
|
||||
virtual bool init(unsigned int _nq, unsigned int _nc, const std::vector<bool> &gc);
|
||||
virtual bool solve(const e_matrix &A,
|
||||
const e_vector &Wy,
|
||||
const e_vector &ydot,
|
||||
const e_matrix &Wq,
|
||||
e_vector &qdot,
|
||||
e_scalar &nlcoef);
|
||||
virtual void setParam(SolverParam param, double value)
|
||||
{
|
||||
switch (param) {
|
||||
case DLS_QMAX:
|
||||
m_qmax = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
virtual bool init(unsigned int _nq, unsigned int _nc, const std::vector<bool>& gc);
|
||||
virtual bool solve(const e_matrix& A, const e_vector& Wy, const e_vector& ydot, const e_matrix& Wq, e_vector& qdot, e_scalar& nlcoef);
|
||||
virtual void setParam(SolverParam param, double value)
|
||||
{
|
||||
switch (param) {
|
||||
case DLS_QMAX:
|
||||
m_qmax = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* WSDLSSOLVER_HPP_ */
|
||||
|
||||
@@ -8,17 +8,20 @@
|
||||
|
||||
#include "WorldObject.hpp"
|
||||
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
/* special singleton to be used as base for uncontrolled object */
|
||||
WorldObject Object::world;
|
||||
|
||||
WorldObject::WorldObject() : UncontrolledObject()
|
||||
WorldObject::WorldObject():UncontrolledObject()
|
||||
{
|
||||
initialize(0, 1);
|
||||
m_internalPose = Frame::Identity();
|
||||
initialize(0,1);
|
||||
m_internalPose = Frame::Identity();
|
||||
}
|
||||
|
||||
WorldObject::~WorldObject() {}
|
||||
WorldObject::~WorldObject()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
|
||||
}
|
||||
|
||||
@@ -10,22 +10,22 @@
|
||||
#define WORLDOBJECT_HPP_
|
||||
|
||||
#include "UncontrolledObject.hpp"
|
||||
namespace iTaSC {
|
||||
namespace iTaSC{
|
||||
|
||||
class WorldObject : public UncontrolledObject {
|
||||
public:
|
||||
WorldObject();
|
||||
virtual ~WorldObject();
|
||||
class WorldObject: public UncontrolledObject {
|
||||
public:
|
||||
WorldObject();
|
||||
virtual ~WorldObject();
|
||||
|
||||
virtual void updateCoordinates(const Timestamp & /*timestamp*/){};
|
||||
virtual void updateKinematics(const Timestamp & /*timestamp*/){};
|
||||
virtual void pushCache(const Timestamp & /*timestamp*/){};
|
||||
virtual void initCache(Cache * /*cache*/){};
|
||||
virtual void updateCoordinates(const Timestamp & /*timestamp*/){};
|
||||
virtual void updateKinematics(const Timestamp & /*timestamp*/){};
|
||||
virtual void pushCache(const Timestamp & /*timestamp*/){};
|
||||
virtual void initCache(Cache * /*cache*/){};
|
||||
protected:
|
||||
virtual void updateJacobian() {}
|
||||
|
||||
protected:
|
||||
virtual void updateJacobian() {}
|
||||
};
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
|
||||
#endif /* WORLDOBJECT_H_ */
|
||||
|
||||
@@ -8,4 +8,6 @@
|
||||
|
||||
#include "eigen_types.hpp"
|
||||
|
||||
const KDL::Frame iTaSC::F_identity(Rotation::Identity(), Vector::Zero());
|
||||
const KDL::Frame iTaSC::F_identity(Rotation::Identity(),Vector::Zero());
|
||||
|
||||
|
||||
|
||||
@@ -9,28 +9,29 @@
|
||||
#ifndef EIGEN_TYPES_HPP_
|
||||
#define EIGEN_TYPES_HPP_
|
||||
|
||||
#include "kdl/chain.hpp"
|
||||
#include <Eigen/Core>
|
||||
#include "kdl/frames.hpp"
|
||||
#include "kdl/tree.hpp"
|
||||
#include "kdl/chain.hpp"
|
||||
#include "kdl/jacobian.hpp"
|
||||
#include "kdl/jntarray.hpp"
|
||||
#include "kdl/tree.hpp"
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
using KDL::Chain;
|
||||
namespace iTaSC{
|
||||
|
||||
using KDL::Twist;
|
||||
using KDL::Frame;
|
||||
using KDL::Inertia;
|
||||
using KDL::Jacobian;
|
||||
using KDL::JntArray;
|
||||
using KDL::Joint;
|
||||
using KDL::Rotation;
|
||||
using KDL::Segment;
|
||||
using KDL::Inertia;
|
||||
using KDL::SegmentMap;
|
||||
using KDL::Tree;
|
||||
using KDL::Twist;
|
||||
using KDL::JntArray;
|
||||
using KDL::Jacobian;
|
||||
using KDL::Segment;
|
||||
using KDL::Rotation;
|
||||
using KDL::Vector;
|
||||
using KDL::Vector2;
|
||||
using KDL::Chain;
|
||||
|
||||
extern const Frame F_identity;
|
||||
|
||||
@@ -38,58 +39,47 @@ extern const Frame F_identity;
|
||||
#define e_vector Eigen::Matrix<e_scalar, Eigen::Dynamic, 1>
|
||||
#define e_zero_vector Eigen::Matrix<e_scalar, Eigen::Dynamic, 1>::Zero
|
||||
#define e_matrix Eigen::Matrix<e_scalar, Eigen::Dynamic, Eigen::Dynamic>
|
||||
#define e_matrix6 Eigen::Matrix<e_scalar, 6, 6>
|
||||
#define e_matrix6 Eigen::Matrix<e_scalar,6,6>
|
||||
#define e_identity_matrix Eigen::Matrix<e_scalar, Eigen::Dynamic, Eigen::Dynamic>::Identity
|
||||
#define e_scalar_vector Eigen::Matrix<e_scalar, Eigen::Dynamic, 1>::Constant
|
||||
#define e_zero_matrix Eigen::Matrix<e_scalar, Eigen::Dynamic, Eigen::Dynamic>::Zero
|
||||
#define e_random_matrix Eigen::Matrix<e_scalar, Eigen::Dynamic, Eigen::Dynamic>::Random
|
||||
#define e_vector6 Eigen::Matrix<e_scalar, 6, 1>
|
||||
#define e_vector3 Eigen::Matrix<e_scalar, 3, 1>
|
||||
#define e_vector6 Eigen::Matrix<e_scalar,6,1>
|
||||
#define e_vector3 Eigen::Matrix<e_scalar,3,1>
|
||||
|
||||
class Range {
|
||||
public:
|
||||
int start;
|
||||
int count;
|
||||
Range(int _start, int _count)
|
||||
{
|
||||
start = _start;
|
||||
count = _count;
|
||||
}
|
||||
Range(const Range &other)
|
||||
{
|
||||
start = other.start;
|
||||
count = other.count;
|
||||
}
|
||||
public:
|
||||
int start;
|
||||
int count;
|
||||
Range(int _start, int _count) { start = _start; count=_count; }
|
||||
Range(const Range& other) { start=other.start; count=other.count; }
|
||||
};
|
||||
|
||||
template<typename MatrixType> inline Eigen::Block<MatrixType> project(MatrixType &m, Range r)
|
||||
template<typename MatrixType> inline Eigen::Block<MatrixType> project(MatrixType& m, Range r)
|
||||
{
|
||||
return Eigen::Block<MatrixType>(m, r.start, 0, r.count, 1);
|
||||
return Eigen::Block<MatrixType>(m,r.start,0,r.count,1);
|
||||
}
|
||||
|
||||
template<typename MatrixType>
|
||||
inline Eigen::Block<MatrixType> project(MatrixType &m, Range r, Range c)
|
||||
template<typename MatrixType> inline Eigen::Block<MatrixType> project(MatrixType& m, Range r, Range c)
|
||||
{
|
||||
return Eigen::Block<MatrixType>(m, r.start, c.start, r.count, c.count);
|
||||
return Eigen::Block<MatrixType>(m,r.start,c.start,r.count,c.count);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
inline static int changeBase(Eigen::MatrixBase<Derived> &J, const Frame &T)
|
||||
{
|
||||
template<typename Derived> inline static int changeBase(Eigen::MatrixBase<Derived>& J, const Frame& T) {
|
||||
|
||||
if (J.rows() != 6)
|
||||
return -1;
|
||||
for (int j = 0; j < J.cols(); ++j) {
|
||||
typename Derived::ColXpr Jj = J.col(j);
|
||||
Twist arg;
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
arg(i) = Jj[i];
|
||||
Twist tmp(T * arg);
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
Jj[i] = e_scalar(tmp(i));
|
||||
}
|
||||
return 0;
|
||||
if (J.rows() != 6)
|
||||
return -1;
|
||||
for (int j = 0; j < J.cols(); ++j) {
|
||||
typename Derived::ColXpr Jj = J.col(j);
|
||||
Twist arg;
|
||||
for(unsigned int i=0;i<6;++i)
|
||||
arg(i)=Jj[i];
|
||||
Twist tmp(T*arg);
|
||||
for(unsigned int i=0;i<6;++i)
|
||||
Jj[i]=e_scalar(tmp(i));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
#endif /* UBLAS_TYPES_HPP_ */
|
||||
|
||||
@@ -25,44 +25,54 @@
|
||||
#include "chain.hpp"
|
||||
|
||||
namespace KDL {
|
||||
using namespace std;
|
||||
using namespace std;
|
||||
|
||||
Chain::Chain() : segments(0), nrOfJoints(0), nrOfSegments(0) {}
|
||||
Chain::Chain():
|
||||
segments(0),
|
||||
nrOfJoints(0),
|
||||
nrOfSegments(0)
|
||||
{
|
||||
}
|
||||
|
||||
Chain::Chain(const Chain& in):nrOfJoints(0),
|
||||
nrOfSegments(0)
|
||||
{
|
||||
for(unsigned int i=0;i<in.getNrOfSegments();i++)
|
||||
this->addSegment(in.getSegment(i));
|
||||
}
|
||||
|
||||
Chain& Chain::operator=(const Chain& arg)
|
||||
{
|
||||
nrOfJoints=0;
|
||||
nrOfSegments=0;
|
||||
segments.resize(0);
|
||||
for(unsigned int i=0;i<arg.nrOfSegments;i++)
|
||||
addSegment(arg.getSegment(i));
|
||||
return *this;
|
||||
|
||||
}
|
||||
|
||||
void Chain::addSegment(const Segment& segment)
|
||||
{
|
||||
segments.push_back(segment);
|
||||
nrOfSegments++;
|
||||
nrOfJoints += segment.getJoint().getNDof();
|
||||
}
|
||||
|
||||
void Chain::addChain(const Chain& chain)
|
||||
{
|
||||
for(unsigned int i=0;i<chain.getNrOfSegments();i++)
|
||||
this->addSegment(chain.getSegment(i));
|
||||
}
|
||||
|
||||
const Segment& Chain::getSegment(unsigned int nr) const
|
||||
{
|
||||
return segments[nr];
|
||||
}
|
||||
|
||||
Chain::~Chain()
|
||||
{
|
||||
}
|
||||
|
||||
Chain::Chain(const Chain &in) : nrOfJoints(0), nrOfSegments(0)
|
||||
{
|
||||
for (unsigned int i = 0; i < in.getNrOfSegments(); i++)
|
||||
this->addSegment(in.getSegment(i));
|
||||
}
|
||||
|
||||
Chain &Chain::operator=(const Chain &arg)
|
||||
{
|
||||
nrOfJoints = 0;
|
||||
nrOfSegments = 0;
|
||||
segments.resize(0);
|
||||
for (unsigned int i = 0; i < arg.nrOfSegments; i++)
|
||||
addSegment(arg.getSegment(i));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Chain::addSegment(const Segment &segment)
|
||||
{
|
||||
segments.push_back(segment);
|
||||
nrOfSegments++;
|
||||
nrOfJoints += segment.getJoint().getNDof();
|
||||
}
|
||||
|
||||
void Chain::addChain(const Chain &chain)
|
||||
{
|
||||
for (unsigned int i = 0; i < chain.getNrOfSegments(); i++)
|
||||
this->addSegment(chain.getSegment(i));
|
||||
}
|
||||
|
||||
const Segment &Chain::getSegment(unsigned int nr) const
|
||||
{
|
||||
return segments[nr];
|
||||
}
|
||||
|
||||
Chain::~Chain() {}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
@@ -23,80 +23,75 @@
|
||||
#define KDL_CHAIN_HPP
|
||||
|
||||
#include "segment.hpp"
|
||||
#include <Eigen/StdVector>
|
||||
#include <string>
|
||||
#include <Eigen/StdVector>
|
||||
|
||||
namespace KDL {
|
||||
/**
|
||||
* \brief This class encapsulates a <strong>serial</strong> kinematic
|
||||
* interconnection structure. It is build out of segments.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class Chain {
|
||||
private:
|
||||
// Eigen allocator is needed for alignment of Eigen data types
|
||||
std::vector<Segment, Eigen::aligned_allocator<Segment>> segments;
|
||||
unsigned int nrOfJoints;
|
||||
unsigned int nrOfSegments;
|
||||
/**
|
||||
* \brief This class encapsulates a <strong>serial</strong> kinematic
|
||||
* interconnection structure. It is build out of segments.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class Chain {
|
||||
private:
|
||||
// Eigen allocator is needed for alignment of Eigen data types
|
||||
std::vector<Segment, Eigen::aligned_allocator<Segment> > segments;
|
||||
unsigned int nrOfJoints;
|
||||
unsigned int nrOfSegments;
|
||||
public:
|
||||
/**
|
||||
* The constructor of a chain, a new chain is always empty.
|
||||
*
|
||||
*/
|
||||
Chain();
|
||||
Chain(const Chain& in);
|
||||
Chain& operator = (const Chain& arg);
|
||||
|
||||
public:
|
||||
/**
|
||||
* The constructor of a chain, a new chain is always empty.
|
||||
*
|
||||
*/
|
||||
Chain();
|
||||
Chain(const Chain &in);
|
||||
Chain &operator=(const Chain &arg);
|
||||
/**
|
||||
* Adds a new segment to the <strong>end</strong> of the chain.
|
||||
*
|
||||
* @param segment The segment to add
|
||||
*/
|
||||
void addSegment(const Segment& segment);
|
||||
/**
|
||||
* Adds a complete chain to the <strong>end</strong> of the chain
|
||||
* The added chain is copied.
|
||||
*
|
||||
* @param chain The chain to add
|
||||
*/
|
||||
void addChain(const Chain& chain);
|
||||
|
||||
/**
|
||||
* Adds a new segment to the <strong>end</strong> of the chain.
|
||||
*
|
||||
* @param segment The segment to add
|
||||
*/
|
||||
void addSegment(const Segment &segment);
|
||||
/**
|
||||
* Adds a complete chain to the <strong>end</strong> of the chain
|
||||
* The added chain is copied.
|
||||
*
|
||||
* @param chain The chain to add
|
||||
*/
|
||||
void addChain(const Chain &chain);
|
||||
/**
|
||||
* Request the total number of joints in the chain.\n
|
||||
* <strong> Important:</strong> It is not the
|
||||
* same as the total number of segments since a segment does not
|
||||
* need to have a joint. This function is important when
|
||||
* creating a KDL::JntArray to use with this chain.
|
||||
* @return total nr of joints
|
||||
*/
|
||||
unsigned int getNrOfJoints()const {return nrOfJoints;};
|
||||
/**
|
||||
* Request the total number of segments in the chain.
|
||||
* @return total number of segments
|
||||
*/
|
||||
unsigned int getNrOfSegments()const {return nrOfSegments;};
|
||||
|
||||
/**
|
||||
* Request the total number of joints in the chain.\n
|
||||
* <strong> Important:</strong> It is not the
|
||||
* same as the total number of segments since a segment does not
|
||||
* need to have a joint. This function is important when
|
||||
* creating a KDL::JntArray to use with this chain.
|
||||
* @return total nr of joints
|
||||
*/
|
||||
unsigned int getNrOfJoints() const
|
||||
{
|
||||
return nrOfJoints;
|
||||
};
|
||||
/**
|
||||
* Request the total number of segments in the chain.
|
||||
* @return total number of segments
|
||||
*/
|
||||
unsigned int getNrOfSegments() const
|
||||
{
|
||||
return nrOfSegments;
|
||||
};
|
||||
/**
|
||||
* Request the nr'd segment of the chain. There is no boundary
|
||||
* checking.
|
||||
*
|
||||
* @param nr the nr of the segment starting from 0
|
||||
*
|
||||
* @return a constant reference to the nr'd segment
|
||||
*/
|
||||
const Segment& getSegment(unsigned int nr)const;
|
||||
|
||||
/**
|
||||
* Request the nr'd segment of the chain. There is no boundary
|
||||
* checking.
|
||||
*
|
||||
* @param nr the nr of the segment starting from 0
|
||||
*
|
||||
* @return a constant reference to the nr'd segment
|
||||
*/
|
||||
const Segment &getSegment(unsigned int nr) const;
|
||||
virtual ~Chain();
|
||||
};
|
||||
|
||||
virtual ~Chain();
|
||||
};
|
||||
|
||||
} // end of namespace KDL
|
||||
|
||||
}//end of namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,84 +23,85 @@
|
||||
#define KDL_CHAIN_FKSOLVER_HPP
|
||||
|
||||
#include "chain.hpp"
|
||||
#include "frameacc.hpp"
|
||||
#include "framevel.hpp"
|
||||
#include "frameacc.hpp"
|
||||
#include "jntarray.hpp"
|
||||
#include "jntarrayacc.hpp"
|
||||
#include "jntarrayvel.hpp"
|
||||
#include "jntarrayacc.hpp"
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a
|
||||
* solver for the forward position kinematics for a KDL::Chain.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a
|
||||
* solver for the forward position kinematics for a KDL::Chain.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
|
||||
// Forward definition
|
||||
class ChainFkSolverPos {
|
||||
public:
|
||||
/**
|
||||
* Calculate forward position kinematics for a KDL::Chain,
|
||||
* from joint coordinates to cartesian pose.
|
||||
*
|
||||
* @param q_in input joint coordinates
|
||||
* @param p_out reference to output cartesian pose
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
virtual int JntToCart(const JntArray &q_in, Frame &p_out, int segmentNr = -1) = 0;
|
||||
virtual ~ChainFkSolverPos(){};
|
||||
};
|
||||
//Forward definition
|
||||
class ChainFkSolverPos {
|
||||
public:
|
||||
/**
|
||||
* Calculate forward position kinematics for a KDL::Chain,
|
||||
* from joint coordinates to cartesian pose.
|
||||
*
|
||||
* @param q_in input joint coordinates
|
||||
* @param p_out reference to output cartesian pose
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
virtual int JntToCart(const JntArray& q_in, Frame& p_out,int segmentNr=-1)=0;
|
||||
virtual ~ChainFkSolverPos(){};
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a solver
|
||||
* for the forward velocity kinematics for a KDL::Chain.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class ChainFkSolverVel {
|
||||
public:
|
||||
/**
|
||||
* Calculate forward position and velocity kinematics, from
|
||||
* joint coordinates to cartesian coordinates.
|
||||
*
|
||||
* @param q_in input joint coordinates (position and velocity)
|
||||
* @param out output cartesian coordinates (position and velocity)
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
virtual int JntToCart(const JntArrayVel &q_in, FrameVel &out, int segmentNr = -1) = 0;
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a solver
|
||||
* for the forward velocity kinematics for a KDL::Chain.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class ChainFkSolverVel {
|
||||
public:
|
||||
/**
|
||||
* Calculate forward position and velocity kinematics, from
|
||||
* joint coordinates to cartesian coordinates.
|
||||
*
|
||||
* @param q_in input joint coordinates (position and velocity)
|
||||
* @param out output cartesian coordinates (position and velocity)
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
virtual int JntToCart(const JntArrayVel& q_in, FrameVel& out,int segmentNr=-1)=0;
|
||||
|
||||
virtual ~ChainFkSolverVel(){};
|
||||
};
|
||||
virtual ~ChainFkSolverVel(){};
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a solver
|
||||
* for the forward acceleration kinematics for a KDL::Chain.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a solver
|
||||
* for the forward acceleration kinematics for a KDL::Chain.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
|
||||
class ChainFkSolverAcc {
|
||||
public:
|
||||
/**
|
||||
* Calculate forward position, velocity and accelaration
|
||||
* kinematics, from joint coordinates to cartesian coordinates
|
||||
*
|
||||
* @param q_in input joint coordinates (position, velocity and
|
||||
* acceleration
|
||||
@param out output cartesian coordinates (position, velocity
|
||||
* and acceleration
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
virtual int JntToCart(const JntArrayAcc &q_in, FrameAcc &out, int segmentNr = -1) = 0;
|
||||
class ChainFkSolverAcc {
|
||||
public:
|
||||
/**
|
||||
* Calculate forward position, velocity and accelaration
|
||||
* kinematics, from joint coordinates to cartesian coordinates
|
||||
*
|
||||
* @param q_in input joint coordinates (position, velocity and
|
||||
* acceleration
|
||||
@param out output cartesian coordinates (position, velocity
|
||||
* and acceleration
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
virtual int JntToCart(const JntArrayAcc& q_in, FrameAcc& out,int segmentNr=-1)=0;
|
||||
|
||||
virtual ~ChainFkSolverAcc() = 0;
|
||||
};
|
||||
virtual ~ChainFkSolverAcc()=0;
|
||||
};
|
||||
|
||||
} // end of namespace KDL
|
||||
|
||||
}//end of namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,30 +28,37 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
ChainFkSolverPos_recursive::ChainFkSolverPos_recursive(const Chain &_chain) : chain(_chain) {}
|
||||
|
||||
int ChainFkSolverPos_recursive::JntToCart(const JntArray &q_in, Frame &p_out, int segmentNr)
|
||||
{
|
||||
unsigned int segNr = (unsigned int)segmentNr;
|
||||
if (segmentNr < 0)
|
||||
segNr = chain.getNrOfSegments();
|
||||
|
||||
p_out = Frame::Identity();
|
||||
|
||||
if (q_in.rows() != chain.getNrOfJoints())
|
||||
return -1;
|
||||
else if (segNr > chain.getNrOfSegments())
|
||||
return -1;
|
||||
else {
|
||||
int j = 0;
|
||||
for (unsigned int i = 0; i < segNr; i++) {
|
||||
p_out = p_out * chain.getSegment(i).pose(((JntArray &)q_in)(j));
|
||||
j += chain.getSegment(i).getJoint().getNDof();
|
||||
ChainFkSolverPos_recursive::ChainFkSolverPos_recursive(const Chain& _chain):
|
||||
chain(_chain)
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ChainFkSolverPos_recursive::JntToCart(const JntArray& q_in, Frame& p_out, int segmentNr)
|
||||
{
|
||||
unsigned int segNr = (unsigned int)segmentNr;
|
||||
if(segmentNr<0)
|
||||
segNr=chain.getNrOfSegments();
|
||||
|
||||
p_out = Frame::Identity();
|
||||
|
||||
if(q_in.rows()!=chain.getNrOfJoints())
|
||||
return -1;
|
||||
else if(segNr>chain.getNrOfSegments())
|
||||
return -1;
|
||||
else{
|
||||
int j=0;
|
||||
for(unsigned int i=0;i<segNr;i++){
|
||||
p_out = p_out*chain.getSegment(i).pose(((JntArray&)q_in)(j));
|
||||
j+=chain.getSegment(i).getJoint().getNDof();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ChainFkSolverPos_recursive::~ChainFkSolverPos_recursive()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
ChainFkSolverPos_recursive::~ChainFkSolverPos_recursive() {}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
@@ -26,24 +26,25 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/**
|
||||
* Implementation of a recursive forward position kinematics
|
||||
* algorithm to calculate the position transformation from joint
|
||||
* space to Cartesian space of a general kinematic chain (KDL::Chain).
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class ChainFkSolverPos_recursive : public ChainFkSolverPos {
|
||||
public:
|
||||
ChainFkSolverPos_recursive(const Chain &chain);
|
||||
~ChainFkSolverPos_recursive();
|
||||
/**
|
||||
* Implementation of a recursive forward position kinematics
|
||||
* algorithm to calculate the position transformation from joint
|
||||
* space to Cartesian space of a general kinematic chain (KDL::Chain).
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class ChainFkSolverPos_recursive : public ChainFkSolverPos
|
||||
{
|
||||
public:
|
||||
ChainFkSolverPos_recursive(const Chain& chain);
|
||||
~ChainFkSolverPos_recursive();
|
||||
|
||||
virtual int JntToCart(const JntArray &q_in, Frame &p_out, int segmentNr = -1);
|
||||
virtual int JntToCart(const JntArray& q_in, Frame& p_out, int segmentNr=-1);
|
||||
|
||||
private:
|
||||
const Chain chain;
|
||||
};
|
||||
private:
|
||||
const Chain chain;
|
||||
};
|
||||
|
||||
} // namespace KDL
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,51 +24,60 @@
|
||||
|
||||
#include "chainjnttojacsolver.hpp"
|
||||
|
||||
namespace KDL {
|
||||
ChainJntToJacSolver::ChainJntToJacSolver(const Chain &_chain) : chain(_chain) {}
|
||||
|
||||
ChainJntToJacSolver::~ChainJntToJacSolver() {}
|
||||
|
||||
int ChainJntToJacSolver::JntToJac(const JntArray &q_in, Jacobian &jac)
|
||||
namespace KDL
|
||||
{
|
||||
assert(q_in.rows() == chain.getNrOfJoints() && q_in.rows() == jac.columns());
|
||||
|
||||
Frame T_local, T_joint;
|
||||
T_total = Frame::Identity();
|
||||
SetToZero(t_local);
|
||||
|
||||
int i = chain.getNrOfSegments() - 1;
|
||||
unsigned int q_nr = chain.getNrOfJoints();
|
||||
|
||||
// Lets recursively iterate until we are in the root segment
|
||||
while (i >= 0) {
|
||||
const Segment &segment = chain.getSegment(i);
|
||||
int ndof = segment.getJoint().getNDof();
|
||||
q_nr -= ndof;
|
||||
|
||||
// get the pose of the joint.
|
||||
T_joint = segment.getJoint().pose(((JntArray &)q_in)(q_nr));
|
||||
// combine with the tip to have the tip pose
|
||||
T_local = T_joint * segment.getFrameToTip();
|
||||
// calculate new T_end:
|
||||
T_total = T_local * T_total;
|
||||
|
||||
for (int dof = 0; dof < ndof; dof++) {
|
||||
// combine joint rotation with tip position to get a reference frame for the joint
|
||||
T_joint.p = T_local.p;
|
||||
// in which the twist can be computed (needed for NDof joint)
|
||||
t_local = segment.twist(T_joint, 1.0, dof);
|
||||
// transform the endpoint of the local twist to the global endpoint:
|
||||
t_local = t_local.RefPoint(T_total.p - T_local.p);
|
||||
// transform the base of the twist to the endpoint
|
||||
t_local = T_total.M.Inverse(t_local);
|
||||
// store the twist in the jacobian:
|
||||
jac.twists[q_nr + dof] = t_local;
|
||||
ChainJntToJacSolver::ChainJntToJacSolver(const Chain& _chain):
|
||||
chain(_chain)
|
||||
{
|
||||
}
|
||||
|
||||
ChainJntToJacSolver::~ChainJntToJacSolver()
|
||||
{
|
||||
}
|
||||
|
||||
int ChainJntToJacSolver::JntToJac(const JntArray& q_in,Jacobian& jac)
|
||||
{
|
||||
assert(q_in.rows()==chain.getNrOfJoints()&&
|
||||
q_in.rows()==jac.columns());
|
||||
|
||||
|
||||
Frame T_local, T_joint;
|
||||
T_total = Frame::Identity();
|
||||
SetToZero(t_local);
|
||||
|
||||
int i=chain.getNrOfSegments()-1;
|
||||
unsigned int q_nr = chain.getNrOfJoints();
|
||||
|
||||
//Lets recursively iterate until we are in the root segment
|
||||
while (i >= 0) {
|
||||
const Segment& segment = chain.getSegment(i);
|
||||
int ndof = segment.getJoint().getNDof();
|
||||
q_nr -= ndof;
|
||||
|
||||
//get the pose of the joint.
|
||||
T_joint = segment.getJoint().pose(((JntArray&)q_in)(q_nr));
|
||||
// combine with the tip to have the tip pose
|
||||
T_local = T_joint*segment.getFrameToTip();
|
||||
//calculate new T_end:
|
||||
T_total = T_local * T_total;
|
||||
|
||||
for (int dof=0; dof<ndof; dof++) {
|
||||
// combine joint rotation with tip position to get a reference frame for the joint
|
||||
T_joint.p = T_local.p;
|
||||
// in which the twist can be computed (needed for NDof joint)
|
||||
t_local = segment.twist(T_joint, 1.0, dof);
|
||||
//transform the endpoint of the local twist to the global endpoint:
|
||||
t_local = t_local.RefPoint(T_total.p - T_local.p);
|
||||
//transform the base of the twist to the endpoint
|
||||
t_local = T_total.M.Inverse(t_local);
|
||||
//store the twist in the jacobian:
|
||||
jac.twists[q_nr+dof] = t_local;
|
||||
}
|
||||
i--;
|
||||
}//endwhile
|
||||
//Change the base of the complete jacobian from the endpoint to the base
|
||||
changeBase(jac, T_total.M, jac);
|
||||
return 0;
|
||||
}
|
||||
i--;
|
||||
} // endwhile
|
||||
// Change the base of the complete jacobian from the endpoint to the base
|
||||
changeBase(jac, T_total.M, jac);
|
||||
return 0;
|
||||
}
|
||||
} // namespace KDL
|
||||
|
||||
|
||||
@@ -22,41 +22,44 @@
|
||||
#ifndef KDL_CHAINJNTTOJACSOLVER_HPP
|
||||
#define KDL_CHAINJNTTOJACSOLVER_HPP
|
||||
|
||||
#include "chain.hpp"
|
||||
#include "frames.hpp"
|
||||
#include "jacobian.hpp"
|
||||
#include "jntarray.hpp"
|
||||
#include "chain.hpp"
|
||||
|
||||
namespace KDL {
|
||||
/**
|
||||
* @brief Class to calculate the jacobian of a general
|
||||
* KDL::Chain, it is used by other solvers. It should not be used
|
||||
* outside of KDL.
|
||||
*
|
||||
*
|
||||
*/
|
||||
namespace KDL
|
||||
{
|
||||
/**
|
||||
* @brief Class to calculate the jacobian of a general
|
||||
* KDL::Chain, it is used by other solvers. It should not be used
|
||||
* outside of KDL.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
class ChainJntToJacSolver {
|
||||
public:
|
||||
ChainJntToJacSolver(const Chain &chain);
|
||||
~ChainJntToJacSolver();
|
||||
/**
|
||||
* Calculate the jacobian expressed in the base frame of the
|
||||
* chain, with reference point at the end effector of the
|
||||
* *chain. The alghoritm is similar to the one used in
|
||||
* KDL::ChainFkSolverVel_recursive
|
||||
*
|
||||
* @param q_in input joint positions
|
||||
* @param jac output jacobian
|
||||
*
|
||||
* @return always returns 0
|
||||
*/
|
||||
int JntToJac(const JntArray &q_in, Jacobian &jac);
|
||||
class ChainJntToJacSolver
|
||||
{
|
||||
public:
|
||||
ChainJntToJacSolver(const Chain& chain);
|
||||
~ChainJntToJacSolver();
|
||||
/**
|
||||
* Calculate the jacobian expressed in the base frame of the
|
||||
* chain, with reference point at the end effector of the
|
||||
* *chain. The alghoritm is similar to the one used in
|
||||
* KDL::ChainFkSolverVel_recursive
|
||||
*
|
||||
* @param q_in input joint positions
|
||||
* @param jac output jacobian
|
||||
*
|
||||
* @return always returns 0
|
||||
*/
|
||||
int JntToJac(const JntArray& q_in,Jacobian& jac);
|
||||
|
||||
private:
|
||||
const Chain chain;
|
||||
Twist t_local;
|
||||
Frame T_total;
|
||||
};
|
||||
} // namespace KDL
|
||||
private:
|
||||
const Chain chain;
|
||||
Twist t_local;
|
||||
Frame T_total;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -14,12 +14,14 @@
|
||||
* $Name: $
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "frameacc.hpp"
|
||||
|
||||
namespace KDL {
|
||||
|
||||
#ifndef KDL_INLINE
|
||||
# include "frameacc.inl"
|
||||
#include "frameacc.inl"
|
||||
#endif
|
||||
|
||||
} // namespace KDL
|
||||
}
|
||||
|
||||
|
||||
@@ -27,210 +27,240 @@
|
||||
#ifndef RRFRAMES_H
|
||||
#define RRFRAMES_H
|
||||
|
||||
#include "frames.hpp"
|
||||
|
||||
#include "utilities/rall2d.h"
|
||||
#include "frames.hpp"
|
||||
|
||||
|
||||
|
||||
namespace KDL {
|
||||
|
||||
class TwistAcc;
|
||||
typedef Rall2d<double, double, double> doubleAcc;
|
||||
typedef Rall2d<double,double,double> doubleAcc;
|
||||
|
||||
class VectorAcc {
|
||||
public:
|
||||
Vector p; //!< position vector
|
||||
Vector v; //!< velocity vector
|
||||
Vector dv; //!< acceleration vector
|
||||
public:
|
||||
VectorAcc() : p(), v(), dv() {}
|
||||
explicit VectorAcc(const Vector &_p) : p(_p), v(Vector::Zero()), dv(Vector::Zero()) {}
|
||||
VectorAcc(const Vector &_p, const Vector &_v) : p(_p), v(_v), dv(Vector::Zero()) {}
|
||||
VectorAcc(const Vector &_p, const Vector &_v, const Vector &_dv) : p(_p), v(_v), dv(_dv) {}
|
||||
IMETHOD VectorAcc &operator=(const VectorAcc &arg);
|
||||
IMETHOD VectorAcc &operator=(const Vector &arg);
|
||||
IMETHOD VectorAcc &operator+=(const VectorAcc &arg);
|
||||
IMETHOD VectorAcc &operator-=(const VectorAcc &arg);
|
||||
IMETHOD static VectorAcc Zero();
|
||||
IMETHOD void ReverseSign();
|
||||
IMETHOD doubleAcc Norm();
|
||||
IMETHOD friend VectorAcc operator+(const VectorAcc &r1, const VectorAcc &r2);
|
||||
IMETHOD friend VectorAcc operator-(const VectorAcc &r1, const VectorAcc &r2);
|
||||
IMETHOD friend VectorAcc operator+(const Vector &r1, const VectorAcc &r2);
|
||||
IMETHOD friend VectorAcc operator-(const Vector &r1, const VectorAcc &r2);
|
||||
IMETHOD friend VectorAcc operator+(const VectorAcc &r1, const Vector &r2);
|
||||
IMETHOD friend VectorAcc operator-(const VectorAcc &r1, const Vector &r2);
|
||||
IMETHOD friend VectorAcc operator*(const VectorAcc &r1, const VectorAcc &r2);
|
||||
IMETHOD friend VectorAcc operator*(const VectorAcc &r1, const Vector &r2);
|
||||
IMETHOD friend VectorAcc operator*(const Vector &r1, const VectorAcc &r2);
|
||||
IMETHOD friend VectorAcc operator*(const VectorAcc &r1, double r2);
|
||||
IMETHOD friend VectorAcc operator*(double r1, const VectorAcc &r2);
|
||||
IMETHOD friend VectorAcc operator*(const doubleAcc &r1, const VectorAcc &r2);
|
||||
IMETHOD friend VectorAcc operator*(const VectorAcc &r2, const doubleAcc &r1);
|
||||
IMETHOD friend VectorAcc operator*(const Rotation &R, const VectorAcc &x);
|
||||
|
||||
IMETHOD friend VectorAcc operator/(const VectorAcc &r1, double r2);
|
||||
IMETHOD friend VectorAcc operator/(const VectorAcc &r2, const doubleAcc &r1);
|
||||
class VectorAcc
|
||||
{
|
||||
public:
|
||||
Vector p; //!< position vector
|
||||
Vector v; //!< velocity vector
|
||||
Vector dv; //!< acceleration vector
|
||||
public:
|
||||
VectorAcc():p(),v(),dv() {}
|
||||
explicit VectorAcc(const Vector& _p):p(_p),v(Vector::Zero()),dv(Vector::Zero()) {}
|
||||
VectorAcc(const Vector& _p,const Vector& _v):p(_p),v(_v),dv(Vector::Zero()) {}
|
||||
VectorAcc(const Vector& _p,const Vector& _v,const Vector& _dv):
|
||||
p(_p),v(_v),dv(_dv) {}
|
||||
IMETHOD VectorAcc& operator = (const VectorAcc& arg);
|
||||
IMETHOD VectorAcc& operator = (const Vector& arg);
|
||||
IMETHOD VectorAcc& operator += (const VectorAcc& arg);
|
||||
IMETHOD VectorAcc& operator -= (const VectorAcc& arg);
|
||||
IMETHOD static VectorAcc Zero();
|
||||
IMETHOD void ReverseSign();
|
||||
IMETHOD doubleAcc Norm();
|
||||
IMETHOD friend VectorAcc operator + (const VectorAcc& r1,const VectorAcc& r2);
|
||||
IMETHOD friend VectorAcc operator - (const VectorAcc& r1,const VectorAcc& r2);
|
||||
IMETHOD friend VectorAcc operator + (const Vector& r1,const VectorAcc& r2);
|
||||
IMETHOD friend VectorAcc operator - (const Vector& r1,const VectorAcc& r2);
|
||||
IMETHOD friend VectorAcc operator + (const VectorAcc& r1,const Vector& r2);
|
||||
IMETHOD friend VectorAcc operator - (const VectorAcc& r1,const Vector& r2);
|
||||
IMETHOD friend VectorAcc operator * (const VectorAcc& r1,const VectorAcc& r2);
|
||||
IMETHOD friend VectorAcc operator * (const VectorAcc& r1,const Vector& r2);
|
||||
IMETHOD friend VectorAcc operator * (const Vector& r1,const VectorAcc& r2);
|
||||
IMETHOD friend VectorAcc operator * (const VectorAcc& r1,double r2);
|
||||
IMETHOD friend VectorAcc operator * (double r1,const VectorAcc& r2);
|
||||
IMETHOD friend VectorAcc operator * (const doubleAcc& r1,const VectorAcc& r2);
|
||||
IMETHOD friend VectorAcc operator * (const VectorAcc& r2,const doubleAcc& r1);
|
||||
IMETHOD friend VectorAcc operator*(const Rotation& R,const VectorAcc& x);
|
||||
|
||||
IMETHOD friend bool Equal(const VectorAcc &r1, const VectorAcc &r2, double eps);
|
||||
IMETHOD friend bool Equal(const Vector &r1, const VectorAcc &r2, double eps);
|
||||
IMETHOD friend bool Equal(const VectorAcc &r1, const Vector &r2, double eps);
|
||||
IMETHOD friend VectorAcc operator-(const VectorAcc &r);
|
||||
IMETHOD friend doubleAcc dot(const VectorAcc &lhs, const VectorAcc &rhs);
|
||||
IMETHOD friend doubleAcc dot(const VectorAcc &lhs, const Vector &rhs);
|
||||
IMETHOD friend doubleAcc dot(const Vector &lhs, const VectorAcc &rhs);
|
||||
IMETHOD friend VectorAcc operator / (const VectorAcc& r1,double r2);
|
||||
IMETHOD friend VectorAcc operator / (const VectorAcc& r2,const doubleAcc& r1);
|
||||
|
||||
|
||||
IMETHOD friend bool Equal(const VectorAcc& r1,const VectorAcc& r2,double eps);
|
||||
IMETHOD friend bool Equal(const Vector& r1,const VectorAcc& r2,double eps);
|
||||
IMETHOD friend bool Equal(const VectorAcc& r1,const Vector& r2,double eps);
|
||||
IMETHOD friend VectorAcc operator - (const VectorAcc& r);
|
||||
IMETHOD friend doubleAcc dot(const VectorAcc& lhs,const VectorAcc& rhs);
|
||||
IMETHOD friend doubleAcc dot(const VectorAcc& lhs,const Vector& rhs);
|
||||
IMETHOD friend doubleAcc dot(const Vector& lhs,const VectorAcc& rhs);
|
||||
};
|
||||
|
||||
class RotationAcc {
|
||||
public:
|
||||
Rotation R; //!< rotation matrix
|
||||
Vector w; //!< angular velocity vector
|
||||
Vector dw; //!< angular acceration vector
|
||||
public:
|
||||
RotationAcc() : R(), w() {}
|
||||
explicit RotationAcc(const Rotation &R_) : R(R_), w(Vector::Zero()) {}
|
||||
RotationAcc(const Rotation &R_, const Vector &_w, const Vector &_dw) : R(R_), w(_w), dw(_dw) {}
|
||||
IMETHOD RotationAcc &operator=(const RotationAcc &arg);
|
||||
IMETHOD RotationAcc &operator=(const Rotation &arg);
|
||||
IMETHOD static RotationAcc Identity();
|
||||
IMETHOD RotationAcc Inverse() const;
|
||||
IMETHOD VectorAcc Inverse(const VectorAcc &arg) const;
|
||||
IMETHOD VectorAcc Inverse(const Vector &arg) const;
|
||||
IMETHOD VectorAcc operator*(const VectorAcc &arg) const;
|
||||
IMETHOD VectorAcc operator*(const Vector &arg) const;
|
||||
|
||||
// Rotations
|
||||
// The SetRot.. functions set the value of *this to the appropriate rotation matrix.
|
||||
// The Rot... static functions give the value of the appropriate rotation matrix back.
|
||||
// The DoRot... functions apply a rotation R to *this,such that *this = *this * R.
|
||||
// IMETHOD void DoRotX(const doubleAcc& angle);
|
||||
// IMETHOD void DoRotY(const doubleAcc& angle);
|
||||
// IMETHOD void DoRotZ(const doubleAcc& angle);
|
||||
// IMETHOD static RRotation RotX(const doubleAcc& angle);
|
||||
// IMETHOD static RRotation RotY(const doubleAcc& angle);
|
||||
// IMETHOD static RRotation RotZ(const doubleAcc& angle);
|
||||
|
||||
// IMETHOD void SetRot(const Vector& rotaxis,const doubleAcc& angle);
|
||||
// Along an arbitrary axes. The norm of rotvec is neglected.
|
||||
// IMETHOD static RotationAcc Rot(const Vector& rotvec,const doubleAcc& angle);
|
||||
// rotvec has arbitrary norm
|
||||
// rotation around a constant vector !
|
||||
// IMETHOD static RotationAcc Rot2(const Vector& rotvec,const doubleAcc& angle);
|
||||
// rotvec is normalized.
|
||||
// rotation around a constant vector !
|
||||
class RotationAcc
|
||||
{
|
||||
public:
|
||||
Rotation R; //!< rotation matrix
|
||||
Vector w; //!< angular velocity vector
|
||||
Vector dw; //!< angular acceration vector
|
||||
public:
|
||||
RotationAcc():R(),w() {}
|
||||
explicit RotationAcc(const Rotation& R_):R(R_),w(Vector::Zero()){}
|
||||
RotationAcc(const Rotation& R_,const Vector& _w,const Vector& _dw):
|
||||
R(R_),w(_w),dw(_dw) {}
|
||||
IMETHOD RotationAcc& operator = (const RotationAcc& arg);
|
||||
IMETHOD RotationAcc& operator = (const Rotation& arg);
|
||||
IMETHOD static RotationAcc Identity();
|
||||
IMETHOD RotationAcc Inverse() const;
|
||||
IMETHOD VectorAcc Inverse(const VectorAcc& arg) const;
|
||||
IMETHOD VectorAcc Inverse(const Vector& arg) const;
|
||||
IMETHOD VectorAcc operator*(const VectorAcc& arg) const;
|
||||
IMETHOD VectorAcc operator*(const Vector& arg) const;
|
||||
|
||||
IMETHOD friend RotationAcc operator*(const RotationAcc &r1, const RotationAcc &r2);
|
||||
IMETHOD friend RotationAcc operator*(const Rotation &r1, const RotationAcc &r2);
|
||||
IMETHOD friend RotationAcc operator*(const RotationAcc &r1, const Rotation &r2);
|
||||
IMETHOD friend bool Equal(const RotationAcc &r1, const RotationAcc &r2, double eps);
|
||||
IMETHOD friend bool Equal(const Rotation &r1, const RotationAcc &r2, double eps);
|
||||
IMETHOD friend bool Equal(const RotationAcc &r1, const Rotation &r2, double eps);
|
||||
IMETHOD TwistAcc Inverse(const TwistAcc &arg) const;
|
||||
IMETHOD TwistAcc Inverse(const Twist &arg) const;
|
||||
IMETHOD TwistAcc operator*(const TwistAcc &arg) const;
|
||||
IMETHOD TwistAcc operator*(const Twist &arg) const;
|
||||
// Rotations
|
||||
// The SetRot.. functions set the value of *this to the appropriate rotation matrix.
|
||||
// The Rot... static functions give the value of the appropriate rotation matrix back.
|
||||
// The DoRot... functions apply a rotation R to *this,such that *this = *this * R.
|
||||
// IMETHOD void DoRotX(const doubleAcc& angle);
|
||||
// IMETHOD void DoRotY(const doubleAcc& angle);
|
||||
// IMETHOD void DoRotZ(const doubleAcc& angle);
|
||||
// IMETHOD static RRotation RotX(const doubleAcc& angle);
|
||||
// IMETHOD static RRotation RotY(const doubleAcc& angle);
|
||||
// IMETHOD static RRotation RotZ(const doubleAcc& angle);
|
||||
|
||||
// IMETHOD void SetRot(const Vector& rotaxis,const doubleAcc& angle);
|
||||
// Along an arbitrary axes. The norm of rotvec is neglected.
|
||||
// IMETHOD static RotationAcc Rot(const Vector& rotvec,const doubleAcc& angle);
|
||||
// rotvec has arbitrary norm
|
||||
// rotation around a constant vector !
|
||||
// IMETHOD static RotationAcc Rot2(const Vector& rotvec,const doubleAcc& angle);
|
||||
// rotvec is normalized.
|
||||
// rotation around a constant vector !
|
||||
|
||||
IMETHOD friend RotationAcc operator* (const RotationAcc& r1,const RotationAcc& r2);
|
||||
IMETHOD friend RotationAcc operator* (const Rotation& r1,const RotationAcc& r2);
|
||||
IMETHOD friend RotationAcc operator* (const RotationAcc& r1,const Rotation& r2);
|
||||
IMETHOD friend bool Equal(const RotationAcc& r1,const RotationAcc& r2,double eps);
|
||||
IMETHOD friend bool Equal(const Rotation& r1,const RotationAcc& r2,double eps);
|
||||
IMETHOD friend bool Equal(const RotationAcc& r1,const Rotation& r2,double eps);
|
||||
IMETHOD TwistAcc Inverse(const TwistAcc& arg) const;
|
||||
IMETHOD TwistAcc Inverse(const Twist& arg) const;
|
||||
IMETHOD TwistAcc operator * (const TwistAcc& arg) const;
|
||||
IMETHOD TwistAcc operator * (const Twist& arg) const;
|
||||
};
|
||||
|
||||
class FrameAcc {
|
||||
public:
|
||||
RotationAcc M; //!< Rotation,angular velocity, and angular acceleration of frame.
|
||||
VectorAcc p; //!< Translation, velocity and acceleration of origin.
|
||||
public:
|
||||
FrameAcc() {}
|
||||
explicit FrameAcc(const Frame &T_) : M(T_.M), p(T_.p) {}
|
||||
FrameAcc(const Frame &T_, const Twist &_t, const Twist &_dt)
|
||||
: M(T_.M, _t.rot, _dt.rot), p(T_.p, _t.vel, _dt.vel)
|
||||
{
|
||||
}
|
||||
FrameAcc(const RotationAcc &_M, const VectorAcc &_p) : M(_M), p(_p) {}
|
||||
|
||||
IMETHOD FrameAcc &operator=(const FrameAcc &arg);
|
||||
IMETHOD FrameAcc &operator=(const Frame &arg);
|
||||
IMETHOD static FrameAcc Identity();
|
||||
IMETHOD FrameAcc Inverse() const;
|
||||
IMETHOD VectorAcc Inverse(const VectorAcc &arg) const;
|
||||
IMETHOD VectorAcc operator*(const VectorAcc &arg) const;
|
||||
IMETHOD VectorAcc operator*(const Vector &arg) const;
|
||||
IMETHOD VectorAcc Inverse(const Vector &arg) const;
|
||||
IMETHOD Frame GetFrame() const;
|
||||
IMETHOD Twist GetTwist() const;
|
||||
IMETHOD Twist GetAccTwist() const;
|
||||
IMETHOD friend FrameAcc operator*(const FrameAcc &f1, const FrameAcc &f2);
|
||||
IMETHOD friend FrameAcc operator*(const Frame &f1, const FrameAcc &f2);
|
||||
IMETHOD friend FrameAcc operator*(const FrameAcc &f1, const Frame &f2);
|
||||
IMETHOD friend bool Equal(const FrameAcc &r1, const FrameAcc &r2, double eps);
|
||||
IMETHOD friend bool Equal(const Frame &r1, const FrameAcc &r2, double eps);
|
||||
IMETHOD friend bool Equal(const FrameAcc &r1, const Frame &r2, double eps);
|
||||
|
||||
IMETHOD TwistAcc Inverse(const TwistAcc &arg) const;
|
||||
IMETHOD TwistAcc Inverse(const Twist &arg) const;
|
||||
IMETHOD TwistAcc operator*(const TwistAcc &arg) const;
|
||||
IMETHOD TwistAcc operator*(const Twist &arg) const;
|
||||
|
||||
class FrameAcc
|
||||
{
|
||||
public:
|
||||
RotationAcc M; //!< Rotation,angular velocity, and angular acceleration of frame.
|
||||
VectorAcc p; //!< Translation, velocity and acceleration of origin.
|
||||
public:
|
||||
FrameAcc(){}
|
||||
explicit FrameAcc(const Frame& T_):M(T_.M),p(T_.p) {}
|
||||
FrameAcc(const Frame& T_,const Twist& _t,const Twist& _dt):
|
||||
M(T_.M,_t.rot,_dt.rot),p(T_.p,_t.vel,_dt.vel) {}
|
||||
FrameAcc(const RotationAcc& _M,const VectorAcc& _p):M(_M),p(_p) {}
|
||||
|
||||
IMETHOD FrameAcc& operator = (const FrameAcc& arg);
|
||||
IMETHOD FrameAcc& operator = (const Frame& arg);
|
||||
IMETHOD static FrameAcc Identity();
|
||||
IMETHOD FrameAcc Inverse() const;
|
||||
IMETHOD VectorAcc Inverse(const VectorAcc& arg) const;
|
||||
IMETHOD VectorAcc operator*(const VectorAcc& arg) const;
|
||||
IMETHOD VectorAcc operator*(const Vector& arg) const;
|
||||
IMETHOD VectorAcc Inverse(const Vector& arg) const;
|
||||
IMETHOD Frame GetFrame() const;
|
||||
IMETHOD Twist GetTwist() const;
|
||||
IMETHOD Twist GetAccTwist() const;
|
||||
IMETHOD friend FrameAcc operator * (const FrameAcc& f1,const FrameAcc& f2);
|
||||
IMETHOD friend FrameAcc operator * (const Frame& f1,const FrameAcc& f2);
|
||||
IMETHOD friend FrameAcc operator * (const FrameAcc& f1,const Frame& f2);
|
||||
IMETHOD friend bool Equal(const FrameAcc& r1,const FrameAcc& r2,double eps);
|
||||
IMETHOD friend bool Equal(const Frame& r1,const FrameAcc& r2,double eps);
|
||||
IMETHOD friend bool Equal(const FrameAcc& r1,const Frame& r2,double eps);
|
||||
|
||||
IMETHOD TwistAcc Inverse(const TwistAcc& arg) const;
|
||||
IMETHOD TwistAcc Inverse(const Twist& arg) const;
|
||||
IMETHOD TwistAcc operator * (const TwistAcc& arg) const;
|
||||
IMETHOD TwistAcc operator * (const Twist& arg) const;
|
||||
};
|
||||
|
||||
// very similar to Wrench class.
|
||||
class TwistAcc {
|
||||
public:
|
||||
VectorAcc vel; //!< translational velocity and its 1st and 2nd derivative
|
||||
VectorAcc rot; //!< rotational velocity and its 1st and 2nd derivative
|
||||
public:
|
||||
TwistAcc() : vel(), rot(){};
|
||||
TwistAcc(const VectorAcc &_vel, const VectorAcc &_rot) : vel(_vel), rot(_rot){};
|
||||
|
||||
IMETHOD TwistAcc &operator-=(const TwistAcc &arg);
|
||||
IMETHOD TwistAcc &operator+=(const TwistAcc &arg);
|
||||
|
||||
IMETHOD friend TwistAcc operator*(const TwistAcc &lhs, double rhs);
|
||||
IMETHOD friend TwistAcc operator*(double lhs, const TwistAcc &rhs);
|
||||
IMETHOD friend TwistAcc operator/(const TwistAcc &lhs, double rhs);
|
||||
|
||||
IMETHOD friend TwistAcc operator*(const TwistAcc &lhs, const doubleAcc &rhs);
|
||||
IMETHOD friend TwistAcc operator*(const doubleAcc &lhs, const TwistAcc &rhs);
|
||||
IMETHOD friend TwistAcc operator/(const TwistAcc &lhs, const doubleAcc &rhs);
|
||||
|
||||
IMETHOD friend TwistAcc operator+(const TwistAcc &lhs, const TwistAcc &rhs);
|
||||
IMETHOD friend TwistAcc operator-(const TwistAcc &lhs, const TwistAcc &rhs);
|
||||
IMETHOD friend TwistAcc operator-(const TwistAcc &arg);
|
||||
|
||||
IMETHOD friend void SetToZero(TwistAcc &v);
|
||||
|
||||
static IMETHOD TwistAcc Zero();
|
||||
|
||||
IMETHOD void ReverseSign();
|
||||
//very similar to Wrench class.
|
||||
class TwistAcc
|
||||
{
|
||||
public:
|
||||
VectorAcc vel; //!< translational velocity and its 1st and 2nd derivative
|
||||
VectorAcc rot; //!< rotational velocity and its 1st and 2nd derivative
|
||||
public:
|
||||
|
||||
IMETHOD TwistAcc RefPoint(const VectorAcc &v_base_AB);
|
||||
// Changes the reference point of the RTwist.
|
||||
// The RVector v_base_AB is expressed in the same base as the RTwist
|
||||
// The RVector v_base_AB is a RVector from the old point to
|
||||
// the new point.
|
||||
// Complexity : 6M+6A
|
||||
TwistAcc():vel(),rot() {};
|
||||
TwistAcc(const VectorAcc& _vel,const VectorAcc& _rot):vel(_vel),rot(_rot) {};
|
||||
|
||||
IMETHOD friend bool Equal(const TwistAcc &a, const TwistAcc &b, double eps);
|
||||
IMETHOD friend bool Equal(const Twist &a, const TwistAcc &b, double eps);
|
||||
IMETHOD friend bool Equal(const TwistAcc &a, const Twist &b, double eps);
|
||||
IMETHOD TwistAcc& operator-=(const TwistAcc& arg);
|
||||
IMETHOD TwistAcc& operator+=(const TwistAcc& arg);
|
||||
|
||||
IMETHOD Twist GetTwist() const;
|
||||
IMETHOD Twist GetTwistDot() const;
|
||||
IMETHOD friend TwistAcc operator*(const TwistAcc& lhs,double rhs);
|
||||
IMETHOD friend TwistAcc operator*(double lhs,const TwistAcc& rhs);
|
||||
IMETHOD friend TwistAcc operator/(const TwistAcc& lhs,double rhs);
|
||||
|
||||
IMETHOD friend TwistAcc operator*(const TwistAcc& lhs,const doubleAcc& rhs);
|
||||
IMETHOD friend TwistAcc operator*(const doubleAcc& lhs,const TwistAcc& rhs);
|
||||
IMETHOD friend TwistAcc operator/(const TwistAcc& lhs,const doubleAcc& rhs);
|
||||
|
||||
IMETHOD friend TwistAcc operator+(const TwistAcc& lhs,const TwistAcc& rhs);
|
||||
IMETHOD friend TwistAcc operator-(const TwistAcc& lhs,const TwistAcc& rhs);
|
||||
IMETHOD friend TwistAcc operator-(const TwistAcc& arg);
|
||||
|
||||
IMETHOD friend void SetToZero(TwistAcc& v);
|
||||
|
||||
static IMETHOD TwistAcc Zero();
|
||||
|
||||
IMETHOD void ReverseSign();
|
||||
|
||||
IMETHOD TwistAcc RefPoint(const VectorAcc& v_base_AB);
|
||||
// Changes the reference point of the RTwist.
|
||||
// The RVector v_base_AB is expressed in the same base as the RTwist
|
||||
// The RVector v_base_AB is a RVector from the old point to
|
||||
// the new point.
|
||||
// Complexity : 6M+6A
|
||||
|
||||
IMETHOD friend bool Equal(const TwistAcc& a,const TwistAcc& b,double eps);
|
||||
IMETHOD friend bool Equal(const Twist& a,const TwistAcc& b,double eps);
|
||||
IMETHOD friend bool Equal(const TwistAcc& a,const Twist& b,double eps);
|
||||
|
||||
|
||||
IMETHOD Twist GetTwist() const;
|
||||
IMETHOD Twist GetTwistDot() const;
|
||||
|
||||
friend class RotationAcc;
|
||||
friend class FrameAcc;
|
||||
|
||||
friend class RotationAcc;
|
||||
friend class FrameAcc;
|
||||
};
|
||||
|
||||
IMETHOD bool Equal(const VectorAcc &, const VectorAcc &, double = epsilon);
|
||||
IMETHOD bool Equal(const Vector &, const VectorAcc &, double = epsilon);
|
||||
IMETHOD bool Equal(const VectorAcc &, const Vector &, double = epsilon);
|
||||
IMETHOD bool Equal(const RotationAcc &, const RotationAcc &, double = epsilon);
|
||||
IMETHOD bool Equal(const Rotation &, const RotationAcc &, double = epsilon);
|
||||
IMETHOD bool Equal(const RotationAcc &, const Rotation &, double = epsilon);
|
||||
IMETHOD bool Equal(const FrameAcc &, const FrameAcc &, double = epsilon);
|
||||
IMETHOD bool Equal(const Frame &, const FrameAcc &, double = epsilon);
|
||||
IMETHOD bool Equal(const FrameAcc &, const Frame &, double = epsilon);
|
||||
IMETHOD bool Equal(const TwistAcc &, const TwistAcc &, double = epsilon);
|
||||
IMETHOD bool Equal(const Twist &, const TwistAcc &, double = epsilon);
|
||||
IMETHOD bool Equal(const TwistAcc &, const Twist &, double = epsilon);
|
||||
|
||||
IMETHOD bool Equal(const VectorAcc&, const VectorAcc&, double = epsilon);
|
||||
IMETHOD bool Equal(const Vector&, const VectorAcc&, double = epsilon);
|
||||
IMETHOD bool Equal(const VectorAcc&, const Vector&, double = epsilon);
|
||||
IMETHOD bool Equal(const RotationAcc&, const RotationAcc&, double = epsilon);
|
||||
IMETHOD bool Equal(const Rotation&, const RotationAcc&, double = epsilon);
|
||||
IMETHOD bool Equal(const RotationAcc&, const Rotation&, double = epsilon);
|
||||
IMETHOD bool Equal(const FrameAcc&, const FrameAcc&, double = epsilon);
|
||||
IMETHOD bool Equal(const Frame&, const FrameAcc&, double = epsilon);
|
||||
IMETHOD bool Equal(const FrameAcc&, const Frame&, double = epsilon);
|
||||
IMETHOD bool Equal(const TwistAcc&, const TwistAcc&, double = epsilon);
|
||||
IMETHOD bool Equal(const Twist&, const TwistAcc&, double = epsilon);
|
||||
IMETHOD bool Equal(const TwistAcc&, const Twist&, double = epsilon);
|
||||
|
||||
|
||||
#ifdef KDL_INLINE
|
||||
# include "frameacc.inl"
|
||||
#include "frameacc.inl"
|
||||
#endif
|
||||
|
||||
} // namespace KDL
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,333 +33,314 @@
|
||||
namespace KDL {
|
||||
|
||||
#ifndef KDL_INLINE
|
||||
# include "frames.inl"
|
||||
#include "frames.inl"
|
||||
#endif
|
||||
|
||||
void Frame::Make4x4(double *d)
|
||||
void Frame::Make4x4(double * d)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
for (i = 0; i < 3; i++) {
|
||||
for (j = 0; j < 3; j++)
|
||||
d[i * 4 + j] = M(i, j);
|
||||
d[i * 4 + 3] = p(i) / 1000;
|
||||
}
|
||||
for (j = 0; j < 3; j++)
|
||||
d[12 + j] = 0.;
|
||||
d[15] = 1;
|
||||
int i;
|
||||
int j;
|
||||
for (i=0;i<3;i++) {
|
||||
for (j=0;j<3;j++)
|
||||
d[i*4+j]=M(i,j);
|
||||
d[i*4+3] = p(i)/1000;
|
||||
}
|
||||
for (j=0;j<3;j++)
|
||||
d[12+j] = 0.;
|
||||
d[15] = 1;
|
||||
}
|
||||
|
||||
Frame Frame::DH_Craig1989(double a, double alpha, double d, double theta)
|
||||
Frame Frame::DH_Craig1989(double a,double alpha,double d,double theta)
|
||||
// returns Modified Denavit-Hartenberg parameters (According to Craig)
|
||||
{
|
||||
double ct, st, ca, sa;
|
||||
ct = cos(theta);
|
||||
st = sin(theta);
|
||||
sa = sin(alpha);
|
||||
ca = cos(alpha);
|
||||
return Frame(Rotation(ct, -st, 0, st * ca, ct * ca, -sa, st * sa, ct * sa, ca),
|
||||
Vector(a, -sa * d, ca * d));
|
||||
double ct,st,ca,sa;
|
||||
ct = cos(theta);
|
||||
st = sin(theta);
|
||||
sa = sin(alpha);
|
||||
ca = cos(alpha);
|
||||
return Frame(Rotation(
|
||||
ct, -st, 0,
|
||||
st*ca, ct*ca, -sa,
|
||||
st*sa, ct*sa, ca ),
|
||||
Vector(
|
||||
a, -sa*d, ca*d )
|
||||
);
|
||||
}
|
||||
|
||||
Frame Frame::DH(double a, double alpha, double d, double theta)
|
||||
Frame Frame::DH(double a,double alpha,double d,double theta)
|
||||
// returns Denavit-Hartenberg parameters (Non-Modified DH)
|
||||
{
|
||||
double ct, st, ca, sa;
|
||||
ct = cos(theta);
|
||||
st = sin(theta);
|
||||
sa = sin(alpha);
|
||||
ca = cos(alpha);
|
||||
return Frame(Rotation(ct, -st * ca, st * sa, st, ct * ca, -ct * sa, 0, sa, ca),
|
||||
Vector(a * ct, a * st, d));
|
||||
double ct,st,ca,sa;
|
||||
ct = cos(theta);
|
||||
st = sin(theta);
|
||||
sa = sin(alpha);
|
||||
ca = cos(alpha);
|
||||
return Frame(Rotation(
|
||||
ct, -st*ca, st*sa,
|
||||
st, ct*ca, -ct*sa,
|
||||
0, sa, ca ),
|
||||
Vector(
|
||||
a*ct, a*st, d )
|
||||
);
|
||||
}
|
||||
|
||||
double Vector2::Norm() const
|
||||
{
|
||||
double tmp0 = fabs(data[0]);
|
||||
double tmp1 = fabs(data[1]);
|
||||
if (tmp0 >= tmp1) {
|
||||
if (tmp1 == 0)
|
||||
return 0;
|
||||
return tmp0 * sqrt(1 + sqr(tmp1 / tmp0));
|
||||
}
|
||||
else {
|
||||
return tmp1 * sqrt(1 + sqr(tmp0 / tmp1));
|
||||
}
|
||||
double tmp0 = fabs(data[0]);
|
||||
double tmp1 = fabs(data[1]);
|
||||
if (tmp0 >= tmp1) {
|
||||
if (tmp1 == 0)
|
||||
return 0;
|
||||
return tmp0*sqrt(1+sqr(tmp1/tmp0));
|
||||
} else {
|
||||
return tmp1*sqrt(1+sqr(tmp0/tmp1));
|
||||
}
|
||||
}
|
||||
// makes v a unitvector and returns the norm of v.
|
||||
// if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
|
||||
// if this is not good, check the return value of this method.
|
||||
double Vector2::Normalize(double eps)
|
||||
{
|
||||
double v = this->Norm();
|
||||
if (v < eps) {
|
||||
*this = Vector2(1, 0);
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
*this = (*this) / v;
|
||||
return v;
|
||||
}
|
||||
double Vector2::Normalize(double eps) {
|
||||
double v = this->Norm();
|
||||
if (v < eps) {
|
||||
*this = Vector2(1,0);
|
||||
return v;
|
||||
} else {
|
||||
*this = (*this)/v;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// do some effort not to lose precision
|
||||
double Vector::Norm() const
|
||||
{
|
||||
double tmp1;
|
||||
double tmp2;
|
||||
tmp1 = fabs(data[0]);
|
||||
tmp2 = fabs(data[1]);
|
||||
if (tmp1 >= tmp2) {
|
||||
tmp2 = fabs(data[2]);
|
||||
double tmp1;
|
||||
double tmp2;
|
||||
tmp1 = fabs(data[0]);
|
||||
tmp2 = fabs(data[1]);
|
||||
if (tmp1 >= tmp2) {
|
||||
if (tmp1 == 0) {
|
||||
// only to everything exactly zero case, all other are handled correctly
|
||||
return 0;
|
||||
}
|
||||
return tmp1 * sqrt(1 + sqr(data[1] / data[0]) + sqr(data[2] / data[0]));
|
||||
tmp2=fabs(data[2]);
|
||||
if (tmp1 >= tmp2) {
|
||||
if (tmp1 == 0) {
|
||||
// only to everything exactly zero case, all other are handled correctly
|
||||
return 0;
|
||||
}
|
||||
return tmp1*sqrt(1+sqr(data[1]/data[0])+sqr(data[2]/data[0]));
|
||||
} else {
|
||||
return tmp2*sqrt(1+sqr(data[0]/data[2])+sqr(data[1]/data[2]));
|
||||
}
|
||||
} else {
|
||||
tmp1=fabs(data[2]);
|
||||
if (tmp2 > tmp1) {
|
||||
return tmp2*sqrt(1+sqr(data[0]/data[1])+sqr(data[2]/data[1]));
|
||||
} else {
|
||||
return tmp1*sqrt(1+sqr(data[0]/data[2])+sqr(data[1]/data[2]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
return tmp2 * sqrt(1 + sqr(data[0] / data[2]) + sqr(data[1] / data[2]));
|
||||
}
|
||||
}
|
||||
else {
|
||||
tmp1 = fabs(data[2]);
|
||||
if (tmp2 > tmp1) {
|
||||
return tmp2 * sqrt(1 + sqr(data[0] / data[1]) + sqr(data[2] / data[1]));
|
||||
}
|
||||
else {
|
||||
return tmp1 * sqrt(1 + sqr(data[0] / data[2]) + sqr(data[1] / data[2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// makes v a unitvector and returns the norm of v.
|
||||
// if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
|
||||
// if this is not good, check the return value of this method.
|
||||
double Vector::Normalize(double eps)
|
||||
{
|
||||
double v = this->Norm();
|
||||
if (v < eps) {
|
||||
*this = Vector(1, 0, 0);
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
*this = (*this) / v;
|
||||
return v;
|
||||
}
|
||||
double Vector::Normalize(double eps) {
|
||||
double v = this->Norm();
|
||||
if (v < eps) {
|
||||
*this = Vector(1,0,0);
|
||||
return v;
|
||||
} else {
|
||||
*this = (*this)/v;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
bool Equal(const Rotation &a, const Rotation &b, double eps)
|
||||
{
|
||||
return (Equal(a.data[0], b.data[0], eps) && Equal(a.data[1], b.data[1], eps) &&
|
||||
Equal(a.data[2], b.data[2], eps) && Equal(a.data[3], b.data[3], eps) &&
|
||||
Equal(a.data[4], b.data[4], eps) && Equal(a.data[5], b.data[5], eps) &&
|
||||
Equal(a.data[6], b.data[6], eps) && Equal(a.data[7], b.data[7], eps) &&
|
||||
Equal(a.data[8], b.data[8], eps));
|
||||
|
||||
bool Equal(const Rotation& a,const Rotation& b,double eps) {
|
||||
return (Equal(a.data[0],b.data[0],eps) &&
|
||||
Equal(a.data[1],b.data[1],eps) &&
|
||||
Equal(a.data[2],b.data[2],eps) &&
|
||||
Equal(a.data[3],b.data[3],eps) &&
|
||||
Equal(a.data[4],b.data[4],eps) &&
|
||||
Equal(a.data[5],b.data[5],eps) &&
|
||||
Equal(a.data[6],b.data[6],eps) &&
|
||||
Equal(a.data[7],b.data[7],eps) &&
|
||||
Equal(a.data[8],b.data[8],eps) );
|
||||
}
|
||||
|
||||
void Rotation::Ortho()
|
||||
{
|
||||
double n;
|
||||
n = sqrt(sqr(data[0]) + sqr(data[3]) + sqr(data[6]));
|
||||
n = (n > 1e-10) ? 1.0 / n : 0.0;
|
||||
data[0] *= n;
|
||||
data[3] *= n;
|
||||
data[6] *= n;
|
||||
n = sqrt(sqr(data[1]) + sqr(data[4]) + sqr(data[7]));
|
||||
n = (n > 1e-10) ? 1.0 / n : 0.0;
|
||||
data[1] *= n;
|
||||
data[4] *= n;
|
||||
data[7] *= n;
|
||||
n = sqrt(sqr(data[2]) + sqr(data[5]) + sqr(data[8]));
|
||||
n = (n > 1e-10) ? 1.0 / n : 0.0;
|
||||
data[2] *= n;
|
||||
data[5] *= n;
|
||||
data[8] *= n;
|
||||
double n;
|
||||
n=sqrt(sqr(data[0])+sqr(data[3])+sqr(data[6]));n=(n>1e-10)?1.0/n:0.0;data[0]*=n;data[3]*=n;data[6]*=n;
|
||||
n=sqrt(sqr(data[1])+sqr(data[4])+sqr(data[7]));n=(n>1e-10)?1.0/n:0.0;data[1]*=n;data[4]*=n;data[7]*=n;
|
||||
n=sqrt(sqr(data[2])+sqr(data[5])+sqr(data[8]));n=(n>1e-10)?1.0/n:0.0;data[2]*=n;data[5]*=n;data[8]*=n;
|
||||
}
|
||||
|
||||
Rotation operator*(const Rotation &lhs, const Rotation &rhs)
|
||||
Rotation operator *(const Rotation& lhs,const Rotation& rhs)
|
||||
// Complexity : 27M+27A
|
||||
{
|
||||
return Rotation(
|
||||
lhs.data[0] * rhs.data[0] + lhs.data[1] * rhs.data[3] + lhs.data[2] * rhs.data[6],
|
||||
lhs.data[0] * rhs.data[1] + lhs.data[1] * rhs.data[4] + lhs.data[2] * rhs.data[7],
|
||||
lhs.data[0] * rhs.data[2] + lhs.data[1] * rhs.data[5] + lhs.data[2] * rhs.data[8],
|
||||
lhs.data[3] * rhs.data[0] + lhs.data[4] * rhs.data[3] + lhs.data[5] * rhs.data[6],
|
||||
lhs.data[3] * rhs.data[1] + lhs.data[4] * rhs.data[4] + lhs.data[5] * rhs.data[7],
|
||||
lhs.data[3] * rhs.data[2] + lhs.data[4] * rhs.data[5] + lhs.data[5] * rhs.data[8],
|
||||
lhs.data[6] * rhs.data[0] + lhs.data[7] * rhs.data[3] + lhs.data[8] * rhs.data[6],
|
||||
lhs.data[6] * rhs.data[1] + lhs.data[7] * rhs.data[4] + lhs.data[8] * rhs.data[7],
|
||||
lhs.data[6] * rhs.data[2] + lhs.data[7] * rhs.data[5] + lhs.data[8] * rhs.data[8]);
|
||||
return Rotation(
|
||||
lhs.data[0]*rhs.data[0]+lhs.data[1]*rhs.data[3]+lhs.data[2]*rhs.data[6],
|
||||
lhs.data[0]*rhs.data[1]+lhs.data[1]*rhs.data[4]+lhs.data[2]*rhs.data[7],
|
||||
lhs.data[0]*rhs.data[2]+lhs.data[1]*rhs.data[5]+lhs.data[2]*rhs.data[8],
|
||||
lhs.data[3]*rhs.data[0]+lhs.data[4]*rhs.data[3]+lhs.data[5]*rhs.data[6],
|
||||
lhs.data[3]*rhs.data[1]+lhs.data[4]*rhs.data[4]+lhs.data[5]*rhs.data[7],
|
||||
lhs.data[3]*rhs.data[2]+lhs.data[4]*rhs.data[5]+lhs.data[5]*rhs.data[8],
|
||||
lhs.data[6]*rhs.data[0]+lhs.data[7]*rhs.data[3]+lhs.data[8]*rhs.data[6],
|
||||
lhs.data[6]*rhs.data[1]+lhs.data[7]*rhs.data[4]+lhs.data[8]*rhs.data[7],
|
||||
lhs.data[6]*rhs.data[2]+lhs.data[7]*rhs.data[5]+lhs.data[8]*rhs.data[8]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
Rotation Rotation::RPY(double roll, double pitch, double yaw)
|
||||
{
|
||||
double ca1, cb1, cc1, sa1, sb1, sc1;
|
||||
ca1 = cos(yaw);
|
||||
sa1 = sin(yaw);
|
||||
cb1 = cos(pitch);
|
||||
sb1 = sin(pitch);
|
||||
cc1 = cos(roll);
|
||||
sc1 = sin(roll);
|
||||
return Rotation(ca1 * cb1,
|
||||
ca1 * sb1 * sc1 - sa1 * cc1,
|
||||
ca1 * sb1 * cc1 + sa1 * sc1,
|
||||
sa1 * cb1,
|
||||
sa1 * sb1 * sc1 + ca1 * cc1,
|
||||
sa1 * sb1 * cc1 - ca1 * sc1,
|
||||
-sb1,
|
||||
cb1 * sc1,
|
||||
cb1 * cc1);
|
||||
}
|
||||
|
||||
Rotation Rotation::RPY(double roll,double pitch,double yaw)
|
||||
{
|
||||
double ca1,cb1,cc1,sa1,sb1,sc1;
|
||||
ca1 = cos(yaw); sa1 = sin(yaw);
|
||||
cb1 = cos(pitch);sb1 = sin(pitch);
|
||||
cc1 = cos(roll);sc1 = sin(roll);
|
||||
return Rotation(ca1*cb1,ca1*sb1*sc1 - sa1*cc1,ca1*sb1*cc1 + sa1*sc1,
|
||||
sa1*cb1,sa1*sb1*sc1 + ca1*cc1,sa1*sb1*cc1 - ca1*sc1,
|
||||
-sb1,cb1*sc1,cb1*cc1);
|
||||
}
|
||||
|
||||
// Gives back a rotation matrix specified with RPY convention
|
||||
void Rotation::GetRPY(double &roll, double &pitch, double &yaw) const
|
||||
{
|
||||
if (fabs(data[6]) > 1.0 - epsilon) {
|
||||
roll = -sign(data[6]) * atan2(data[1], data[4]);
|
||||
pitch = -sign(data[6]) * PI / 2;
|
||||
yaw = 0.0;
|
||||
}
|
||||
else {
|
||||
roll = atan2(data[7], data[8]);
|
||||
pitch = atan2(-data[6], sqrt(sqr(data[0]) + sqr(data[3])));
|
||||
yaw = atan2(data[3], data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
Rotation Rotation::EulerZYZ(double Alfa, double Beta, double Gamma)
|
||||
{
|
||||
double sa, ca, sb, cb, sg, cg;
|
||||
sa = sin(Alfa);
|
||||
ca = cos(Alfa);
|
||||
sb = sin(Beta);
|
||||
cb = cos(Beta);
|
||||
sg = sin(Gamma);
|
||||
cg = cos(Gamma);
|
||||
return Rotation(ca * cb * cg - sa * sg,
|
||||
-ca * cb * sg - sa * cg,
|
||||
ca * sb,
|
||||
sa * cb * cg + ca * sg,
|
||||
-sa * cb * sg + ca * cg,
|
||||
sa * sb,
|
||||
-sb * cg,
|
||||
sb * sg,
|
||||
cb);
|
||||
}
|
||||
|
||||
void Rotation::GetEulerZYZ(double &alfa, double &beta, double &gamma) const
|
||||
{
|
||||
if (fabs(data[6]) < epsilon) {
|
||||
alfa = 0.0;
|
||||
if (data[8] > 0) {
|
||||
beta = 0.0;
|
||||
gamma = atan2(-data[1], data[0]);
|
||||
void Rotation::GetRPY(double& roll,double& pitch,double& yaw) const
|
||||
{
|
||||
if (fabs(data[6]) > 1.0 - epsilon ) {
|
||||
roll = -sign(data[6]) * atan2(data[1], data[4]);
|
||||
pitch= -sign(data[6]) * PI / 2;
|
||||
yaw = 0.0 ;
|
||||
} else {
|
||||
roll = atan2(data[7], data[8]);
|
||||
pitch = atan2(-data[6], sqrt( sqr(data[0]) +sqr(data[3]) ) );
|
||||
yaw = atan2(data[3], data[0]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
beta = PI;
|
||||
gamma = atan2(data[1], -data[0]);
|
||||
|
||||
Rotation Rotation::EulerZYZ(double Alfa,double Beta,double Gamma) {
|
||||
double sa,ca,sb,cb,sg,cg;
|
||||
sa = sin(Alfa);ca = cos(Alfa);
|
||||
sb = sin(Beta);cb = cos(Beta);
|
||||
sg = sin(Gamma);cg = cos(Gamma);
|
||||
return Rotation( ca*cb*cg-sa*sg, -ca*cb*sg-sa*cg, ca*sb,
|
||||
sa*cb*cg+ca*sg, -sa*cb*sg+ca*cg, sa*sb,
|
||||
-sb*cg , sb*sg, cb
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void Rotation::GetEulerZYZ(double& alfa,double& beta,double& gamma) const {
|
||||
if (fabs(data[6]) < epsilon ) {
|
||||
alfa=0.0;
|
||||
if (data[8]>0) {
|
||||
beta = 0.0;
|
||||
gamma= atan2(-data[1],data[0]);
|
||||
} else {
|
||||
beta = PI;
|
||||
gamma= atan2(data[1],-data[0]);
|
||||
}
|
||||
} else {
|
||||
alfa=atan2(data[5], data[2]);
|
||||
beta=atan2(sqrt( sqr(data[6]) +sqr(data[7]) ),data[8]);
|
||||
gamma=atan2(data[7], -data[6]);
|
||||
}
|
||||
}
|
||||
|
||||
Rotation Rotation::Rot(const Vector& rotaxis,double angle) {
|
||||
// The formula is
|
||||
// V.(V.tr) + st*[V x] + ct*(I-V.(V.tr))
|
||||
// can be found by multiplying it with an arbitrary vector p
|
||||
// and noting that this vector is rotated.
|
||||
double ct = cos(angle);
|
||||
double st = sin(angle);
|
||||
double vt = 1-ct;
|
||||
Vector rotvec = rotaxis;
|
||||
rotvec.Normalize();
|
||||
return Rotation(
|
||||
ct + vt*rotvec(0)*rotvec(0),
|
||||
-rotvec(2)*st + vt*rotvec(0)*rotvec(1),
|
||||
rotvec(1)*st + vt*rotvec(0)*rotvec(2),
|
||||
rotvec(2)*st + vt*rotvec(1)*rotvec(0),
|
||||
ct + vt*rotvec(1)*rotvec(1),
|
||||
-rotvec(0)*st + vt*rotvec(1)*rotvec(2),
|
||||
-rotvec(1)*st + vt*rotvec(2)*rotvec(0),
|
||||
rotvec(0)*st + vt*rotvec(2)*rotvec(1),
|
||||
ct + vt*rotvec(2)*rotvec(2)
|
||||
);
|
||||
}
|
||||
}
|
||||
else {
|
||||
alfa = atan2(data[5], data[2]);
|
||||
beta = atan2(sqrt(sqr(data[6]) + sqr(data[7])), data[8]);
|
||||
gamma = atan2(data[7], -data[6]);
|
||||
}
|
||||
|
||||
Rotation Rotation::Rot2(const Vector& rotvec,double angle) {
|
||||
// rotvec should be normalized !
|
||||
// The formula is
|
||||
// V.(V.tr) + st*[V x] + ct*(I-V.(V.tr))
|
||||
// can be found by multiplying it with an arbitrary vector p
|
||||
// and noting that this vector is rotated.
|
||||
double ct = cos(angle);
|
||||
double st = sin(angle);
|
||||
double vt = 1-ct;
|
||||
return Rotation(
|
||||
ct + vt*rotvec(0)*rotvec(0),
|
||||
-rotvec(2)*st + vt*rotvec(0)*rotvec(1),
|
||||
rotvec(1)*st + vt*rotvec(0)*rotvec(2),
|
||||
rotvec(2)*st + vt*rotvec(1)*rotvec(0),
|
||||
ct + vt*rotvec(1)*rotvec(1),
|
||||
-rotvec(0)*st + vt*rotvec(1)*rotvec(2),
|
||||
-rotvec(1)*st + vt*rotvec(2)*rotvec(0),
|
||||
rotvec(0)*st + vt*rotvec(2)*rotvec(1),
|
||||
ct + vt*rotvec(2)*rotvec(2)
|
||||
);
|
||||
}
|
||||
|
||||
Rotation Rotation::Rot(const Vector &rotaxis, double angle)
|
||||
{
|
||||
// The formula is
|
||||
// V.(V.tr) + st*[V x] + ct*(I-V.(V.tr))
|
||||
// can be found by multiplying it with an arbitrary vector p
|
||||
// and noting that this vector is rotated.
|
||||
double ct = cos(angle);
|
||||
double st = sin(angle);
|
||||
double vt = 1 - ct;
|
||||
Vector rotvec = rotaxis;
|
||||
rotvec.Normalize();
|
||||
return Rotation(ct + vt * rotvec(0) * rotvec(0),
|
||||
-rotvec(2) * st + vt * rotvec(0) * rotvec(1),
|
||||
rotvec(1) * st + vt * rotvec(0) * rotvec(2),
|
||||
rotvec(2) * st + vt * rotvec(1) * rotvec(0),
|
||||
ct + vt * rotvec(1) * rotvec(1),
|
||||
-rotvec(0) * st + vt * rotvec(1) * rotvec(2),
|
||||
-rotvec(1) * st + vt * rotvec(2) * rotvec(0),
|
||||
rotvec(0) * st + vt * rotvec(2) * rotvec(1),
|
||||
ct + vt * rotvec(2) * rotvec(2));
|
||||
}
|
||||
|
||||
Rotation Rotation::Rot2(const Vector &rotvec, double angle)
|
||||
{
|
||||
// rotvec should be normalized !
|
||||
// The formula is
|
||||
// V.(V.tr) + st*[V x] + ct*(I-V.(V.tr))
|
||||
// can be found by multiplying it with an arbitrary vector p
|
||||
// and noting that this vector is rotated.
|
||||
double ct = cos(angle);
|
||||
double st = sin(angle);
|
||||
double vt = 1 - ct;
|
||||
return Rotation(ct + vt * rotvec(0) * rotvec(0),
|
||||
-rotvec(2) * st + vt * rotvec(0) * rotvec(1),
|
||||
rotvec(1) * st + vt * rotvec(0) * rotvec(2),
|
||||
rotvec(2) * st + vt * rotvec(1) * rotvec(0),
|
||||
ct + vt * rotvec(1) * rotvec(1),
|
||||
-rotvec(0) * st + vt * rotvec(1) * rotvec(2),
|
||||
-rotvec(1) * st + vt * rotvec(2) * rotvec(0),
|
||||
rotvec(0) * st + vt * rotvec(2) * rotvec(1),
|
||||
ct + vt * rotvec(2) * rotvec(2));
|
||||
}
|
||||
|
||||
Vector Rotation::GetRot() const
|
||||
// Returns a vector with the direction of the equiv. axis
|
||||
// and its norm is angle
|
||||
{
|
||||
Vector axis = Vector((data[7] - data[5]), (data[2] - data[6]), (data[3] - data[1])) / 2;
|
||||
// Returns a vector with the direction of the equiv. axis
|
||||
// and its norm is angle
|
||||
{
|
||||
Vector axis = Vector((data[7]-data[5]),
|
||||
(data[2]-data[6]),
|
||||
(data[3]-data[1]) )/2;
|
||||
|
||||
double sa = axis.Norm();
|
||||
double ca = (data[0] + data[4] + data[8] - 1) / 2.0;
|
||||
double alfa;
|
||||
if (sa > epsilon)
|
||||
alfa = ::atan2(sa, ca) / sa;
|
||||
else {
|
||||
if (ca < 0.0) {
|
||||
alfa = KDL::PI;
|
||||
axis.data[0] = 0.0;
|
||||
axis.data[1] = 0.0;
|
||||
axis.data[2] = 0.0;
|
||||
if (data[0] > 0.0) {
|
||||
axis.data[0] = 1.0;
|
||||
}
|
||||
else if (data[4] > 0.0) {
|
||||
axis.data[1] = 1.0;
|
||||
}
|
||||
else {
|
||||
axis.data[2] = 1.0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
alfa = 0.0;
|
||||
}
|
||||
}
|
||||
return axis * alfa;
|
||||
}
|
||||
double sa = axis.Norm();
|
||||
double ca = (data[0]+data[4]+data[8]-1)/2.0;
|
||||
double alfa;
|
||||
if (sa > epsilon)
|
||||
alfa = ::atan2(sa,ca)/sa;
|
||||
else {
|
||||
if (ca < 0.0) {
|
||||
alfa = KDL::PI;
|
||||
axis.data[0] = 0.0;
|
||||
axis.data[1] = 0.0;
|
||||
axis.data[2] = 0.0;
|
||||
if (data[0] > 0.0) {
|
||||
axis.data[0] = 1.0;
|
||||
} else if (data[4] > 0.0) {
|
||||
axis.data[1] = 1.0;
|
||||
} else {
|
||||
axis.data[2] = 1.0;
|
||||
}
|
||||
} else {
|
||||
alfa = 0.0;
|
||||
}
|
||||
}
|
||||
return axis * alfa;
|
||||
}
|
||||
|
||||
Vector2 Rotation::GetXZRot() const
|
||||
{
|
||||
// [0,1,0] x Y
|
||||
Vector2 axis(data[7], -data[1]);
|
||||
double norm = axis.Normalize();
|
||||
if (norm < epsilon) {
|
||||
norm = (data[4] < 0.0) ? PI : 0.0;
|
||||
}
|
||||
else {
|
||||
norm = acos(data[4]);
|
||||
}
|
||||
return axis * norm;
|
||||
// [0,1,0] x Y
|
||||
Vector2 axis(data[7], -data[1]);
|
||||
double norm = axis.Normalize();
|
||||
if (norm < epsilon) {
|
||||
norm = (data[4] < 0.0) ? PI : 0.0;
|
||||
} else {
|
||||
norm = acos(data[4]);
|
||||
}
|
||||
return axis*norm;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the rotation angle around the equiv. axis
|
||||
* @param axis the rotation axis is returned in this variable
|
||||
* @param eps : in the case of angle == 0 : rot axis is undefined and choosen
|
||||
@@ -370,37 +351,42 @@ Vector2 Rotation::GetXZRot() const
|
||||
* /todo :
|
||||
* Check corresponding routines in rframes and rrframes
|
||||
*/
|
||||
double Rotation::GetRotAngle(Vector &axis, double eps) const
|
||||
{
|
||||
double ca = (data[0] + data[4] + data[8] - 1) / 2.0;
|
||||
if (ca > 1 - eps) {
|
||||
// undefined choose the Z-axis, and angle 0
|
||||
axis = Vector(0, 0, 1);
|
||||
return 0;
|
||||
}
|
||||
if (ca < -1 + eps) {
|
||||
// two solutions, choose a positive Z-component of the axis
|
||||
double z = sqrt((data[8] + 1) / 2);
|
||||
double x = (data[2]) / 2 / z;
|
||||
double y = (data[5]) / 2 / z;
|
||||
axis = Vector(x, y, z);
|
||||
return PI;
|
||||
}
|
||||
double angle = acos(ca);
|
||||
double sa = sin(angle);
|
||||
axis = Vector(
|
||||
(data[7] - data[5]) / 2 / sa, (data[2] - data[6]) / 2 / sa, (data[3] - data[1]) / 2 / sa);
|
||||
return angle;
|
||||
double Rotation::GetRotAngle(Vector& axis,double eps) const {
|
||||
double ca = (data[0]+data[4]+data[8]-1)/2.0;
|
||||
if (ca>1-eps) {
|
||||
// undefined choose the Z-axis, and angle 0
|
||||
axis = Vector(0,0,1);
|
||||
return 0;
|
||||
}
|
||||
if (ca < -1+eps) {
|
||||
// two solutions, choose a positive Z-component of the axis
|
||||
double z = sqrt( (data[8]+1)/2 );
|
||||
double x = (data[2])/2/z;
|
||||
double y = (data[5])/2/z;
|
||||
axis = Vector( x,y,z );
|
||||
return PI;
|
||||
}
|
||||
double angle = acos(ca);
|
||||
double sa = sin(angle);
|
||||
axis = Vector((data[7]-data[5])/2/sa,
|
||||
(data[2]-data[6])/2/sa,
|
||||
(data[3]-data[1])/2/sa );
|
||||
return angle;
|
||||
}
|
||||
|
||||
bool operator==(const Rotation &a, const Rotation &b)
|
||||
{
|
||||
bool operator==(const Rotation& a,const Rotation& b) {
|
||||
#ifdef KDL_USE_EQUAL
|
||||
return Equal(a, b);
|
||||
return Equal(a,b);
|
||||
#else
|
||||
return (a.data[0] == b.data[0] && a.data[1] == b.data[1] && a.data[2] == b.data[2] &&
|
||||
a.data[3] == b.data[3] && a.data[4] == b.data[4] && a.data[5] == b.data[5] &&
|
||||
a.data[6] == b.data[6] && a.data[7] == b.data[7] && a.data[8] == b.data[8]);
|
||||
return ( a.data[0]==b.data[0] &&
|
||||
a.data[1]==b.data[1] &&
|
||||
a.data[2]==b.data[2] &&
|
||||
a.data[3]==b.data[3] &&
|
||||
a.data[4]==b.data[4] &&
|
||||
a.data[5]==b.data[5] &&
|
||||
a.data[6]==b.data[6] &&
|
||||
a.data[7]==b.data[7] &&
|
||||
a.data[8]==b.data[8] );
|
||||
#endif
|
||||
}
|
||||
} // namespace KDL
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@
|
||||
#ifndef KDL_FRAMES_H
|
||||
#define KDL_FRAMES_H
|
||||
|
||||
|
||||
#include "utilities/kdl-config.h"
|
||||
#include "utilities/utility.h"
|
||||
|
||||
@@ -122,6 +123,8 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
|
||||
|
||||
class Vector;
|
||||
class Rotation;
|
||||
class Frame;
|
||||
@@ -131,128 +134,133 @@ class Vector2;
|
||||
class Rotation2;
|
||||
class Frame2;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \brief A concrete implementation of a 3 dimensional vector class
|
||||
*/
|
||||
class Vector {
|
||||
public:
|
||||
double data[3];
|
||||
//! Does not initialise the Vector to zero. use Vector::Zero() or SetToZero for that
|
||||
inline Vector()
|
||||
{
|
||||
data[0] = data[1] = data[2] = 0.0;
|
||||
}
|
||||
class Vector
|
||||
{
|
||||
public:
|
||||
double data[3];
|
||||
//! Does not initialise the Vector to zero. use Vector::Zero() or SetToZero for that
|
||||
inline Vector() {data[0]=data[1]=data[2] = 0.0;}
|
||||
|
||||
//! Constructs a vector out of the three values x, y and z
|
||||
inline Vector(double x, double y, double z);
|
||||
//! Constructs a vector out of the three values x, y and z
|
||||
inline Vector(double x,double y, double z);
|
||||
|
||||
//! Constructs a vector out of an array of three values x, y and z
|
||||
inline Vector(double *xyz);
|
||||
//! Constructs a vector out of an array of three values x, y and z
|
||||
inline Vector(double* xyz);
|
||||
|
||||
//! Constructs a vector out of an array of three values x, y and z
|
||||
inline Vector(float *xyz);
|
||||
//! Constructs a vector out of an array of three values x, y and z
|
||||
inline Vector(float* xyz);
|
||||
|
||||
//! Assignment operator. The normal copy by value semantics.
|
||||
inline Vector(const Vector &arg);
|
||||
//! Assignment operator. The normal copy by value semantics.
|
||||
inline Vector(const Vector& arg);
|
||||
|
||||
//! store vector components in array
|
||||
inline void GetValue(double *xyz) const;
|
||||
//! store vector components in array
|
||||
inline void GetValue(double* xyz) const;
|
||||
|
||||
//! Assignment operator. The normal copy by value semantics.
|
||||
inline Vector &operator=(const Vector &arg);
|
||||
//! Assignment operator. The normal copy by value semantics.
|
||||
inline Vector& operator = ( const Vector& arg);
|
||||
|
||||
//! Access to elements, range checked when NDEBUG is not set, from 0..2
|
||||
inline double operator()(int index) const;
|
||||
//! Access to elements, range checked when NDEBUG is not set, from 0..2
|
||||
inline double operator()(int index) const;
|
||||
|
||||
//! Access to elements, range checked when NDEBUG is not set, from 0..2
|
||||
inline double &operator()(int index);
|
||||
//! Access to elements, range checked when NDEBUG is not set, from 0..2
|
||||
inline double& operator() (int index);
|
||||
|
||||
//! Equivalent to double operator()(int index) const
|
||||
double operator[](int index) const
|
||||
{
|
||||
return this->operator()(index);
|
||||
}
|
||||
//! Equivalent to double operator()(int index) const
|
||||
double operator[] ( int index ) const
|
||||
{
|
||||
return this->operator() ( index );
|
||||
}
|
||||
|
||||
//! Equivalent to double& operator()(int index)
|
||||
double &operator[](int index)
|
||||
{
|
||||
return this->operator()(index);
|
||||
}
|
||||
//! Equivalent to double& operator()(int index)
|
||||
double& operator[] ( int index )
|
||||
{
|
||||
return this->operator() ( index );
|
||||
}
|
||||
|
||||
inline double x() const;
|
||||
inline double y() const;
|
||||
inline double z() const;
|
||||
inline void x(double);
|
||||
inline void y(double);
|
||||
inline void z(double);
|
||||
inline double x() const;
|
||||
inline double y() const;
|
||||
inline double z() const;
|
||||
inline void x(double);
|
||||
inline void y(double);
|
||||
inline void z(double);
|
||||
|
||||
//! Reverses the sign of the Vector object itself
|
||||
inline void ReverseSign();
|
||||
//! Reverses the sign of the Vector object itself
|
||||
inline void ReverseSign();
|
||||
|
||||
//! subtracts a vector from the Vector object itself
|
||||
inline Vector &operator-=(const Vector &arg);
|
||||
|
||||
//! Adds a vector from the Vector object itself
|
||||
inline Vector &operator+=(const Vector &arg);
|
||||
//! subtracts a vector from the Vector object itself
|
||||
inline Vector& operator-=(const Vector& arg);
|
||||
|
||||
//! Multiply by a scalar
|
||||
inline Vector &operator*=(double arg);
|
||||
|
||||
//! Scalar multiplication is defined
|
||||
inline friend Vector operator*(const Vector &lhs, double rhs);
|
||||
//! Scalar multiplication is defined
|
||||
inline friend Vector operator*(double lhs, const Vector &rhs);
|
||||
//! Scalar division is defined
|
||||
//! Adds a vector from the Vector object itself
|
||||
inline Vector& operator +=(const Vector& arg);
|
||||
|
||||
inline friend Vector operator/(const Vector &lhs, double rhs);
|
||||
inline friend Vector operator+(const Vector &lhs, const Vector &rhs);
|
||||
inline friend Vector operator-(const Vector &lhs, const Vector &rhs);
|
||||
inline friend Vector operator*(const Vector &lhs, const Vector &rhs);
|
||||
inline friend Vector operator-(const Vector &arg);
|
||||
inline friend double dot(const Vector &lhs, const Vector &rhs);
|
||||
//! Multiply by a scalar
|
||||
inline Vector& operator *=(double arg);
|
||||
|
||||
//! To have a uniform operator to put an element to zero, for scalar values
|
||||
//! and for objects.
|
||||
inline friend void SetToZero(Vector &v);
|
||||
//! Scalar multiplication is defined
|
||||
inline friend Vector operator*(const Vector& lhs,double rhs);
|
||||
//! Scalar multiplication is defined
|
||||
inline friend Vector operator*(double lhs,const Vector& rhs);
|
||||
//! Scalar division is defined
|
||||
|
||||
//! @return a zero vector
|
||||
inline static Vector Zero();
|
||||
inline friend Vector operator/(const Vector& lhs,double rhs);
|
||||
inline friend Vector operator+(const Vector& lhs,const Vector& rhs);
|
||||
inline friend Vector operator-(const Vector& lhs,const Vector& rhs);
|
||||
inline friend Vector operator*(const Vector& lhs,const Vector& rhs);
|
||||
inline friend Vector operator-(const Vector& arg);
|
||||
inline friend double dot(const Vector& lhs,const Vector& rhs);
|
||||
|
||||
/** Normalizes this vector and returns it norm
|
||||
* makes v a unitvector and returns the norm of v.
|
||||
* if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
|
||||
* if this is not good, check the return value of this method.
|
||||
*/
|
||||
double Normalize(double eps = epsilon);
|
||||
//! To have a uniform operator to put an element to zero, for scalar values
|
||||
//! and for objects.
|
||||
inline friend void SetToZero(Vector& v);
|
||||
|
||||
//! @return the norm of the vector
|
||||
double Norm() const;
|
||||
//! @return a zero vector
|
||||
inline static Vector Zero();
|
||||
|
||||
//! a 3D vector where the 2D vector v is put in the XY plane
|
||||
inline void Set2DXY(const Vector2 &v);
|
||||
//! a 3D vector where the 2D vector v is put in the YZ plane
|
||||
inline void Set2DYZ(const Vector2 &v);
|
||||
//! a 3D vector where the 2D vector v is put in the ZX plane
|
||||
inline void Set2DZX(const Vector2 &v);
|
||||
//! a 3D vector where the 2D vector v_XY is put in the XY plane of the frame F_someframe_XY.
|
||||
inline void Set2DPlane(const Frame &F_someframe_XY, const Vector2 &v_XY);
|
||||
/** Normalizes this vector and returns it norm
|
||||
* makes v a unitvector and returns the norm of v.
|
||||
* if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
|
||||
* if this is not good, check the return value of this method.
|
||||
*/
|
||||
double Normalize(double eps=epsilon);
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Vector &a, const Vector &b, double eps);
|
||||
//! @return the norm of the vector
|
||||
double Norm() const;
|
||||
|
||||
//! return a normalized vector
|
||||
inline friend Vector Normalize(const Vector &a, double eps);
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const Vector &a, const Vector &b);
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const Vector &a, const Vector &b);
|
||||
|
||||
friend class Rotation;
|
||||
friend class Frame;
|
||||
//! a 3D vector where the 2D vector v is put in the XY plane
|
||||
inline void Set2DXY(const Vector2& v);
|
||||
//! a 3D vector where the 2D vector v is put in the YZ plane
|
||||
inline void Set2DYZ(const Vector2& v);
|
||||
//! a 3D vector where the 2D vector v is put in the ZX plane
|
||||
inline void Set2DZX(const Vector2& v);
|
||||
//! a 3D vector where the 2D vector v_XY is put in the XY plane of the frame F_someframe_XY.
|
||||
inline void Set2DPlane(const Frame& F_someframe_XY,const Vector2& v_XY);
|
||||
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Vector& a,const Vector& b,double eps);
|
||||
|
||||
//! return a normalized vector
|
||||
inline friend Vector Normalize(const Vector& a, double eps);
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const Vector& a,const Vector& b);
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const Vector& a,const Vector& b);
|
||||
|
||||
friend class Rotation;
|
||||
friend class Frame;
|
||||
};
|
||||
inline Vector Normalize(const Vector &, double eps = epsilon);
|
||||
inline Vector Normalize(const Vector&, double eps=epsilon);
|
||||
|
||||
/**
|
||||
\brief represents rotations in 3 dimensional space.
|
||||
@@ -287,234 +295,227 @@ inline Vector Normalize(const Vector &, double eps = epsilon);
|
||||
\par type
|
||||
Concrete implementation
|
||||
*/
|
||||
class Rotation {
|
||||
public:
|
||||
double data[9];
|
||||
class Rotation
|
||||
{
|
||||
public:
|
||||
double data[9];
|
||||
|
||||
inline Rotation()
|
||||
{
|
||||
*this = Identity();
|
||||
}
|
||||
inline Rotation(double Xx,
|
||||
double Yx,
|
||||
double Zx,
|
||||
double Xy,
|
||||
double Yy,
|
||||
double Zy,
|
||||
double Xz,
|
||||
double Yz,
|
||||
double Zz);
|
||||
inline Rotation(const Vector &x, const Vector &y, const Vector &z);
|
||||
// default copy constructor is sufficient
|
||||
inline Rotation() {
|
||||
*this = Identity();
|
||||
}
|
||||
inline Rotation(double Xx,double Yx,double Zx,
|
||||
double Xy,double Yy,double Zy,
|
||||
double Xz,double Yz,double Zz);
|
||||
inline Rotation(const Vector& x,const Vector& y,const Vector& z);
|
||||
// default copy constructor is sufficient
|
||||
|
||||
inline void setValue(float *oglmat);
|
||||
inline void getValue(float *oglmat) const;
|
||||
inline void setValue(float* oglmat);
|
||||
inline void getValue(float* oglmat) const;
|
||||
|
||||
inline Rotation &operator=(const Rotation &arg);
|
||||
inline Rotation& operator=(const Rotation& arg);
|
||||
|
||||
//! Defines a multiplication R*V between a Rotation R and a Vector V.
|
||||
//! Complexity : 9M+6A
|
||||
inline Vector operator*(const Vector &v) const;
|
||||
//! Defines a multiplication R*V between a Rotation R and a Vector V.
|
||||
//! Complexity : 9M+6A
|
||||
inline Vector operator*(const Vector& v) const;
|
||||
|
||||
//! Access to elements 0..2,0..2, bounds are checked when NDEBUG is not set
|
||||
inline double &operator()(int i, int j);
|
||||
//! Access to elements 0..2,0..2, bounds are checked when NDEBUG is not set
|
||||
inline double& operator()(int i,int j);
|
||||
|
||||
//! Access to elements 0..2,0..2, bounds are checked when NDEBUG is not set
|
||||
inline double operator()(int i, int j) const;
|
||||
//! Access to elements 0..2,0..2, bounds are checked when NDEBUG is not set
|
||||
inline double operator() (int i,int j) const;
|
||||
|
||||
friend Rotation operator*(const Rotation &lhs, const Rotation &rhs);
|
||||
friend Rotation operator *(const Rotation& lhs,const Rotation& rhs);
|
||||
|
||||
//! Sets the value of *this to its inverse.
|
||||
inline void SetInverse();
|
||||
//! Sets the value of *this to its inverse.
|
||||
inline void SetInverse();
|
||||
|
||||
//! Gives back the inverse rotation matrix of *this.
|
||||
inline Rotation Inverse() const;
|
||||
//! Gives back the inverse rotation matrix of *this.
|
||||
inline Rotation Inverse() const;
|
||||
|
||||
//! The same as R.Inverse()*v but more efficient.
|
||||
inline Vector Inverse(const Vector &v) const;
|
||||
//! The same as R.Inverse()*v but more efficient.
|
||||
inline Vector Inverse(const Vector& v) const;
|
||||
|
||||
//! The same as R.Inverse()*arg but more efficient.
|
||||
inline Wrench Inverse(const Wrench &arg) const;
|
||||
//! The same as R.Inverse()*arg but more efficient.
|
||||
inline Wrench Inverse(const Wrench& arg) const;
|
||||
|
||||
//! The same as R.Inverse()*arg but more efficient.
|
||||
inline Twist Inverse(const Twist &arg) const;
|
||||
//! The same as R.Inverse()*arg but more efficient.
|
||||
inline Twist Inverse(const Twist& arg) const;
|
||||
|
||||
//! Gives back an identity rotaton matrix
|
||||
inline static Rotation Identity();
|
||||
//! Gives back an identity rotaton matrix
|
||||
inline static Rotation Identity();
|
||||
|
||||
// = Rotations
|
||||
//! The Rot... static functions give the value of the appropriate rotation matrix back.
|
||||
inline static Rotation RotX(double angle);
|
||||
//! The Rot... static functions give the value of the appropriate rotation matrix back.
|
||||
inline static Rotation RotY(double angle);
|
||||
//! The Rot... static functions give the value of the appropriate rotation matrix back.
|
||||
inline static Rotation RotZ(double angle);
|
||||
//! The DoRot... functions apply a rotation R to *this,such that *this = *this * Rot..
|
||||
//! DoRot... functions are only defined when they can be executed more efficiently
|
||||
inline void DoRotX(double angle);
|
||||
//! The DoRot... functions apply a rotation R to *this,such that *this = *this * Rot..
|
||||
//! DoRot... functions are only defined when they can be executed more efficiently
|
||||
inline void DoRotY(double angle);
|
||||
//! The DoRot... functions apply a rotation R to *this,such that *this = *this * Rot..
|
||||
//! DoRot... functions are only defined when they can be executed more efficiently
|
||||
inline void DoRotZ(double angle);
|
||||
|
||||
//! Along an arbitrary axes. It is not necessary to normalize rotaxis.
|
||||
//! returns identity rotation matrix in the case that the norm of rotaxis
|
||||
//! is too small to be used.
|
||||
// @see Rot2 if you want to handle this error in another way.
|
||||
static Rotation Rot(const Vector &rotaxis, double angle);
|
||||
// = Rotations
|
||||
//! The Rot... static functions give the value of the appropriate rotation matrix back.
|
||||
inline static Rotation RotX(double angle);
|
||||
//! The Rot... static functions give the value of the appropriate rotation matrix back.
|
||||
inline static Rotation RotY(double angle);
|
||||
//! The Rot... static functions give the value of the appropriate rotation matrix back.
|
||||
inline static Rotation RotZ(double angle);
|
||||
//! The DoRot... functions apply a rotation R to *this,such that *this = *this * Rot..
|
||||
//! DoRot... functions are only defined when they can be executed more efficiently
|
||||
inline void DoRotX(double angle);
|
||||
//! The DoRot... functions apply a rotation R to *this,such that *this = *this * Rot..
|
||||
//! DoRot... functions are only defined when they can be executed more efficiently
|
||||
inline void DoRotY(double angle);
|
||||
//! The DoRot... functions apply a rotation R to *this,such that *this = *this * Rot..
|
||||
//! DoRot... functions are only defined when they can be executed more efficiently
|
||||
inline void DoRotZ(double angle);
|
||||
|
||||
//! Along an arbitrary axes. rotvec should be normalized.
|
||||
static Rotation Rot2(const Vector &rotvec, double angle);
|
||||
//! Along an arbitrary axes. It is not necessary to normalize rotaxis.
|
||||
//! returns identity rotation matrix in the case that the norm of rotaxis
|
||||
//! is too small to be used.
|
||||
// @see Rot2 if you want to handle this error in another way.
|
||||
static Rotation Rot(const Vector& rotaxis,double angle);
|
||||
|
||||
// make sure the matrix is a pure rotation (no scaling)
|
||||
void Ortho();
|
||||
//! Along an arbitrary axes. rotvec should be normalized.
|
||||
static Rotation Rot2(const Vector& rotvec,double angle);
|
||||
|
||||
// make sure the matrix is a pure rotation (no scaling)
|
||||
void Ortho();
|
||||
|
||||
//! Returns a vector with the direction of the equiv. axis
|
||||
//! and its norm is angle
|
||||
Vector GetRot() const;
|
||||
//! Returns a vector with the direction of the equiv. axis
|
||||
//! and its norm is angle
|
||||
Vector GetRot() const;
|
||||
|
||||
//! Returns a 2D vector representing the equivalent rotation in the XZ plane that brings the
|
||||
//! Y axis onto the Matrix Y axis and its norm is angle
|
||||
Vector2 GetXZRot() const;
|
||||
//! Returns a 2D vector representing the equivalent rotation in the XZ plane that brings the
|
||||
//! Y axis onto the Matrix Y axis and its norm is angle
|
||||
Vector2 GetXZRot() const;
|
||||
|
||||
/** Returns the rotation angle around the equiv. axis
|
||||
* @param axis the rotation axis is returned in this variable
|
||||
* @param eps : in the case of angle == 0 : rot axis is undefined and choosen
|
||||
* to be +/- Z-axis
|
||||
* in the case of angle == PI : 2 solutions, positive Z-component
|
||||
* of the axis is choosen.
|
||||
* @result returns the rotation angle (between [0..PI] )
|
||||
*/
|
||||
double GetRotAngle(Vector &axis, double eps = epsilon) const;
|
||||
/** Returns the rotation angle around the equiv. axis
|
||||
* @param axis the rotation axis is returned in this variable
|
||||
* @param eps : in the case of angle == 0 : rot axis is undefined and choosen
|
||||
* to be +/- Z-axis
|
||||
* in the case of angle == PI : 2 solutions, positive Z-component
|
||||
* of the axis is choosen.
|
||||
* @result returns the rotation angle (between [0..PI] )
|
||||
*/
|
||||
double GetRotAngle(Vector& axis,double eps=epsilon) const;
|
||||
|
||||
//! Gives back a rotation matrix specified with EulerZYZ convention :
|
||||
//! First rotate around Z with alfa,
|
||||
//! then around the new Y with beta, then around
|
||||
//! new Z with gamma.
|
||||
static Rotation EulerZYZ(double Alfa, double Beta, double Gamma);
|
||||
|
||||
//! Gives back the EulerZYZ convention description of the rotation matrix :
|
||||
//! First rotate around Z with alfa,
|
||||
//! then around the new Y with beta, then around
|
||||
//! new Z with gamma.
|
||||
//!
|
||||
//! Variables are bound by
|
||||
//! (-PI <= alfa <= PI),
|
||||
//! (0 <= beta <= PI),
|
||||
//! (-PI <= alfa <= PI)
|
||||
void GetEulerZYZ(double &alfa, double &beta, double &gamma) const;
|
||||
//! Gives back a rotation matrix specified with EulerZYZ convention :
|
||||
//! First rotate around Z with alfa,
|
||||
//! then around the new Y with beta, then around
|
||||
//! new Z with gamma.
|
||||
static Rotation EulerZYZ(double Alfa,double Beta,double Gamma);
|
||||
|
||||
//! Sets the value of this object to a rotation specified with RPY convention:
|
||||
//! first rotate around X with roll, then around the
|
||||
//! old Y with pitch, then around old Z with alfa
|
||||
static Rotation RPY(double roll, double pitch, double yaw);
|
||||
//! Gives back the EulerZYZ convention description of the rotation matrix :
|
||||
//! First rotate around Z with alfa,
|
||||
//! then around the new Y with beta, then around
|
||||
//! new Z with gamma.
|
||||
//!
|
||||
//! Variables are bound by
|
||||
//! (-PI <= alfa <= PI),
|
||||
//! (0 <= beta <= PI),
|
||||
//! (-PI <= alfa <= PI)
|
||||
void GetEulerZYZ(double& alfa,double& beta,double& gamma) const;
|
||||
|
||||
//! Gives back a vector in RPY coordinates, variables are bound by
|
||||
//! -PI <= roll <= PI
|
||||
//! -PI <= Yaw <= PI
|
||||
//! -PI/2 <= PITCH <= PI/2
|
||||
//!
|
||||
//! convention : first rotate around X with roll, then around the
|
||||
//! old Y with pitch, then around old Z with alfa
|
||||
void GetRPY(double &roll, double &pitch, double &yaw) const;
|
||||
|
||||
//! Gives back a rotation matrix specified with EulerZYX convention :
|
||||
//! First rotate around Z with alfa,
|
||||
//! then around the new Y with beta, then around
|
||||
//! new X with gamma.
|
||||
//!
|
||||
//! closely related to RPY-convention
|
||||
inline static Rotation EulerZYX(double Alfa, double Beta, double Gamma)
|
||||
{
|
||||
return RPY(Gamma, Beta, Alfa);
|
||||
}
|
||||
//! Sets the value of this object to a rotation specified with RPY convention:
|
||||
//! first rotate around X with roll, then around the
|
||||
//! old Y with pitch, then around old Z with alfa
|
||||
static Rotation RPY(double roll,double pitch,double yaw);
|
||||
|
||||
//! GetEulerZYX gets the euler ZYX parameters of a rotation :
|
||||
//! First rotate around Z with alfa,
|
||||
//! then around the new Y with beta, then around
|
||||
//! new X with gamma.
|
||||
//!
|
||||
//! Range of the results of GetEulerZYX :
|
||||
//! -PI <= alfa <= PI
|
||||
//! -PI <= gamma <= PI
|
||||
//! -PI/2 <= beta <= PI/2
|
||||
//!
|
||||
//! Closely related to RPY-convention.
|
||||
inline void GetEulerZYX(double &Alfa, double &Beta, double &Gamma) const
|
||||
{
|
||||
GetRPY(Gamma, Beta, Alfa);
|
||||
}
|
||||
//! Gives back a vector in RPY coordinates, variables are bound by
|
||||
//! -PI <= roll <= PI
|
||||
//! -PI <= Yaw <= PI
|
||||
//! -PI/2 <= PITCH <= PI/2
|
||||
//!
|
||||
//! convention : first rotate around X with roll, then around the
|
||||
//! old Y with pitch, then around old Z with alfa
|
||||
void GetRPY(double& roll,double& pitch,double& yaw) const;
|
||||
|
||||
//! Transformation of the base to which the twist is expressed.
|
||||
//! Complexity : 18M+12A
|
||||
//! @see Frame*Twist for a transformation that also transforms
|
||||
//! the velocity reference point.
|
||||
inline Twist operator*(const Twist &arg) const;
|
||||
|
||||
//! Transformation of the base to which the wrench is expressed.
|
||||
//! Complexity : 18M+12A
|
||||
//! @see Frame*Wrench for a transformation that also transforms
|
||||
//! the force reference point.
|
||||
inline Wrench operator*(const Wrench &arg) const;
|
||||
//! Gives back a rotation matrix specified with EulerZYX convention :
|
||||
//! First rotate around Z with alfa,
|
||||
//! then around the new Y with beta, then around
|
||||
//! new X with gamma.
|
||||
//!
|
||||
//! closely related to RPY-convention
|
||||
inline static Rotation EulerZYX(double Alfa,double Beta,double Gamma) {
|
||||
return RPY(Gamma,Beta,Alfa);
|
||||
}
|
||||
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline Vector UnitX() const
|
||||
{
|
||||
return Vector(data[0], data[3], data[6]);
|
||||
}
|
||||
//! GetEulerZYX gets the euler ZYX parameters of a rotation :
|
||||
//! First rotate around Z with alfa,
|
||||
//! then around the new Y with beta, then around
|
||||
//! new X with gamma.
|
||||
//!
|
||||
//! Range of the results of GetEulerZYX :
|
||||
//! -PI <= alfa <= PI
|
||||
//! -PI <= gamma <= PI
|
||||
//! -PI/2 <= beta <= PI/2
|
||||
//!
|
||||
//! Closely related to RPY-convention.
|
||||
inline void GetEulerZYX(double& Alfa,double& Beta,double& Gamma) const {
|
||||
GetRPY(Gamma,Beta,Alfa);
|
||||
}
|
||||
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline void UnitX(const Vector &X)
|
||||
{
|
||||
data[0] = X(0);
|
||||
data[3] = X(1);
|
||||
data[6] = X(2);
|
||||
}
|
||||
//! Transformation of the base to which the twist is expressed.
|
||||
//! Complexity : 18M+12A
|
||||
//! @see Frame*Twist for a transformation that also transforms
|
||||
//! the velocity reference point.
|
||||
inline Twist operator * (const Twist& arg) const;
|
||||
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline Vector UnitY() const
|
||||
{
|
||||
return Vector(data[1], data[4], data[7]);
|
||||
}
|
||||
//! Transformation of the base to which the wrench is expressed.
|
||||
//! Complexity : 18M+12A
|
||||
//! @see Frame*Wrench for a transformation that also transforms
|
||||
//! the force reference point.
|
||||
inline Wrench operator * (const Wrench& arg) const;
|
||||
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline void UnitY(const Vector &X)
|
||||
{
|
||||
data[1] = X(0);
|
||||
data[4] = X(1);
|
||||
data[7] = X(2);
|
||||
}
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline Vector UnitX() const {
|
||||
return Vector(data[0],data[3],data[6]);
|
||||
}
|
||||
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline Vector UnitZ() const
|
||||
{
|
||||
return Vector(data[2], data[5], data[8]);
|
||||
}
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline void UnitX(const Vector& X) {
|
||||
data[0] = X(0);
|
||||
data[3] = X(1);
|
||||
data[6] = X(2);
|
||||
}
|
||||
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline void UnitZ(const Vector &X)
|
||||
{
|
||||
data[2] = X(0);
|
||||
data[5] = X(1);
|
||||
data[8] = X(2);
|
||||
}
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline Vector UnitY() const {
|
||||
return Vector(data[1],data[4],data[7]);
|
||||
}
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline void UnitY(const Vector& X) {
|
||||
data[1] = X(0);
|
||||
data[4] = X(1);
|
||||
data[7] = X(2);
|
||||
}
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
friend bool operator==(const Rotation &a, const Rotation &b);
|
||||
//! The literal inequality operator!=()
|
||||
friend bool operator!=(const Rotation &a, const Rotation &b);
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline Vector UnitZ() const {
|
||||
return Vector(data[2],data[5],data[8]);
|
||||
}
|
||||
|
||||
friend class Frame;
|
||||
//! Access to the underlying unitvectors of the rotation matrix
|
||||
inline void UnitZ(const Vector& X) {
|
||||
data[2] = X(0);
|
||||
data[5] = X(1);
|
||||
data[8] = X(2);
|
||||
}
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
friend bool operator==(const Rotation& a,const Rotation& b);
|
||||
//! The literal inequality operator!=()
|
||||
friend bool operator!=(const Rotation& a,const Rotation& b);
|
||||
|
||||
friend class Frame;
|
||||
};
|
||||
bool operator==(const Rotation &a, const Rotation &b);
|
||||
bool operator==(const Rotation& a,const Rotation& b);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief represents a frame transformation in 3D space (rotation + translation)
|
||||
\brief represents a frame transformation in 3D space (rotation + translation)
|
||||
|
||||
if V2 = Frame*V1 (V2 expressed in frame A, V1 expressed in frame B)
|
||||
then V2 = Frame.M*V1+Frame.p
|
||||
@@ -523,148 +524,150 @@ bool operator==(const Rotation &a, const Rotation &b);
|
||||
Frame.p contains the origin of frame B expressed in frame A.
|
||||
*/
|
||||
class Frame {
|
||||
public:
|
||||
Vector p; //!< origine of the Frame
|
||||
Rotation M; //!< Orientation of the Frame
|
||||
public:
|
||||
Vector p; //!< origine of the Frame
|
||||
Rotation M; //!< Orientation of the Frame
|
||||
|
||||
public:
|
||||
inline Frame(const Rotation &R, const Vector &V);
|
||||
public:
|
||||
|
||||
//! The rotation matrix defaults to identity
|
||||
explicit inline Frame(const Vector &V);
|
||||
//! The position matrix defaults to zero
|
||||
explicit inline Frame(const Rotation &R);
|
||||
inline Frame(const Rotation& R,const Vector& V);
|
||||
|
||||
inline void setValue(float *oglmat);
|
||||
inline void getValue(float *oglmat) const;
|
||||
//! The rotation matrix defaults to identity
|
||||
explicit inline Frame(const Vector& V);
|
||||
//! The position matrix defaults to zero
|
||||
explicit inline Frame(const Rotation& R);
|
||||
|
||||
inline Frame() {}
|
||||
//! The copy constructor. Normal copy by value semantics.
|
||||
inline Frame(const Frame &arg);
|
||||
inline void setValue(float* oglmat);
|
||||
inline void getValue(float* oglmat) const;
|
||||
|
||||
//! Reads data from an double array
|
||||
//\TODO should be formulated as a constructor
|
||||
void Make4x4(double *d);
|
||||
inline Frame() {}
|
||||
//! The copy constructor. Normal copy by value semantics.
|
||||
inline Frame(const Frame& arg);
|
||||
|
||||
//! Treats a frame as a 4x4 matrix and returns element i,j
|
||||
//! Access to elements 0..3,0..3, bounds are checked when NDEBUG is not set
|
||||
inline double operator()(int i, int j);
|
||||
//! Reads data from an double array
|
||||
//\TODO should be formulated as a constructor
|
||||
void Make4x4(double* d);
|
||||
|
||||
//! Treats a frame as a 4x4 matrix and returns element i,j
|
||||
//! Access to elements 0..3,0..3, bounds are checked when NDEBUG is not set
|
||||
inline double operator()(int i, int j) const;
|
||||
//! Treats a frame as a 4x4 matrix and returns element i,j
|
||||
//! Access to elements 0..3,0..3, bounds are checked when NDEBUG is not set
|
||||
inline double operator()(int i,int j);
|
||||
|
||||
// = Inverse
|
||||
//! Gives back inverse transformation of a Frame
|
||||
inline Frame Inverse() const;
|
||||
//! Treats a frame as a 4x4 matrix and returns element i,j
|
||||
//! Access to elements 0..3,0..3, bounds are checked when NDEBUG is not set
|
||||
inline double operator() (int i,int j) const;
|
||||
|
||||
//! The same as p2=R.Inverse()*p but more efficient.
|
||||
inline Vector Inverse(const Vector &arg) const;
|
||||
// = Inverse
|
||||
//! Gives back inverse transformation of a Frame
|
||||
inline Frame Inverse() const;
|
||||
|
||||
//! The same as p2=R.Inverse()*p but more efficient.
|
||||
inline Wrench Inverse(const Wrench &arg) const;
|
||||
//! The same as p2=R.Inverse()*p but more efficient.
|
||||
inline Vector Inverse(const Vector& arg) const;
|
||||
|
||||
//! The same as p2=R.Inverse()*p but more efficient.
|
||||
inline Twist Inverse(const Twist &arg) const;
|
||||
//! The same as p2=R.Inverse()*p but more efficient.
|
||||
inline Wrench Inverse(const Wrench& arg) const;
|
||||
|
||||
//! Normal copy-by-value semantics.
|
||||
inline Frame &operator=(const Frame &arg);
|
||||
//! The same as p2=R.Inverse()*p but more efficient.
|
||||
inline Twist Inverse(const Twist& arg) const;
|
||||
|
||||
//! Transformation of the base to which the vector
|
||||
//! is expressed.
|
||||
inline Vector operator*(const Vector &arg) const;
|
||||
//! Normal copy-by-value semantics.
|
||||
inline Frame& operator = (const Frame& arg);
|
||||
|
||||
//! Transformation of both the force reference point
|
||||
//! and of the base to which the wrench is expressed.
|
||||
//! look at Rotation*Wrench operator for a transformation
|
||||
//! of only the base to which the twist is expressed.
|
||||
//!
|
||||
//! Complexity : 24M+18A
|
||||
inline Wrench operator*(const Wrench &arg) const;
|
||||
//! Transformation of the base to which the vector
|
||||
//! is expressed.
|
||||
inline Vector operator * (const Vector& arg) const;
|
||||
|
||||
//! Transformation of both the velocity reference point
|
||||
//! and of the base to which the twist is expressed.
|
||||
//! look at Rotation*Twist for a transformation of only the
|
||||
//! base to which the twist is expressed.
|
||||
//!
|
||||
//! Complexity : 24M+18A
|
||||
inline Twist operator*(const Twist &arg) const;
|
||||
//! Transformation of both the force reference point
|
||||
//! and of the base to which the wrench is expressed.
|
||||
//! look at Rotation*Wrench operator for a transformation
|
||||
//! of only the base to which the twist is expressed.
|
||||
//!
|
||||
//! Complexity : 24M+18A
|
||||
inline Wrench operator * (const Wrench& arg) const;
|
||||
|
||||
//! Composition of two frames.
|
||||
inline friend Frame operator*(const Frame &lhs, const Frame &rhs);
|
||||
//! Transformation of both the velocity reference point
|
||||
//! and of the base to which the twist is expressed.
|
||||
//! look at Rotation*Twist for a transformation of only the
|
||||
//! base to which the twist is expressed.
|
||||
//!
|
||||
//! Complexity : 24M+18A
|
||||
inline Twist operator * (const Twist& arg) const;
|
||||
|
||||
//! @return the identity transformation Frame(Rotation::Identity(),Vector::Zero()).
|
||||
inline static Frame Identity();
|
||||
//! Composition of two frames.
|
||||
inline friend Frame operator *(const Frame& lhs,const Frame& rhs);
|
||||
|
||||
//! The twist <t_this> is expressed wrt the current
|
||||
//! frame. This frame is integrated into an updated frame with
|
||||
//! <samplefrequency>. Very simple first order integration rule.
|
||||
inline void Integrate(const Twist &t_this, double frequency);
|
||||
//! @return the identity transformation Frame(Rotation::Identity(),Vector::Zero()).
|
||||
inline static Frame Identity();
|
||||
|
||||
/*
|
||||
// DH_Craig1989 : constructs a transformationmatrix
|
||||
// T_link(i-1)_link(i) with the Denavit-Hartenberg convention as
|
||||
// described in the Craigs book: Craig, J. J.,Introduction to
|
||||
// Robotics: Mechanics and Control, Addison-Wesley,
|
||||
// isbn:0-201-10326-5, 1986.
|
||||
//
|
||||
// Note that the frame is a redundant way to express the information
|
||||
// in the DH-convention.
|
||||
// \verbatim
|
||||
// Parameters in full : a(i-1),alpha(i-1),d(i),theta(i)
|
||||
//
|
||||
// axis i-1 is connected by link i-1 to axis i numbering axis 1
|
||||
// to axis n link 0 (immobile base) to link n
|
||||
//
|
||||
// link length a(i-1) length of the mutual perpendicular line
|
||||
// (normal) between the 2 axes. This normal runs from (i-1) to
|
||||
// (i) axis.
|
||||
//
|
||||
// link twist alpha(i-1): construct plane perpendicular to the
|
||||
// normal project axis(i-1) and axis(i) into plane angle from
|
||||
// (i-1) to (i) measured in the direction of the normal
|
||||
//
|
||||
// link offset d(i) signed distance between normal (i-1) to (i)
|
||||
// and normal (i) to (i+1) along axis i joint angle theta(i)
|
||||
// signed angle between normal (i-1) to (i) and normal (i) to
|
||||
// (i+1) along axis i
|
||||
//
|
||||
// First and last joints : a(0)= a(n) = 0
|
||||
// alpha(0) = alpha(n) = 0
|
||||
//
|
||||
// PRISMATIC : theta(1) = 0 d(1) arbitrarily
|
||||
//
|
||||
// REVOLUTE : theta(1) arbitrarily d(1) = 0
|
||||
//
|
||||
// Not unique : if intersecting joint axis 2 choices for normal
|
||||
// Frame assignment of the DH convention : Z(i-1) follows axis
|
||||
// (i-1) X(i-1) is the normal between axis(i-1) and axis(i)
|
||||
// Y(i-1) follows out of Z(i-1) and X(i-1)
|
||||
//
|
||||
// a(i-1) = distance from Z(i-1) to Z(i) along X(i-1)
|
||||
// alpha(i-1) = angle between Z(i-1) to Z(i) along X(i-1)
|
||||
// d(i) = distance from X(i-1) to X(i) along Z(i)
|
||||
// theta(i) = angle between X(i-1) to X(i) along X(i)
|
||||
// \endverbatim
|
||||
*/
|
||||
static Frame DH_Craig1989(double a, double alpha, double d, double theta);
|
||||
//! The twist <t_this> is expressed wrt the current
|
||||
//! frame. This frame is integrated into an updated frame with
|
||||
//! <samplefrequency>. Very simple first order integration rule.
|
||||
inline void Integrate(const Twist& t_this,double frequency);
|
||||
|
||||
// DH : constructs a transformationmatrix T_link(i-1)_link(i) with
|
||||
// the Denavit-Hartenberg convention as described in the original
|
||||
// publictation: Denavit, J. and Hartenberg, R. S., A kinematic
|
||||
// notation for lower-pair mechanisms based on matrices, ASME
|
||||
// Journal of Applied Mechanics, 23:215-221, 1955.
|
||||
/*
|
||||
// DH_Craig1989 : constructs a transformationmatrix
|
||||
// T_link(i-1)_link(i) with the Denavit-Hartenberg convention as
|
||||
// described in the Craigs book: Craig, J. J.,Introduction to
|
||||
// Robotics: Mechanics and Control, Addison-Wesley,
|
||||
// isbn:0-201-10326-5, 1986.
|
||||
//
|
||||
// Note that the frame is a redundant way to express the information
|
||||
// in the DH-convention.
|
||||
// \verbatim
|
||||
// Parameters in full : a(i-1),alpha(i-1),d(i),theta(i)
|
||||
//
|
||||
// axis i-1 is connected by link i-1 to axis i numbering axis 1
|
||||
// to axis n link 0 (immobile base) to link n
|
||||
//
|
||||
// link length a(i-1) length of the mutual perpendicular line
|
||||
// (normal) between the 2 axes. This normal runs from (i-1) to
|
||||
// (i) axis.
|
||||
//
|
||||
// link twist alpha(i-1): construct plane perpendicular to the
|
||||
// normal project axis(i-1) and axis(i) into plane angle from
|
||||
// (i-1) to (i) measured in the direction of the normal
|
||||
//
|
||||
// link offset d(i) signed distance between normal (i-1) to (i)
|
||||
// and normal (i) to (i+1) along axis i joint angle theta(i)
|
||||
// signed angle between normal (i-1) to (i) and normal (i) to
|
||||
// (i+1) along axis i
|
||||
//
|
||||
// First and last joints : a(0)= a(n) = 0
|
||||
// alpha(0) = alpha(n) = 0
|
||||
//
|
||||
// PRISMATIC : theta(1) = 0 d(1) arbitrarily
|
||||
//
|
||||
// REVOLUTE : theta(1) arbitrarily d(1) = 0
|
||||
//
|
||||
// Not unique : if intersecting joint axis 2 choices for normal
|
||||
// Frame assignment of the DH convention : Z(i-1) follows axis
|
||||
// (i-1) X(i-1) is the normal between axis(i-1) and axis(i)
|
||||
// Y(i-1) follows out of Z(i-1) and X(i-1)
|
||||
//
|
||||
// a(i-1) = distance from Z(i-1) to Z(i) along X(i-1)
|
||||
// alpha(i-1) = angle between Z(i-1) to Z(i) along X(i-1)
|
||||
// d(i) = distance from X(i-1) to X(i) along Z(i)
|
||||
// theta(i) = angle between X(i-1) to X(i) along X(i)
|
||||
// \endverbatim
|
||||
*/
|
||||
static Frame DH_Craig1989(double a,double alpha,double d,double theta);
|
||||
|
||||
static Frame DH(double a, double alpha, double d, double theta);
|
||||
// DH : constructs a transformationmatrix T_link(i-1)_link(i) with
|
||||
// the Denavit-Hartenberg convention as described in the original
|
||||
// publictation: Denavit, J. and Hartenberg, R. S., A kinematic
|
||||
// notation for lower-pair mechanisms based on matrices, ASME
|
||||
// Journal of Applied Mechanics, 23:215-221, 1955.
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Frame &a, const Frame &b, double eps);
|
||||
static Frame DH(double a,double alpha,double d,double theta);
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const Frame &a, const Frame &b);
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const Frame &a, const Frame &b);
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Frame& a,const Frame& b,double eps);
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const Frame& a,const Frame& b);
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const Frame& a,const Frame& b);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -672,72 +675,76 @@ class Frame {
|
||||
*
|
||||
* This class represents a twist. A twist is the combination of translational
|
||||
* velocity and rotational velocity applied at one point.
|
||||
*/
|
||||
*/
|
||||
class Twist {
|
||||
public:
|
||||
Vector vel; //!< The velocity of that point
|
||||
Vector rot; //!< The rotational velocity of that point.
|
||||
public:
|
||||
//! The default constructor initialises to Zero via the constructor of Vector.
|
||||
Twist() : vel(), rot(){};
|
||||
public:
|
||||
Vector vel; //!< The velocity of that point
|
||||
Vector rot; //!< The rotational velocity of that point.
|
||||
public:
|
||||
|
||||
Twist(const Vector &_vel, const Vector &_rot) : vel(_vel), rot(_rot){};
|
||||
//! The default constructor initialises to Zero via the constructor of Vector.
|
||||
Twist():vel(),rot() {};
|
||||
|
||||
inline Twist &operator-=(const Twist &arg);
|
||||
inline Twist &operator+=(const Twist &arg);
|
||||
//! index-based access to components, first vel(0..2), then rot(3..5)
|
||||
inline double &operator()(int i);
|
||||
Twist(const Vector& _vel,const Vector& _rot):vel(_vel),rot(_rot) {};
|
||||
|
||||
//! index-based access to components, first vel(0..2), then rot(3..5)
|
||||
//! For use with a const Twist
|
||||
inline double operator()(int i) const;
|
||||
inline Twist& operator-=(const Twist& arg);
|
||||
inline Twist& operator+=(const Twist& arg);
|
||||
//! index-based access to components, first vel(0..2), then rot(3..5)
|
||||
inline double& operator()(int i);
|
||||
|
||||
double operator[](int index) const
|
||||
{
|
||||
return this->operator()(index);
|
||||
}
|
||||
//! index-based access to components, first vel(0..2), then rot(3..5)
|
||||
//! For use with a const Twist
|
||||
inline double operator()(int i) const;
|
||||
|
||||
double &operator[](int index)
|
||||
{
|
||||
return this->operator()(index);
|
||||
}
|
||||
double operator[] ( int index ) const
|
||||
{
|
||||
return this->operator() ( index );
|
||||
}
|
||||
|
||||
inline friend Twist operator*(const Twist &lhs, double rhs);
|
||||
inline friend Twist operator*(double lhs, const Twist &rhs);
|
||||
inline friend Twist operator/(const Twist &lhs, double rhs);
|
||||
inline friend Twist operator+(const Twist &lhs, const Twist &rhs);
|
||||
inline friend Twist operator-(const Twist &lhs, const Twist &rhs);
|
||||
inline friend Twist operator-(const Twist &arg);
|
||||
inline friend double dot(const Twist &lhs, const Wrench &rhs);
|
||||
inline friend double dot(const Wrench &rhs, const Twist &lhs);
|
||||
inline friend void SetToZero(Twist &v);
|
||||
double& operator[] ( int index )
|
||||
{
|
||||
return this->operator() ( index );
|
||||
}
|
||||
|
||||
//! @return a zero Twist : Twist(Vector::Zero(),Vector::Zero())
|
||||
static inline Twist Zero();
|
||||
inline friend Twist operator*(const Twist& lhs,double rhs);
|
||||
inline friend Twist operator*(double lhs,const Twist& rhs);
|
||||
inline friend Twist operator/(const Twist& lhs,double rhs);
|
||||
inline friend Twist operator+(const Twist& lhs,const Twist& rhs);
|
||||
inline friend Twist operator-(const Twist& lhs,const Twist& rhs);
|
||||
inline friend Twist operator-(const Twist& arg);
|
||||
inline friend double dot(const Twist& lhs,const Wrench& rhs);
|
||||
inline friend double dot(const Wrench& rhs,const Twist& lhs);
|
||||
inline friend void SetToZero(Twist& v);
|
||||
|
||||
//! Reverses the sign of the twist
|
||||
inline void ReverseSign();
|
||||
|
||||
//! Changes the reference point of the twist.
|
||||
//! The vector v_base_AB is expressed in the same base as the twist
|
||||
//! The vector v_base_AB is a vector from the old point to
|
||||
//! the new point.
|
||||
//!
|
||||
//! Complexity : 6M+6A
|
||||
inline Twist RefPoint(const Vector &v_base_AB) const;
|
||||
//! @return a zero Twist : Twist(Vector::Zero(),Vector::Zero())
|
||||
static inline Twist Zero();
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Twist &a, const Twist &b, double eps);
|
||||
//! Reverses the sign of the twist
|
||||
inline void ReverseSign();
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const Twist &a, const Twist &b);
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const Twist &a, const Twist &b);
|
||||
//! Changes the reference point of the twist.
|
||||
//! The vector v_base_AB is expressed in the same base as the twist
|
||||
//! The vector v_base_AB is a vector from the old point to
|
||||
//! the new point.
|
||||
//!
|
||||
//! Complexity : 6M+6A
|
||||
inline Twist RefPoint(const Vector& v_base_AB) const;
|
||||
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Twist& a,const Twist& b,double eps);
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const Twist& a,const Twist& b);
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const Twist& a,const Twist& b);
|
||||
|
||||
// = Friends
|
||||
friend class Rotation;
|
||||
friend class Frame;
|
||||
|
||||
// = Friends
|
||||
friend class Rotation;
|
||||
friend class Frame;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -746,7 +753,7 @@ class Twist {
|
||||
* This class represents an acceleration twist. A acceleration twist is
|
||||
* the combination of translational
|
||||
* acceleration and rotational acceleration applied at one point.
|
||||
*/
|
||||
*/
|
||||
/*
|
||||
class AccelerationTwist {
|
||||
public:
|
||||
@@ -770,21 +777,20 @@ public:
|
||||
|
||||
double operator[] ( int index ) const
|
||||
{
|
||||
return this->operator() ( index );
|
||||
}
|
||||
return this->operator() ( index );
|
||||
}
|
||||
|
||||
double& operator[] ( int index )
|
||||
{
|
||||
return this->operator() ( index );
|
||||
return this->operator() ( index );
|
||||
}
|
||||
|
||||
inline friend AccelerationTwist operator*(const AccelerationTwist& lhs,double rhs);
|
||||
inline friend AccelerationTwist operator*(double lhs,const AccelerationTwist& rhs);
|
||||
inline friend AccelerationTwist operator/(const AccelerationTwist& lhs,double rhs);
|
||||
inline friend AccelerationTwist operator+(const AccelerationTwist& lhs,const
|
||||
AccelerationTwist& rhs); inline friend AccelerationTwist operator-(const AccelerationTwist&
|
||||
lhs,const AccelerationTwist& rhs); inline friend AccelerationTwist operator-(const
|
||||
AccelerationTwist& arg);
|
||||
inline friend AccelerationTwist operator+(const AccelerationTwist& lhs,const AccelerationTwist& rhs);
|
||||
inline friend AccelerationTwist operator-(const AccelerationTwist& lhs,const AccelerationTwist& rhs);
|
||||
inline friend AccelerationTwist operator-(const AccelerationTwist& arg);
|
||||
//inline friend double dot(const AccelerationTwist& lhs,const Wrench& rhs);
|
||||
//inline friend double dot(const Wrench& rhs,const AccelerationTwist& lhs);
|
||||
inline friend void SetToZero(AccelerationTwist& v);
|
||||
@@ -807,12 +813,11 @@ AccelerationTwist& arg);
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const AccelerationTwist& a,const AccelerationTwist& b,double
|
||||
eps=epsilon);
|
||||
inline friend bool Equal(const AccelerationTwist& a,const AccelerationTwist& b,double eps=epsilon);
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const AccelerationTwist& a,const AccelerationTwist& b);
|
||||
//! The literal inequality operator!=().
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const AccelerationTwist& a,const AccelerationTwist& b);
|
||||
|
||||
// = Friends
|
||||
@@ -826,270 +831,278 @@ eps=epsilon);
|
||||
*
|
||||
* This class represents a Wrench. A Wrench is the force and torque applied at a point
|
||||
*/
|
||||
class Wrench {
|
||||
public:
|
||||
Vector force; //!< Force that is applied at the origin of the current ref frame
|
||||
Vector torque; //!< Torque that is applied at the origin of the current ref frame
|
||||
public:
|
||||
//! Does initialise force and torque to zero via the underlying constructor of Vector
|
||||
Wrench() : force(), torque(){};
|
||||
Wrench(const Vector &_force, const Vector &_torque) : force(_force), torque(_torque){};
|
||||
class Wrench
|
||||
{
|
||||
public:
|
||||
Vector force; //!< Force that is applied at the origin of the current ref frame
|
||||
Vector torque; //!< Torque that is applied at the origin of the current ref frame
|
||||
public:
|
||||
|
||||
// = Operators
|
||||
inline Wrench &operator-=(const Wrench &arg);
|
||||
inline Wrench &operator+=(const Wrench &arg);
|
||||
//! Does initialise force and torque to zero via the underlying constructor of Vector
|
||||
Wrench():force(),torque() {};
|
||||
Wrench(const Vector& _force,const Vector& _torque):force(_force),torque(_torque) {};
|
||||
|
||||
//! index-based access to components, first force(0..2), then torque(3..5)
|
||||
inline double &operator()(int i);
|
||||
// = Operators
|
||||
inline Wrench& operator-=(const Wrench& arg);
|
||||
inline Wrench& operator+=(const Wrench& arg);
|
||||
|
||||
//! index-based access to components, first force(0..2), then torque(3..5)
|
||||
//! for use with a const Wrench
|
||||
inline double operator()(int i) const;
|
||||
//! index-based access to components, first force(0..2), then torque(3..5)
|
||||
inline double& operator()(int i);
|
||||
|
||||
double operator[](int index) const
|
||||
{
|
||||
return this->operator()(index);
|
||||
}
|
||||
//! index-based access to components, first force(0..2), then torque(3..5)
|
||||
//! for use with a const Wrench
|
||||
inline double operator()(int i) const;
|
||||
|
||||
double &operator[](int index)
|
||||
{
|
||||
return this->operator()(index);
|
||||
}
|
||||
double operator[] ( int index ) const
|
||||
{
|
||||
return this->operator() ( index );
|
||||
}
|
||||
|
||||
//! Scalar multiplication
|
||||
inline friend Wrench operator*(const Wrench &lhs, double rhs);
|
||||
//! Scalar multiplication
|
||||
inline friend Wrench operator*(double lhs, const Wrench &rhs);
|
||||
//! Scalar division
|
||||
inline friend Wrench operator/(const Wrench &lhs, double rhs);
|
||||
double& operator[] ( int index )
|
||||
{
|
||||
return this->operator() ( index );
|
||||
}
|
||||
|
||||
inline friend Wrench operator+(const Wrench &lhs, const Wrench &rhs);
|
||||
inline friend Wrench operator-(const Wrench &lhs, const Wrench &rhs);
|
||||
//! Scalar multiplication
|
||||
inline friend Wrench operator*(const Wrench& lhs,double rhs);
|
||||
//! Scalar multiplication
|
||||
inline friend Wrench operator*(double lhs,const Wrench& rhs);
|
||||
//! Scalar division
|
||||
inline friend Wrench operator/(const Wrench& lhs,double rhs);
|
||||
|
||||
//! An unary - operator
|
||||
inline friend Wrench operator-(const Wrench &arg);
|
||||
inline friend Wrench operator+(const Wrench& lhs,const Wrench& rhs);
|
||||
inline friend Wrench operator-(const Wrench& lhs,const Wrench& rhs);
|
||||
|
||||
//! Sets the Wrench to Zero, to have a uniform function that sets an object or
|
||||
//! double to zero.
|
||||
inline friend void SetToZero(Wrench &v);
|
||||
//! An unary - operator
|
||||
inline friend Wrench operator-(const Wrench& arg);
|
||||
|
||||
//! @return a zero Wrench
|
||||
static inline Wrench Zero();
|
||||
//! Sets the Wrench to Zero, to have a uniform function that sets an object or
|
||||
//! double to zero.
|
||||
inline friend void SetToZero(Wrench& v);
|
||||
|
||||
//! Reverses the sign of the current Wrench
|
||||
inline void ReverseSign();
|
||||
//! @return a zero Wrench
|
||||
static inline Wrench Zero();
|
||||
|
||||
//! Changes the reference point of the wrench.
|
||||
//! The vector v_base_AB is expressed in the same base as the twist
|
||||
//! The vector v_base_AB is a vector from the old point to
|
||||
//! the new point.
|
||||
//!
|
||||
//! Complexity : 6M+6A
|
||||
inline Wrench RefPoint(const Vector &v_base_AB) const;
|
||||
//! Reverses the sign of the current Wrench
|
||||
inline void ReverseSign();
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Wrench &a, const Wrench &b, double eps);
|
||||
//! Changes the reference point of the wrench.
|
||||
//! The vector v_base_AB is expressed in the same base as the twist
|
||||
//! The vector v_base_AB is a vector from the old point to
|
||||
//! the new point.
|
||||
//!
|
||||
//! Complexity : 6M+6A
|
||||
inline Wrench RefPoint(const Vector& v_base_AB) const;
|
||||
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Wrench& a,const Wrench& b,double eps);
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const Wrench& a,const Wrench& b);
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const Wrench& a,const Wrench& b);
|
||||
|
||||
friend class Rotation;
|
||||
friend class Frame;
|
||||
|
||||
//! The literal equality operator==(), also identical.
|
||||
inline friend bool operator==(const Wrench &a, const Wrench &b);
|
||||
//! The literal inequality operator!=().
|
||||
inline friend bool operator!=(const Wrench &a, const Wrench &b);
|
||||
|
||||
friend class Rotation;
|
||||
friend class Frame;
|
||||
};
|
||||
|
||||
|
||||
//! 2D version of Vector
|
||||
class Vector2 {
|
||||
double data[2];
|
||||
class Vector2
|
||||
{
|
||||
double data[2];
|
||||
public:
|
||||
//! Does not initialise to Zero().
|
||||
Vector2() {data[0]=data[1] = 0.0;}
|
||||
inline Vector2(double x,double y);
|
||||
inline Vector2(const Vector2& arg);
|
||||
inline Vector2(double* xyz);
|
||||
inline Vector2(float* xyz);
|
||||
|
||||
public:
|
||||
//! Does not initialise to Zero().
|
||||
Vector2()
|
||||
{
|
||||
data[0] = data[1] = 0.0;
|
||||
}
|
||||
inline Vector2(double x, double y);
|
||||
inline Vector2(const Vector2 &arg);
|
||||
inline Vector2(double *xyz);
|
||||
inline Vector2(float *xyz);
|
||||
inline Vector2& operator = ( const Vector2& arg);
|
||||
|
||||
inline Vector2 &operator=(const Vector2 &arg);
|
||||
//! Access to elements, range checked when NDEBUG is not set, from 0..1
|
||||
inline double operator()(int index) const;
|
||||
|
||||
//! Access to elements, range checked when NDEBUG is not set, from 0..1
|
||||
inline double operator()(int index) const;
|
||||
//! Access to elements, range checked when NDEBUG is not set, from 0..1
|
||||
inline double& operator() (int index);
|
||||
|
||||
//! Access to elements, range checked when NDEBUG is not set, from 0..1
|
||||
inline double &operator()(int index);
|
||||
//! store vector components in array
|
||||
inline void GetValue(double* xy) const;
|
||||
|
||||
//! store vector components in array
|
||||
inline void GetValue(double *xy) const;
|
||||
inline void ReverseSign();
|
||||
inline Vector2& operator-=(const Vector2& arg);
|
||||
inline Vector2& operator +=(const Vector2& arg);
|
||||
|
||||
inline void ReverseSign();
|
||||
inline Vector2 &operator-=(const Vector2 &arg);
|
||||
inline Vector2 &operator+=(const Vector2 &arg);
|
||||
|
||||
inline friend Vector2 operator*(const Vector2 &lhs, double rhs);
|
||||
inline friend Vector2 operator*(double lhs, const Vector2 &rhs);
|
||||
inline friend Vector2 operator/(const Vector2 &lhs, double rhs);
|
||||
inline friend Vector2 operator+(const Vector2 &lhs, const Vector2 &rhs);
|
||||
inline friend Vector2 operator-(const Vector2 &lhs, const Vector2 &rhs);
|
||||
inline friend Vector2 operator*(const Vector2 &lhs, const Vector2 &rhs);
|
||||
inline friend Vector2 operator-(const Vector2 &arg);
|
||||
inline friend void SetToZero(Vector2 &v);
|
||||
inline friend Vector2 operator*(const Vector2& lhs,double rhs);
|
||||
inline friend Vector2 operator*(double lhs,const Vector2& rhs);
|
||||
inline friend Vector2 operator/(const Vector2& lhs,double rhs);
|
||||
inline friend Vector2 operator+(const Vector2& lhs,const Vector2& rhs);
|
||||
inline friend Vector2 operator-(const Vector2& lhs,const Vector2& rhs);
|
||||
inline friend Vector2 operator*(const Vector2& lhs,const Vector2& rhs);
|
||||
inline friend Vector2 operator-(const Vector2& arg);
|
||||
inline friend void SetToZero(Vector2& v);
|
||||
|
||||
//! @return a zero 2D vector.
|
||||
inline static Vector2 Zero();
|
||||
//! @return a zero 2D vector.
|
||||
inline static Vector2 Zero();
|
||||
|
||||
/** Normalizes this vector and returns it norm
|
||||
* makes v a unitvector and returns the norm of v.
|
||||
* if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
|
||||
* if this is not good, check the return value of this method.
|
||||
*/
|
||||
double Normalize(double eps = epsilon);
|
||||
/** Normalizes this vector and returns it norm
|
||||
* makes v a unitvector and returns the norm of v.
|
||||
* if v is smaller than eps, Vector(1,0,0) is returned with norm 0.
|
||||
* if this is not good, check the return value of this method.
|
||||
*/
|
||||
double Normalize(double eps=epsilon);
|
||||
|
||||
//! @return the norm of the vector
|
||||
inline double Norm() const;
|
||||
//! @return the norm of the vector
|
||||
inline double Norm() const;
|
||||
|
||||
//! projects v in its XY plane, and sets *this to these values
|
||||
inline void Set3DXY(const Vector &v);
|
||||
//! projects v in its XY plane, and sets *this to these values
|
||||
inline void Set3DXY(const Vector& v);
|
||||
|
||||
//! projects v in its YZ plane, and sets *this to these values
|
||||
inline void Set3DYZ(const Vector &v);
|
||||
//! projects v in its YZ plane, and sets *this to these values
|
||||
inline void Set3DYZ(const Vector& v);
|
||||
|
||||
//! projects v in its ZX plane, and sets *this to these values
|
||||
inline void Set3DZX(const Vector &v);
|
||||
//! projects v in its ZX plane, and sets *this to these values
|
||||
inline void Set3DZX(const Vector& v);
|
||||
|
||||
//! projects v_someframe in the XY plane of F_someframe_XY,
|
||||
//! and sets *this to these values
|
||||
//! expressed wrt someframe.
|
||||
inline void Set3DPlane(const Frame &F_someframe_XY, const Vector &v_someframe);
|
||||
//! projects v_someframe in the XY plane of F_someframe_XY,
|
||||
//! and sets *this to these values
|
||||
//! expressed wrt someframe.
|
||||
inline void Set3DPlane(const Frame& F_someframe_XY,const Vector& v_someframe);
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Vector2 &a, const Vector2 &b, double eps);
|
||||
|
||||
friend class Rotation2;
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Vector2& a,const Vector2& b,double eps);
|
||||
|
||||
friend class Rotation2;
|
||||
};
|
||||
|
||||
|
||||
//! A 2D Rotation class, for conventions see Rotation. For further documentation
|
||||
//! of the methods see Rotation class.
|
||||
class Rotation2 {
|
||||
double s, c;
|
||||
//! c,s represent cos(angle), sin(angle), this also represents first col. of rot matrix
|
||||
//! from outside, this class behaves as if it would store the complete 2x2 matrix.
|
||||
public:
|
||||
//! Default constructor does NOT initialise to Zero().
|
||||
Rotation2()
|
||||
{
|
||||
c = 1.0;
|
||||
s = 0.0;
|
||||
}
|
||||
class Rotation2
|
||||
{
|
||||
double s,c;
|
||||
//! c,s represent cos(angle), sin(angle), this also represents first col. of rot matrix
|
||||
//! from outside, this class behaves as if it would store the complete 2x2 matrix.
|
||||
public:
|
||||
//! Default constructor does NOT initialise to Zero().
|
||||
Rotation2() {c=1.0;s=0.0;}
|
||||
|
||||
explicit Rotation2(double angle_rad) : s(sin(angle_rad)), c(cos(angle_rad)) {}
|
||||
explicit Rotation2(double angle_rad):s(sin(angle_rad)),c(cos(angle_rad)) {}
|
||||
|
||||
Rotation2(double ca, double sa) : s(sa), c(ca) {}
|
||||
Rotation2(double ca,double sa):s(sa),c(ca){}
|
||||
|
||||
inline Rotation2 &operator=(const Rotation2 &arg);
|
||||
inline Vector2 operator*(const Vector2 &v) const;
|
||||
//! Access to elements 0..1,0..1, bounds are checked when NDEBUG is not set
|
||||
inline double operator()(int i, int j) const;
|
||||
inline Rotation2& operator=(const Rotation2& arg);
|
||||
inline Vector2 operator*(const Vector2& v) const;
|
||||
//! Access to elements 0..1,0..1, bounds are checked when NDEBUG is not set
|
||||
inline double operator() (int i,int j) const;
|
||||
|
||||
inline friend Rotation2 operator*(const Rotation2 &lhs, const Rotation2 &rhs);
|
||||
inline friend Rotation2 operator *(const Rotation2& lhs,const Rotation2& rhs);
|
||||
|
||||
inline void SetInverse();
|
||||
inline Rotation2 Inverse() const;
|
||||
inline Vector2 Inverse(const Vector2 &v) const;
|
||||
inline void SetInverse();
|
||||
inline Rotation2 Inverse() const;
|
||||
inline Vector2 Inverse(const Vector2& v) const;
|
||||
|
||||
inline void SetIdentity();
|
||||
inline static Rotation2 Identity();
|
||||
inline void SetIdentity();
|
||||
inline static Rotation2 Identity();
|
||||
|
||||
//! The SetRot.. functions set the value of *this to the appropriate rotation matrix.
|
||||
inline void SetRot(double angle);
|
||||
|
||||
//! The Rot... static functions give the value of the appropriate rotation matrix bac
|
||||
inline static Rotation2 Rot(double angle);
|
||||
//! The SetRot.. functions set the value of *this to the appropriate rotation matrix.
|
||||
inline void SetRot(double angle);
|
||||
|
||||
//! Gets the angle (in radians)
|
||||
inline double GetRot() const;
|
||||
//! The Rot... static functions give the value of the appropriate rotation matrix bac
|
||||
inline static Rotation2 Rot(double angle);
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Rotation2 &a, const Rotation2 &b, double eps);
|
||||
//! Gets the angle (in radians)
|
||||
inline double GetRot() const;
|
||||
|
||||
//! do not use operator == because the definition of Equal(.,.) is slightly
|
||||
//! different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
inline friend bool Equal(const Rotation2& a,const Rotation2& b,double eps);
|
||||
};
|
||||
|
||||
//! A 2D frame class, for further documentation see the Frames class
|
||||
//! for methods with unchanged semantics.
|
||||
class Frame2 {
|
||||
public:
|
||||
Vector2 p; //!< origine of the Frame
|
||||
Rotation2 M; //!< Orientation of the Frame
|
||||
class Frame2
|
||||
{
|
||||
public:
|
||||
Vector2 p; //!< origine of the Frame
|
||||
Rotation2 M; //!< Orientation of the Frame
|
||||
|
||||
public:
|
||||
inline Frame2(const Rotation2 &R, const Vector2 &V);
|
||||
explicit inline Frame2(const Vector2 &V);
|
||||
explicit inline Frame2(const Rotation2 &R);
|
||||
inline Frame2(void);
|
||||
inline Frame2(const Frame2 &arg);
|
||||
inline void Make4x4(double *d);
|
||||
public:
|
||||
|
||||
//! Treats a frame as a 3x3 matrix and returns element i,j
|
||||
//! Access to elements 0..2,0..2, bounds are checked when NDEBUG is not set
|
||||
inline double operator()(int i, int j);
|
||||
inline Frame2(const Rotation2& R,const Vector2& V);
|
||||
explicit inline Frame2(const Vector2& V);
|
||||
explicit inline Frame2(const Rotation2& R);
|
||||
inline Frame2(void);
|
||||
inline Frame2(const Frame2& arg);
|
||||
inline void Make4x4(double* d);
|
||||
|
||||
//! Treats a frame as a 4x4 matrix and returns element i,j
|
||||
//! Access to elements 0..3,0..3, bounds are checked when NDEBUG is not set
|
||||
inline double operator()(int i, int j) const;
|
||||
//! Treats a frame as a 3x3 matrix and returns element i,j
|
||||
//! Access to elements 0..2,0..2, bounds are checked when NDEBUG is not set
|
||||
inline double operator()(int i,int j);
|
||||
|
||||
inline void SetInverse();
|
||||
inline Frame2 Inverse() const;
|
||||
inline Vector2 Inverse(const Vector2 &arg) const;
|
||||
inline Frame2 &operator=(const Frame2 &arg);
|
||||
inline Vector2 operator*(const Vector2 &arg);
|
||||
inline friend Frame2 operator*(const Frame2 &lhs, const Frame2 &rhs);
|
||||
inline void SetIdentity();
|
||||
inline void Integrate(const Twist &t_this, double frequency);
|
||||
inline static Frame2 Identity()
|
||||
{
|
||||
Frame2 tmp;
|
||||
tmp.SetIdentity();
|
||||
return tmp;
|
||||
}
|
||||
inline friend bool Equal(const Frame2 &a, const Frame2 &b, double eps);
|
||||
//! Treats a frame as a 4x4 matrix and returns element i,j
|
||||
//! Access to elements 0..3,0..3, bounds are checked when NDEBUG is not set
|
||||
inline double operator() (int i,int j) const;
|
||||
|
||||
inline void SetInverse();
|
||||
inline Frame2 Inverse() const;
|
||||
inline Vector2 Inverse(const Vector2& arg) const;
|
||||
inline Frame2& operator = (const Frame2& arg);
|
||||
inline Vector2 operator * (const Vector2& arg);
|
||||
inline friend Frame2 operator *(const Frame2& lhs,const Frame2& rhs);
|
||||
inline void SetIdentity();
|
||||
inline void Integrate(const Twist& t_this,double frequency);
|
||||
inline static Frame2 Identity() {
|
||||
Frame2 tmp;
|
||||
tmp.SetIdentity();
|
||||
return tmp;
|
||||
}
|
||||
inline friend bool Equal(const Frame2& a,const Frame2& b,double eps);
|
||||
};
|
||||
|
||||
inline bool Equal(const Vector &, const Vector &, double = epsilon);
|
||||
bool Equal(const Rotation &, const Rotation &, double = epsilon);
|
||||
inline bool Equal(const Frame &, const Frame &, double = epsilon);
|
||||
inline bool Equal(const Twist &, const Twist &, double = epsilon);
|
||||
inline bool Equal(const Wrench &, const Wrench &, double = epsilon);
|
||||
inline bool Equal(const Vector2 &, const Vector2 &, double = epsilon);
|
||||
inline bool Equal(const Rotation2 &, const Rotation2 &, double = epsilon);
|
||||
inline bool Equal(const Frame2 &, const Frame2 &, double = epsilon);
|
||||
|
||||
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt = 1);
|
||||
IMETHOD Vector diff(const Rotation &R_a_b1, const Rotation &R_a_b2, double dt = 1);
|
||||
IMETHOD Twist diff(const Frame &F_a_b1, const Frame &F_a_b2, double dt = 1);
|
||||
IMETHOD Twist diff(const Twist &a, const Twist &b, double dt = 1);
|
||||
IMETHOD Wrench diff(const Wrench &W_a_p1, const Wrench &W_a_p2, double dt = 1);
|
||||
IMETHOD Vector addDelta(const Vector &a, const Vector &da, double dt = 1);
|
||||
IMETHOD Rotation addDelta(const Rotation &a, const Vector &da, double dt = 1);
|
||||
IMETHOD Frame addDelta(const Frame &a, const Twist &da, double dt = 1);
|
||||
IMETHOD Twist addDelta(const Twist &a, const Twist &da, double dt = 1);
|
||||
IMETHOD Wrench addDelta(const Wrench &a, const Wrench &da, double dt = 1);
|
||||
inline bool Equal(const Vector&, const Vector&, double = epsilon);
|
||||
bool Equal(const Rotation&, const Rotation&, double = epsilon);
|
||||
inline bool Equal(const Frame&, const Frame&, double = epsilon);
|
||||
inline bool Equal(const Twist&, const Twist&, double = epsilon);
|
||||
inline bool Equal(const Wrench&, const Wrench&, double = epsilon);
|
||||
inline bool Equal(const Vector2&, const Vector2&, double = epsilon);
|
||||
inline bool Equal(const Rotation2&, const Rotation2&, double = epsilon);
|
||||
inline bool Equal(const Frame2&, const Frame2&, double = epsilon);
|
||||
|
||||
IMETHOD Vector diff(const Vector& a,const Vector& b,double dt=1);
|
||||
IMETHOD Vector diff(const Rotation& R_a_b1,const Rotation& R_a_b2,double dt=1);
|
||||
IMETHOD Twist diff(const Frame& F_a_b1,const Frame& F_a_b2,double dt=1);
|
||||
IMETHOD Twist diff(const Twist& a,const Twist& b,double dt=1);
|
||||
IMETHOD Wrench diff(const Wrench& W_a_p1,const Wrench& W_a_p2,double dt=1);
|
||||
IMETHOD Vector addDelta(const Vector& a,const Vector&da,double dt=1);
|
||||
IMETHOD Rotation addDelta(const Rotation& a,const Vector&da,double dt=1);
|
||||
IMETHOD Frame addDelta(const Frame& a,const Twist& da,double dt=1);
|
||||
IMETHOD Twist addDelta(const Twist& a,const Twist&da,double dt=1);
|
||||
IMETHOD Wrench addDelta(const Wrench& a,const Wrench&da,double dt=1);
|
||||
#ifdef KDL_INLINE
|
||||
// #include "vector.inl"
|
||||
// #include "wrench.inl"
|
||||
// #include "rotation.inl"
|
||||
// #include "frame.inl"
|
||||
// #include "twist.inl"
|
||||
// #include "vector2.inl"
|
||||
// #include "rotation2.inl"
|
||||
// #include "frame2.inl"
|
||||
# include "frames.inl"
|
||||
//#include "rotation.inl"
|
||||
//#include "frame.inl"
|
||||
//#include "twist.inl"
|
||||
//#include "vector2.inl"
|
||||
//#include "rotation2.inl"
|
||||
//#include "frame2.inl"
|
||||
#include "frames.inl"
|
||||
#endif
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,290 +29,285 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "frames_io.hpp"
|
||||
#include "frames.hpp"
|
||||
#include "utilities/error.h"
|
||||
#include "utilities/error_stack.h"
|
||||
#include "frames.hpp"
|
||||
#include "frames_io.hpp"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <iostream>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace KDL {
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Vector &v)
|
||||
{
|
||||
os << "[" << std::setw(KDL_FRAME_WIDTH) << v(0) << "," << std::setw(KDL_FRAME_WIDTH) << v(1)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v(2) << "]";
|
||||
return os;
|
||||
|
||||
std::ostream& operator << (std::ostream& os,const Vector& v) {
|
||||
os << "[" << std::setw(KDL_FRAME_WIDTH) << v(0) << "," << std::setw(KDL_FRAME_WIDTH)<<v(1)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v(2) << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Twist &v)
|
||||
{
|
||||
os << "[" << std::setw(KDL_FRAME_WIDTH) << v.vel(0) << "," << std::setw(KDL_FRAME_WIDTH)
|
||||
<< v.vel(1) << "," << std::setw(KDL_FRAME_WIDTH) << v.vel(2) << ","
|
||||
<< std::setw(KDL_FRAME_WIDTH) << v.rot(0) << "," << std::setw(KDL_FRAME_WIDTH) << v.rot(1)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.rot(2) << "]";
|
||||
return os;
|
||||
std::ostream& operator << (std::ostream& os,const Twist& v) {
|
||||
os << "[" << std::setw(KDL_FRAME_WIDTH) << v.vel(0)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.vel(1)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.vel(2)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.rot(0)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.rot(1)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.rot(2)
|
||||
<< "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Wrench &v)
|
||||
{
|
||||
os << "[" << std::setw(KDL_FRAME_WIDTH) << v.force(0) << "," << std::setw(KDL_FRAME_WIDTH)
|
||||
<< v.force(1) << "," << std::setw(KDL_FRAME_WIDTH) << v.force(2) << ","
|
||||
<< std::setw(KDL_FRAME_WIDTH) << v.torque(0) << "," << std::setw(KDL_FRAME_WIDTH)
|
||||
<< v.torque(1) << "," << std::setw(KDL_FRAME_WIDTH) << v.torque(2) << "]";
|
||||
return os;
|
||||
std::ostream& operator << (std::ostream& os,const Wrench& v) {
|
||||
os << "[" << std::setw(KDL_FRAME_WIDTH) << v.force(0)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.force(1)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.force(2)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.torque(0)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.torque(1)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << v.torque(2)
|
||||
<< "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Rotation &R)
|
||||
{
|
||||
|
||||
std::ostream& operator << (std::ostream& os,const Rotation& R) {
|
||||
#ifdef KDL_ROTATION_PROPERTIES_RPY
|
||||
double r, p, y;
|
||||
R.GetRPY(r, p, y);
|
||||
os << "[RPY]" << endl;
|
||||
os << "[";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << r << ",";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << p << ",";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << y << "]";
|
||||
double r,p,y;
|
||||
R.GetRPY(r,p,y);
|
||||
os << "[RPY]"<<endl;
|
||||
os << "[";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << r << ",";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << p << ",";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << y << "]";
|
||||
#else
|
||||
# ifdef KDL_ROTATION_PROPERTIES_EULER
|
||||
double z, y, x;
|
||||
R.GetEulerZYX(z, y, x);
|
||||
os << "[EULERZYX]" << endl;
|
||||
os << "[";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << z << ",";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << y << ",";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << x << "]";
|
||||
# else
|
||||
os << "[";
|
||||
for (int i = 0; i <= 2; i++) {
|
||||
os << std::setw(KDL_FRAME_WIDTH) << R(i, 0) << "," << std::setw(KDL_FRAME_WIDTH) << R(i, 1)
|
||||
<< "," << std::setw(KDL_FRAME_WIDTH) << R(i, 2);
|
||||
if (i < 2)
|
||||
os << ";" << std::endl << " ";
|
||||
else
|
||||
os << "]";
|
||||
}
|
||||
# endif
|
||||
# ifdef KDL_ROTATION_PROPERTIES_EULER
|
||||
double z,y,x;
|
||||
R.GetEulerZYX(z,y,x);
|
||||
os << "[EULERZYX]"<<endl;
|
||||
os << "[";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << z << ",";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << y << ",";
|
||||
os << std::setw(KDL_FRAME_WIDTH) << x << "]";
|
||||
# else
|
||||
os << "[";
|
||||
for (int i=0;i<=2;i++) {
|
||||
os << std::setw(KDL_FRAME_WIDTH) << R(i,0) << "," <<
|
||||
std::setw(KDL_FRAME_WIDTH) << R(i,1) << "," <<
|
||||
std::setw(KDL_FRAME_WIDTH) << R(i,2);
|
||||
if (i<2)
|
||||
os << ";"<< std::endl << " ";
|
||||
else
|
||||
os << "]";
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
return os;
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Frame &T)
|
||||
std::ostream& operator << (std::ostream& os, const Frame& T)
|
||||
{
|
||||
os << "[" << T.M << std::endl << T.p << "]";
|
||||
return os;
|
||||
os << "[" << T.M << std::endl<< T.p << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Vector2 &v)
|
||||
{
|
||||
os << "[" << std::setw(KDL_FRAME_WIDTH) << v(0) << "," << std::setw(KDL_FRAME_WIDTH) << v(1)
|
||||
<< "]";
|
||||
return os;
|
||||
std::ostream& operator << (std::ostream& os,const Vector2& v) {
|
||||
os << "[" << std::setw(KDL_FRAME_WIDTH) << v(0) << "," << std::setw(KDL_FRAME_WIDTH)<<v(1)
|
||||
<< "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
// Rotation2 gives back an angle in degrees with the << and >> operators.
|
||||
std::ostream &operator<<(std::ostream &os, const Rotation2 &R)
|
||||
{
|
||||
os << "[" << R.GetRot() * rad2deg << "]";
|
||||
return os;
|
||||
std::ostream& operator << (std::ostream& os,const Rotation2& R) {
|
||||
os << "[" << R.GetRot()*rad2deg << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Frame2 &T)
|
||||
std::ostream& operator << (std::ostream& os, const Frame2& T)
|
||||
{
|
||||
os << T.M << T.p;
|
||||
return os;
|
||||
os << T.M << T.p;
|
||||
return os;
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Vector &v)
|
||||
{
|
||||
IOTrace("Stream input Vector (vector or ZERO)");
|
||||
char storage[10];
|
||||
EatWord(is, "[]", storage, 10);
|
||||
if (storage[0] == '\0') {
|
||||
Eat(is, '[');
|
||||
is >> v(0);
|
||||
Eat(is, ',');
|
||||
is >> v(1);
|
||||
Eat(is, ',');
|
||||
is >> v(2);
|
||||
EatEnd(is, ']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage, "ZERO") == 0) {
|
||||
v = Vector::Zero();
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
throw Error_Frame_Vector_Unexpected_id();
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Twist &v)
|
||||
{
|
||||
IOTrace("Stream input Twist");
|
||||
Eat(is, '[');
|
||||
is >> v.vel(0);
|
||||
Eat(is, ',');
|
||||
is >> v.vel(1);
|
||||
Eat(is, ',');
|
||||
is >> v.vel(2);
|
||||
Eat(is, ',');
|
||||
is >> v.rot(0);
|
||||
Eat(is, ',');
|
||||
is >> v.rot(1);
|
||||
Eat(is, ',');
|
||||
is >> v.rot(2);
|
||||
EatEnd(is, ']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Wrench &v)
|
||||
{
|
||||
IOTrace("Stream input Wrench");
|
||||
Eat(is, '[');
|
||||
is >> v.force(0);
|
||||
Eat(is, ',');
|
||||
is >> v.force(1);
|
||||
Eat(is, ',');
|
||||
is >> v.force(2);
|
||||
Eat(is, ',');
|
||||
is >> v.torque(0);
|
||||
Eat(is, ',');
|
||||
is >> v.torque(1);
|
||||
Eat(is, ',');
|
||||
is >> v.torque(2);
|
||||
EatEnd(is, ']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Rotation &r)
|
||||
{
|
||||
IOTrace("Stream input Rotation (Matrix or EULERZYX, EULERZYZ,RPY, ROT, IDENTITY)");
|
||||
char storage[10];
|
||||
EatWord(is, "[]", storage, 10);
|
||||
if (storage[0] == '\0') {
|
||||
Eat(is, '[');
|
||||
for (int i = 0; i < 3; i++) {
|
||||
is >> r(i, 0);
|
||||
Eat(is, ',');
|
||||
is >> r(i, 1);
|
||||
Eat(is, ',');
|
||||
is >> r(i, 2);
|
||||
if (i < 2)
|
||||
Eat(is, ';');
|
||||
else
|
||||
EatEnd(is, ']');
|
||||
std::istream& operator >> (std::istream& is,Vector& v)
|
||||
{ IOTrace("Stream input Vector (vector or ZERO)");
|
||||
char storage[10];
|
||||
EatWord(is,"[]",storage,10);
|
||||
if (storage[0]=='\0') {
|
||||
Eat(is,'[');
|
||||
is >> v(0);
|
||||
Eat(is,',');
|
||||
is >> v(1);
|
||||
Eat(is,',');
|
||||
is >> v(2);
|
||||
EatEnd(is,']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
Vector v;
|
||||
if (strcmp(storage, "EULERZYX") == 0) {
|
||||
is >> v;
|
||||
v = v * deg2rad;
|
||||
r = Rotation::EulerZYX(v(0), v(1), v(2));
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage, "EULERZYZ") == 0) {
|
||||
is >> v;
|
||||
v = v * deg2rad;
|
||||
r = Rotation::EulerZYZ(v(0), v(1), v(2));
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage, "RPY") == 0) {
|
||||
is >> v;
|
||||
v = v * deg2rad;
|
||||
r = Rotation::RPY(v(0), v(1), v(2));
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage, "ROT") == 0) {
|
||||
is >> v;
|
||||
double angle;
|
||||
Eat(is, '[');
|
||||
is >> angle;
|
||||
EatEnd(is, ']');
|
||||
r = Rotation::Rot(v, angle * deg2rad);
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage, "IDENTITY") == 0) {
|
||||
r = Rotation::Identity();
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
throw Error_Frame_Rotation_Unexpected_id();
|
||||
return is;
|
||||
if (strcmp(storage,"ZERO")==0) {
|
||||
v = Vector::Zero();
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
throw Error_Frame_Vector_Unexpected_id();
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Frame &T)
|
||||
{
|
||||
IOTrace("Stream input Frame (Rotation,Vector) or DH[...]");
|
||||
char storage[10];
|
||||
EatWord(is, "[", storage, 10);
|
||||
if (storage[0] == '\0') {
|
||||
Eat(is, '[');
|
||||
std::istream& operator >> (std::istream& is,Twist& v)
|
||||
{ IOTrace("Stream input Twist");
|
||||
Eat(is,'[');
|
||||
is >> v.vel(0);
|
||||
Eat(is,',');
|
||||
is >> v.vel(1);
|
||||
Eat(is,',');
|
||||
is >> v.vel(2);
|
||||
Eat(is,',');
|
||||
is >> v.rot(0);
|
||||
Eat(is,',');
|
||||
is >> v.rot(1);
|
||||
Eat(is,',');
|
||||
is >> v.rot(2);
|
||||
EatEnd(is,']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istream& operator >> (std::istream& is,Wrench& v)
|
||||
{ IOTrace("Stream input Wrench");
|
||||
Eat(is,'[');
|
||||
is >> v.force(0);
|
||||
Eat(is,',');
|
||||
is >> v.force(1);
|
||||
Eat(is,',');
|
||||
is >> v.force(2);
|
||||
Eat(is,',');
|
||||
is >> v.torque(0);
|
||||
Eat(is,',');
|
||||
is >> v.torque(1);
|
||||
Eat(is,',');
|
||||
is >> v.torque(2);
|
||||
EatEnd(is,']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istream& operator >> (std::istream& is,Rotation& r)
|
||||
{ IOTrace("Stream input Rotation (Matrix or EULERZYX, EULERZYZ,RPY, ROT, IDENTITY)");
|
||||
char storage[10];
|
||||
EatWord(is,"[]",storage,10);
|
||||
if (storage[0]=='\0') {
|
||||
Eat(is,'[');
|
||||
for (int i=0;i<3;i++) {
|
||||
is >> r(i,0);
|
||||
Eat(is,',') ;
|
||||
is >> r(i,1);
|
||||
Eat(is,',');
|
||||
is >> r(i,2);
|
||||
if (i<2)
|
||||
Eat(is,';');
|
||||
else
|
||||
EatEnd(is,']');
|
||||
}
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
Vector v;
|
||||
if (strcmp(storage,"EULERZYX")==0) {
|
||||
is >> v;
|
||||
v=v*deg2rad;
|
||||
r = Rotation::EulerZYX(v(0),v(1),v(2));
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage,"EULERZYZ")==0) {
|
||||
is >> v;
|
||||
v=v*deg2rad;
|
||||
r = Rotation::EulerZYZ(v(0),v(1),v(2));
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage,"RPY")==0) {
|
||||
is >> v;
|
||||
v=v*deg2rad;
|
||||
r = Rotation::RPY(v(0),v(1),v(2));
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage,"ROT")==0) {
|
||||
is >> v;
|
||||
double angle;
|
||||
Eat(is,'[');
|
||||
is >> angle;
|
||||
EatEnd(is,']');
|
||||
r = Rotation::Rot(v,angle*deg2rad);
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage,"IDENTITY")==0) {
|
||||
r = Rotation::Identity();
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
throw Error_Frame_Rotation_Unexpected_id();
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istream& operator >> (std::istream& is,Frame& T)
|
||||
{ IOTrace("Stream input Frame (Rotation,Vector) or DH[...]");
|
||||
char storage[10];
|
||||
EatWord(is,"[",storage,10);
|
||||
if (storage[0]=='\0') {
|
||||
Eat(is,'[');
|
||||
is >> T.M;
|
||||
is >> T.p;
|
||||
EatEnd(is,']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage,"DH")==0) {
|
||||
double a,alpha,d,theta;
|
||||
Eat(is,'[');
|
||||
is >> a;
|
||||
Eat(is,',');
|
||||
is >> alpha;
|
||||
Eat(is,',');
|
||||
is >> d;
|
||||
Eat(is,',');
|
||||
is >> theta;
|
||||
EatEnd(is,']');
|
||||
T = Frame::DH(a,alpha*deg2rad,d,theta*deg2rad);
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
throw Error_Frame_Frame_Unexpected_id();
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istream& operator >> (std::istream& is,Vector2& v)
|
||||
{ IOTrace("Stream input Vector2");
|
||||
Eat(is,'[');
|
||||
is >> v(0);
|
||||
Eat(is,',');
|
||||
is >> v(1);
|
||||
EatEnd(is,']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
std::istream& operator >> (std::istream& is,Rotation2& r)
|
||||
{ IOTrace("Stream input Rotation2");
|
||||
Eat(is,'[');
|
||||
double val;
|
||||
is >> val;
|
||||
r.Rot(val*deg2rad);
|
||||
EatEnd(is,']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
std::istream& operator >> (std::istream& is,Frame2& T)
|
||||
{ IOTrace("Stream input Frame2");
|
||||
is >> T.M;
|
||||
is >> T.p;
|
||||
EatEnd(is, ']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
if (strcmp(storage, "DH") == 0) {
|
||||
double a, alpha, d, theta;
|
||||
Eat(is, '[');
|
||||
is >> a;
|
||||
Eat(is, ',');
|
||||
is >> alpha;
|
||||
Eat(is, ',');
|
||||
is >> d;
|
||||
Eat(is, ',');
|
||||
is >> theta;
|
||||
EatEnd(is, ']');
|
||||
T = Frame::DH(a, alpha * deg2rad, d, theta * deg2rad);
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
throw Error_Frame_Frame_Unexpected_id();
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Vector2 &v)
|
||||
{
|
||||
IOTrace("Stream input Vector2");
|
||||
Eat(is, '[');
|
||||
is >> v(0);
|
||||
Eat(is, ',');
|
||||
is >> v(1);
|
||||
EatEnd(is, ']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
std::istream &operator>>(std::istream &is, Rotation2 &r)
|
||||
{
|
||||
IOTrace("Stream input Rotation2");
|
||||
Eat(is, '[');
|
||||
double val;
|
||||
is >> val;
|
||||
r.Rot(val * deg2rad);
|
||||
EatEnd(is, ']');
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
std::istream &operator>>(std::istream &is, Frame2 &T)
|
||||
{
|
||||
IOTrace("Stream input Frame2");
|
||||
is >> T.M;
|
||||
is >> T.p;
|
||||
IOTracePop();
|
||||
return is;
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
} // namespace Frame
|
||||
|
||||
@@ -76,35 +76,39 @@
|
||||
#ifndef FRAMES_IO_H
|
||||
#define FRAMES_IO_H
|
||||
|
||||
#include "frames.hpp"
|
||||
#include "jacobian.hpp"
|
||||
#include "jntarray.hpp"
|
||||
#include "utilities/utility_io.h"
|
||||
#include "frames.hpp"
|
||||
#include "jntarray.hpp"
|
||||
#include "jacobian.hpp"
|
||||
|
||||
namespace KDL {
|
||||
|
||||
//! width to be used when printing variables out with frames_io.h
|
||||
//! global variable, can be changed.
|
||||
//! width to be used when printing variables out with frames_io.h
|
||||
//! global variable, can be changed.
|
||||
|
||||
// I/O to C++ stream.
|
||||
std::ostream &operator<<(std::ostream &os, const Vector &v);
|
||||
std::ostream &operator<<(std::ostream &os, const Rotation &R);
|
||||
std::ostream &operator<<(std::ostream &os, const Frame &T);
|
||||
std::ostream &operator<<(std::ostream &os, const Twist &T);
|
||||
std::ostream &operator<<(std::ostream &os, const Wrench &T);
|
||||
std::ostream &operator<<(std::ostream &os, const Vector2 &v);
|
||||
std::ostream &operator<<(std::ostream &os, const Rotation2 &R);
|
||||
std::ostream &operator<<(std::ostream &os, const Frame2 &T);
|
||||
|
||||
std::istream &operator>>(std::istream &is, Vector &v);
|
||||
std::istream &operator>>(std::istream &is, Rotation &R);
|
||||
std::istream &operator>>(std::istream &is, Frame &T);
|
||||
std::istream &operator>>(std::istream &os, Twist &T);
|
||||
std::istream &operator>>(std::istream &os, Wrench &T);
|
||||
std::istream &operator>>(std::istream &is, Vector2 &v);
|
||||
std::istream &operator>>(std::istream &is, Rotation2 &R);
|
||||
std::istream &operator>>(std::istream &is, Frame2 &T);
|
||||
// I/O to C++ stream.
|
||||
std::ostream& operator << (std::ostream& os,const Vector& v);
|
||||
std::ostream& operator << (std::ostream& os,const Rotation& R);
|
||||
std::ostream& operator << (std::ostream& os,const Frame& T);
|
||||
std::ostream& operator << (std::ostream& os,const Twist& T);
|
||||
std::ostream& operator << (std::ostream& os,const Wrench& T);
|
||||
std::ostream& operator << (std::ostream& os,const Vector2& v);
|
||||
std::ostream& operator << (std::ostream& os,const Rotation2& R);
|
||||
std::ostream& operator << (std::ostream& os,const Frame2& T);
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
|
||||
std::istream& operator >> (std::istream& is,Vector& v);
|
||||
std::istream& operator >> (std::istream& is,Rotation& R);
|
||||
std::istream& operator >> (std::istream& is,Frame& T);
|
||||
std::istream& operator >> (std::istream& os,Twist& T);
|
||||
std::istream& operator >> (std::istream& os,Wrench& T);
|
||||
std::istream& operator >> (std::istream& is,Vector2& v);
|
||||
std::istream& operator >> (std::istream& is,Rotation2& R);
|
||||
std::istream& operator >> (std::istream& is,Frame2& T);
|
||||
|
||||
|
||||
} // namespace Frame
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,12 +14,15 @@
|
||||
* $Name: $
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "framevel.hpp"
|
||||
|
||||
namespace KDL {
|
||||
|
||||
#ifndef KDL_INLINE
|
||||
# include "framevel.inl"
|
||||
#include "framevel.inl"
|
||||
#endif
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -3,9 +3,10 @@
|
||||
* This file contains the definition of classes for a
|
||||
* Rall Algebra of (subset of) the classes defined in frames,
|
||||
* i.e. classes that contain a pair (value,derivative) and define operations on that pair
|
||||
* this classes are usefull for automatic differentiation ( <-> symbolic diff , <-> numeric
|
||||
*diff) Defines VectorVel, RotationVel, FrameVel. Look at Frames.h for details on how to work with
|
||||
*Frame objects. Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
* this classes are usefull for automatic differentiation ( <-> symbolic diff , <-> numeric diff)
|
||||
* Defines VectorVel, RotationVel, FrameVel. Look at Frames.h for details on how to work
|
||||
* with Frame objects.
|
||||
* Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
*
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
@@ -20,42 +21,41 @@
|
||||
#ifndef KDL_FRAMEVEL_H
|
||||
#define KDL_FRAMEVEL_H
|
||||
|
||||
#include "utilities/utility.h"
|
||||
#include "utilities/rall1d.h"
|
||||
#include "utilities/traits.h"
|
||||
#include "utilities/utility.h"
|
||||
|
||||
#include "frames.hpp"
|
||||
|
||||
|
||||
|
||||
namespace KDL {
|
||||
|
||||
typedef Rall1d<double> doubleVel;
|
||||
|
||||
IMETHOD doubleVel diff(const doubleVel &a, const doubleVel &b, double dt = 1.0)
|
||||
{
|
||||
return doubleVel((b.t - a.t) / dt, (b.grad - a.grad) / dt);
|
||||
IMETHOD doubleVel diff(const doubleVel& a,const doubleVel& b,double dt=1.0) {
|
||||
return doubleVel((b.t-a.t)/dt,(b.grad-a.grad)/dt);
|
||||
}
|
||||
|
||||
IMETHOD doubleVel addDelta(const doubleVel &a, const doubleVel &da, double dt = 1.0)
|
||||
{
|
||||
return doubleVel(a.t + da.t * dt, a.grad + da.grad * dt);
|
||||
IMETHOD doubleVel addDelta(const doubleVel& a,const doubleVel&da,double dt=1.0) {
|
||||
return doubleVel(a.t+da.t*dt,a.grad+da.grad*dt);
|
||||
}
|
||||
|
||||
IMETHOD void random(doubleVel &F)
|
||||
{
|
||||
random(F.t);
|
||||
random(F.grad);
|
||||
IMETHOD void random(doubleVel& F) {
|
||||
random(F.t);
|
||||
random(F.grad);
|
||||
}
|
||||
IMETHOD void posrandom(doubleVel &F)
|
||||
{
|
||||
posrandom(F.t);
|
||||
posrandom(F.grad);
|
||||
IMETHOD void posrandom(doubleVel& F) {
|
||||
posrandom(F.t);
|
||||
posrandom(F.grad);
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
}
|
||||
|
||||
template<> struct Traits<KDL::doubleVel> {
|
||||
typedef double valueType;
|
||||
typedef KDL::doubleVel derivType;
|
||||
template <>
|
||||
struct Traits<KDL::doubleVel> {
|
||||
typedef double valueType;
|
||||
typedef KDL::doubleVel derivType;
|
||||
};
|
||||
|
||||
namespace KDL {
|
||||
@@ -71,117 +71,113 @@ class VectorVel
|
||||
// = CLASS TYPE
|
||||
// Concrete
|
||||
{
|
||||
public:
|
||||
Vector p; // position vector
|
||||
Vector v; // velocity vector
|
||||
public:
|
||||
VectorVel() : p(), v() {}
|
||||
VectorVel(const Vector &_p, const Vector &_v) : p(_p), v(_v) {}
|
||||
explicit VectorVel(const Vector &_p) : p(_p), v(Vector::Zero()) {}
|
||||
public:
|
||||
Vector p; // position vector
|
||||
Vector v; // velocity vector
|
||||
public:
|
||||
VectorVel():p(),v(){}
|
||||
VectorVel(const Vector& _p,const Vector& _v):p(_p),v(_v) {}
|
||||
explicit VectorVel(const Vector& _p):p(_p),v(Vector::Zero()) {}
|
||||
|
||||
Vector value() const
|
||||
{
|
||||
return p;
|
||||
}
|
||||
Vector deriv() const
|
||||
{
|
||||
return v;
|
||||
}
|
||||
Vector value() const { return p;}
|
||||
Vector deriv() const { return v;}
|
||||
|
||||
IMETHOD VectorVel &operator=(const VectorVel &arg);
|
||||
IMETHOD VectorVel &operator=(const Vector &arg);
|
||||
IMETHOD VectorVel &operator+=(const VectorVel &arg);
|
||||
IMETHOD VectorVel &operator-=(const VectorVel &arg);
|
||||
IMETHOD static VectorVel Zero();
|
||||
IMETHOD void ReverseSign();
|
||||
IMETHOD doubleVel Norm() const;
|
||||
IMETHOD friend VectorVel operator+(const VectorVel &r1, const VectorVel &r2);
|
||||
IMETHOD friend VectorVel operator-(const VectorVel &r1, const VectorVel &r2);
|
||||
IMETHOD friend VectorVel operator+(const Vector &r1, const VectorVel &r2);
|
||||
IMETHOD friend VectorVel operator-(const Vector &r1, const VectorVel &r2);
|
||||
IMETHOD friend VectorVel operator+(const VectorVel &r1, const Vector &r2);
|
||||
IMETHOD friend VectorVel operator-(const VectorVel &r1, const Vector &r2);
|
||||
IMETHOD friend VectorVel operator*(const VectorVel &r1, const VectorVel &r2);
|
||||
IMETHOD friend VectorVel operator*(const VectorVel &r1, const Vector &r2);
|
||||
IMETHOD friend VectorVel operator*(const Vector &r1, const VectorVel &r2);
|
||||
IMETHOD friend VectorVel operator*(const VectorVel &r1, double r2);
|
||||
IMETHOD friend VectorVel operator*(double r1, const VectorVel &r2);
|
||||
IMETHOD friend VectorVel operator*(const doubleVel &r1, const VectorVel &r2);
|
||||
IMETHOD friend VectorVel operator*(const VectorVel &r2, const doubleVel &r1);
|
||||
IMETHOD friend VectorVel operator*(const Rotation &R, const VectorVel &x);
|
||||
IMETHOD VectorVel& operator = (const VectorVel& arg);
|
||||
IMETHOD VectorVel& operator = (const Vector& arg);
|
||||
IMETHOD VectorVel& operator += (const VectorVel& arg);
|
||||
IMETHOD VectorVel& operator -= (const VectorVel& arg);
|
||||
IMETHOD static VectorVel Zero();
|
||||
IMETHOD void ReverseSign();
|
||||
IMETHOD doubleVel Norm() const;
|
||||
IMETHOD friend VectorVel operator + (const VectorVel& r1,const VectorVel& r2);
|
||||
IMETHOD friend VectorVel operator - (const VectorVel& r1,const VectorVel& r2);
|
||||
IMETHOD friend VectorVel operator + (const Vector& r1,const VectorVel& r2);
|
||||
IMETHOD friend VectorVel operator - (const Vector& r1,const VectorVel& r2);
|
||||
IMETHOD friend VectorVel operator + (const VectorVel& r1,const Vector& r2);
|
||||
IMETHOD friend VectorVel operator - (const VectorVel& r1,const Vector& r2);
|
||||
IMETHOD friend VectorVel operator * (const VectorVel& r1,const VectorVel& r2);
|
||||
IMETHOD friend VectorVel operator * (const VectorVel& r1,const Vector& r2);
|
||||
IMETHOD friend VectorVel operator * (const Vector& r1,const VectorVel& r2);
|
||||
IMETHOD friend VectorVel operator * (const VectorVel& r1,double r2);
|
||||
IMETHOD friend VectorVel operator * (double r1,const VectorVel& r2);
|
||||
IMETHOD friend VectorVel operator * (const doubleVel& r1,const VectorVel& r2);
|
||||
IMETHOD friend VectorVel operator * (const VectorVel& r2,const doubleVel& r1);
|
||||
IMETHOD friend VectorVel operator*(const Rotation& R,const VectorVel& x);
|
||||
|
||||
IMETHOD friend VectorVel operator/(const VectorVel &r1, double r2);
|
||||
IMETHOD friend VectorVel operator/(const VectorVel &r2, const doubleVel &r1);
|
||||
IMETHOD friend void SetToZero(VectorVel &v);
|
||||
IMETHOD friend VectorVel operator / (const VectorVel& r1,double r2);
|
||||
IMETHOD friend VectorVel operator / (const VectorVel& r2,const doubleVel& r1);
|
||||
IMETHOD friend void SetToZero(VectorVel& v);
|
||||
|
||||
IMETHOD friend bool Equal(const VectorVel &r1, const VectorVel &r2, double eps);
|
||||
IMETHOD friend bool Equal(const Vector &r1, const VectorVel &r2, double eps);
|
||||
IMETHOD friend bool Equal(const VectorVel &r1, const Vector &r2, double eps);
|
||||
IMETHOD friend VectorVel operator-(const VectorVel &r);
|
||||
IMETHOD friend doubleVel dot(const VectorVel &lhs, const VectorVel &rhs);
|
||||
IMETHOD friend doubleVel dot(const VectorVel &lhs, const Vector &rhs);
|
||||
IMETHOD friend doubleVel dot(const Vector &lhs, const VectorVel &rhs);
|
||||
|
||||
IMETHOD friend bool Equal(const VectorVel& r1,const VectorVel& r2,double eps);
|
||||
IMETHOD friend bool Equal(const Vector& r1,const VectorVel& r2,double eps);
|
||||
IMETHOD friend bool Equal(const VectorVel& r1,const Vector& r2,double eps);
|
||||
IMETHOD friend VectorVel operator - (const VectorVel& r);
|
||||
IMETHOD friend doubleVel dot(const VectorVel& lhs,const VectorVel& rhs);
|
||||
IMETHOD friend doubleVel dot(const VectorVel& lhs,const Vector& rhs);
|
||||
IMETHOD friend doubleVel dot(const Vector& lhs,const VectorVel& rhs);
|
||||
};
|
||||
|
||||
|
||||
|
||||
class RotationVel
|
||||
// = TITLE
|
||||
// An RotationVel is a Rotation and its first derivative, a rotation vector
|
||||
// = CLASS TYPE
|
||||
// Concrete
|
||||
{
|
||||
public:
|
||||
Rotation R; // Rotation matrix
|
||||
Vector w; // rotation vector
|
||||
public:
|
||||
RotationVel() : R(), w() {}
|
||||
explicit RotationVel(const Rotation &R_) : R(R_), w(Vector::Zero()) {}
|
||||
RotationVel(const Rotation &R_, const Vector &_w) : R(R_), w(_w) {}
|
||||
public:
|
||||
Rotation R; // Rotation matrix
|
||||
Vector w; // rotation vector
|
||||
public:
|
||||
RotationVel():R(),w() {}
|
||||
explicit RotationVel(const Rotation& R_):R(R_),w(Vector::Zero()){}
|
||||
RotationVel(const Rotation& R_,const Vector& _w):R(R_),w(_w){}
|
||||
|
||||
Rotation value() const
|
||||
{
|
||||
return R;
|
||||
}
|
||||
Vector deriv() const
|
||||
{
|
||||
return w;
|
||||
}
|
||||
|
||||
IMETHOD RotationVel &operator=(const RotationVel &arg);
|
||||
IMETHOD RotationVel &operator=(const Rotation &arg);
|
||||
IMETHOD VectorVel UnitX() const;
|
||||
IMETHOD VectorVel UnitY() const;
|
||||
IMETHOD VectorVel UnitZ() const;
|
||||
IMETHOD static RotationVel Identity();
|
||||
IMETHOD RotationVel Inverse() const;
|
||||
IMETHOD VectorVel Inverse(const VectorVel &arg) const;
|
||||
IMETHOD VectorVel Inverse(const Vector &arg) const;
|
||||
IMETHOD VectorVel operator*(const VectorVel &arg) const;
|
||||
IMETHOD VectorVel operator*(const Vector &arg) const;
|
||||
IMETHOD void DoRotX(const doubleVel &angle);
|
||||
IMETHOD void DoRotY(const doubleVel &angle);
|
||||
IMETHOD void DoRotZ(const doubleVel &angle);
|
||||
IMETHOD static RotationVel RotX(const doubleVel &angle);
|
||||
IMETHOD static RotationVel RotY(const doubleVel &angle);
|
||||
IMETHOD static RotationVel RotZ(const doubleVel &angle);
|
||||
IMETHOD static RotationVel Rot(const Vector &rotvec, const doubleVel &angle);
|
||||
// rotvec has arbitrary norm
|
||||
// rotation around a constant vector !
|
||||
IMETHOD static RotationVel Rot2(const Vector &rotvec, const doubleVel &angle);
|
||||
// rotvec is normalized.
|
||||
// rotation around a constant vector !
|
||||
IMETHOD friend RotationVel operator*(const RotationVel &r1, const RotationVel &r2);
|
||||
IMETHOD friend RotationVel operator*(const Rotation &r1, const RotationVel &r2);
|
||||
IMETHOD friend RotationVel operator*(const RotationVel &r1, const Rotation &r2);
|
||||
IMETHOD friend bool Equal(const RotationVel &r1, const RotationVel &r2, double eps);
|
||||
IMETHOD friend bool Equal(const Rotation &r1, const RotationVel &r2, double eps);
|
||||
IMETHOD friend bool Equal(const RotationVel &r1, const Rotation &r2, double eps);
|
||||
Rotation value() const { return R;}
|
||||
Vector deriv() const { return w;}
|
||||
|
||||
IMETHOD TwistVel Inverse(const TwistVel &arg) const;
|
||||
IMETHOD TwistVel Inverse(const Twist &arg) const;
|
||||
IMETHOD TwistVel operator*(const TwistVel &arg) const;
|
||||
IMETHOD TwistVel operator*(const Twist &arg) const;
|
||||
|
||||
IMETHOD RotationVel& operator = (const RotationVel& arg);
|
||||
IMETHOD RotationVel& operator = (const Rotation& arg);
|
||||
IMETHOD VectorVel UnitX() const;
|
||||
IMETHOD VectorVel UnitY() const;
|
||||
IMETHOD VectorVel UnitZ() const;
|
||||
IMETHOD static RotationVel Identity();
|
||||
IMETHOD RotationVel Inverse() const;
|
||||
IMETHOD VectorVel Inverse(const VectorVel& arg) const;
|
||||
IMETHOD VectorVel Inverse(const Vector& arg) const;
|
||||
IMETHOD VectorVel operator*(const VectorVel& arg) const;
|
||||
IMETHOD VectorVel operator*(const Vector& arg) const;
|
||||
IMETHOD void DoRotX(const doubleVel& angle);
|
||||
IMETHOD void DoRotY(const doubleVel& angle);
|
||||
IMETHOD void DoRotZ(const doubleVel& angle);
|
||||
IMETHOD static RotationVel RotX(const doubleVel& angle);
|
||||
IMETHOD static RotationVel RotY(const doubleVel& angle);
|
||||
IMETHOD static RotationVel RotZ(const doubleVel& angle);
|
||||
IMETHOD static RotationVel Rot(const Vector& rotvec,const doubleVel& angle);
|
||||
// rotvec has arbitrary norm
|
||||
// rotation around a constant vector !
|
||||
IMETHOD static RotationVel Rot2(const Vector& rotvec,const doubleVel& angle);
|
||||
// rotvec is normalized.
|
||||
// rotation around a constant vector !
|
||||
IMETHOD friend RotationVel operator* (const RotationVel& r1,const RotationVel& r2);
|
||||
IMETHOD friend RotationVel operator* (const Rotation& r1,const RotationVel& r2);
|
||||
IMETHOD friend RotationVel operator* (const RotationVel& r1,const Rotation& r2);
|
||||
IMETHOD friend bool Equal(const RotationVel& r1,const RotationVel& r2,double eps);
|
||||
IMETHOD friend bool Equal(const Rotation& r1,const RotationVel& r2,double eps);
|
||||
IMETHOD friend bool Equal(const RotationVel& r1,const Rotation& r2,double eps);
|
||||
|
||||
IMETHOD TwistVel Inverse(const TwistVel& arg) const;
|
||||
IMETHOD TwistVel Inverse(const Twist& arg) const;
|
||||
IMETHOD TwistVel operator * (const TwistVel& arg) const;
|
||||
IMETHOD TwistVel operator * (const Twist& arg) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class FrameVel
|
||||
// = TITLE
|
||||
// An FrameVel is a Frame and its first derivative, a Twist vector
|
||||
@@ -190,213 +186,208 @@ class FrameVel
|
||||
// = CAVEATS
|
||||
//
|
||||
{
|
||||
public:
|
||||
RotationVel M;
|
||||
VectorVel p;
|
||||
public:
|
||||
RotationVel M;
|
||||
VectorVel p;
|
||||
public:
|
||||
FrameVel(){}
|
||||
|
||||
public:
|
||||
FrameVel() {}
|
||||
explicit FrameVel(const Frame& T_):
|
||||
M(T_.M),p(T_.p) {}
|
||||
|
||||
explicit FrameVel(const Frame &T_) : M(T_.M), p(T_.p) {}
|
||||
FrameVel(const Frame& T_,const Twist& _t):
|
||||
M(T_.M,_t.rot),p(T_.p,_t.vel) {}
|
||||
|
||||
FrameVel(const Frame &T_, const Twist &_t) : M(T_.M, _t.rot), p(T_.p, _t.vel) {}
|
||||
FrameVel(const RotationVel& _M,const VectorVel& _p):
|
||||
M(_M),p(_p) {}
|
||||
|
||||
FrameVel(const RotationVel &_M, const VectorVel &_p) : M(_M), p(_p) {}
|
||||
|
||||
Frame value() const
|
||||
{
|
||||
return Frame(M.value(), p.value());
|
||||
}
|
||||
Twist deriv() const
|
||||
{
|
||||
return Twist(p.deriv(), M.deriv());
|
||||
}
|
||||
Frame value() const { return Frame(M.value(),p.value());}
|
||||
Twist deriv() const { return Twist(p.deriv(),M.deriv());}
|
||||
|
||||
IMETHOD FrameVel &operator=(const Frame &arg);
|
||||
IMETHOD FrameVel &operator=(const FrameVel &arg);
|
||||
IMETHOD static FrameVel Identity();
|
||||
IMETHOD FrameVel Inverse() const;
|
||||
IMETHOD VectorVel Inverse(const VectorVel &arg) const;
|
||||
IMETHOD VectorVel operator*(const VectorVel &arg) const;
|
||||
IMETHOD VectorVel operator*(const Vector &arg) const;
|
||||
IMETHOD VectorVel Inverse(const Vector &arg) const;
|
||||
IMETHOD Frame GetFrame() const;
|
||||
IMETHOD Twist GetTwist() const;
|
||||
IMETHOD friend FrameVel operator*(const FrameVel &f1, const FrameVel &f2);
|
||||
IMETHOD friend FrameVel operator*(const Frame &f1, const FrameVel &f2);
|
||||
IMETHOD friend FrameVel operator*(const FrameVel &f1, const Frame &f2);
|
||||
IMETHOD friend bool Equal(const FrameVel &r1, const FrameVel &r2, double eps);
|
||||
IMETHOD friend bool Equal(const Frame &r1, const FrameVel &r2, double eps);
|
||||
IMETHOD friend bool Equal(const FrameVel &r1, const Frame &r2, double eps);
|
||||
|
||||
IMETHOD TwistVel Inverse(const TwistVel &arg) const;
|
||||
IMETHOD TwistVel Inverse(const Twist &arg) const;
|
||||
IMETHOD TwistVel operator*(const TwistVel &arg) const;
|
||||
IMETHOD TwistVel operator*(const Twist &arg) const;
|
||||
IMETHOD FrameVel& operator = (const Frame& arg);
|
||||
IMETHOD FrameVel& operator = (const FrameVel& arg);
|
||||
IMETHOD static FrameVel Identity();
|
||||
IMETHOD FrameVel Inverse() const;
|
||||
IMETHOD VectorVel Inverse(const VectorVel& arg) const;
|
||||
IMETHOD VectorVel operator*(const VectorVel& arg) const;
|
||||
IMETHOD VectorVel operator*(const Vector& arg) const;
|
||||
IMETHOD VectorVel Inverse(const Vector& arg) const;
|
||||
IMETHOD Frame GetFrame() const;
|
||||
IMETHOD Twist GetTwist() const;
|
||||
IMETHOD friend FrameVel operator * (const FrameVel& f1,const FrameVel& f2);
|
||||
IMETHOD friend FrameVel operator * (const Frame& f1,const FrameVel& f2);
|
||||
IMETHOD friend FrameVel operator * (const FrameVel& f1,const Frame& f2);
|
||||
IMETHOD friend bool Equal(const FrameVel& r1,const FrameVel& r2,double eps);
|
||||
IMETHOD friend bool Equal(const Frame& r1,const FrameVel& r2,double eps);
|
||||
IMETHOD friend bool Equal(const FrameVel& r1,const Frame& r2,double eps);
|
||||
|
||||
IMETHOD TwistVel Inverse(const TwistVel& arg) const;
|
||||
IMETHOD TwistVel Inverse(const Twist& arg) const;
|
||||
IMETHOD TwistVel operator * (const TwistVel& arg) const;
|
||||
IMETHOD TwistVel operator * (const Twist& arg) const;
|
||||
};
|
||||
|
||||
// very similar to Wrench class.
|
||||
|
||||
|
||||
|
||||
|
||||
//very similar to Wrench class.
|
||||
class TwistVel
|
||||
// = TITLE
|
||||
// This class represents a TwistVel. This is a velocity and rotational velocity together
|
||||
{
|
||||
public:
|
||||
VectorVel vel;
|
||||
VectorVel rot;
|
||||
public:
|
||||
VectorVel vel;
|
||||
VectorVel rot;
|
||||
public:
|
||||
|
||||
public:
|
||||
// = Constructors
|
||||
TwistVel() : vel(), rot(){};
|
||||
TwistVel(const VectorVel &_vel, const VectorVel &_rot) : vel(_vel), rot(_rot){};
|
||||
TwistVel(const Twist &p, const Twist &v) : vel(p.vel, v.vel), rot(p.rot, v.rot){};
|
||||
TwistVel(const Twist &p) : vel(p.vel), rot(p.rot){};
|
||||
// = Constructors
|
||||
TwistVel():vel(),rot() {};
|
||||
TwistVel(const VectorVel& _vel,const VectorVel& _rot):vel(_vel),rot(_rot) {};
|
||||
TwistVel(const Twist& p,const Twist& v):vel(p.vel, v.vel), rot( p.rot, v.rot) {};
|
||||
TwistVel(const Twist& p):vel(p.vel), rot( p.rot) {};
|
||||
|
||||
Twist value() const
|
||||
{
|
||||
return Twist(vel.value(), rot.value());
|
||||
}
|
||||
Twist deriv() const
|
||||
{
|
||||
return Twist(vel.deriv(), rot.deriv());
|
||||
}
|
||||
// = Operators
|
||||
IMETHOD TwistVel &operator-=(const TwistVel &arg);
|
||||
IMETHOD TwistVel &operator+=(const TwistVel &arg);
|
||||
Twist value() const {
|
||||
return Twist(vel.value(),rot.value());
|
||||
}
|
||||
Twist deriv() const {
|
||||
return Twist(vel.deriv(),rot.deriv());
|
||||
}
|
||||
// = Operators
|
||||
IMETHOD TwistVel& operator-=(const TwistVel& arg);
|
||||
IMETHOD TwistVel& operator+=(const TwistVel& arg);
|
||||
|
||||
// = External operators
|
||||
IMETHOD friend TwistVel operator*(const TwistVel &lhs, double rhs);
|
||||
IMETHOD friend TwistVel operator*(double lhs, const TwistVel &rhs);
|
||||
IMETHOD friend TwistVel operator/(const TwistVel &lhs, double rhs);
|
||||
// = External operators
|
||||
IMETHOD friend TwistVel operator*(const TwistVel& lhs,double rhs);
|
||||
IMETHOD friend TwistVel operator*(double lhs,const TwistVel& rhs);
|
||||
IMETHOD friend TwistVel operator/(const TwistVel& lhs,double rhs);
|
||||
|
||||
IMETHOD friend TwistVel operator*(const TwistVel &lhs, const doubleVel &rhs);
|
||||
IMETHOD friend TwistVel operator*(const doubleVel &lhs, const TwistVel &rhs);
|
||||
IMETHOD friend TwistVel operator/(const TwistVel &lhs, const doubleVel &rhs);
|
||||
IMETHOD friend TwistVel operator*(const TwistVel& lhs,const doubleVel& rhs);
|
||||
IMETHOD friend TwistVel operator*(const doubleVel& lhs,const TwistVel& rhs);
|
||||
IMETHOD friend TwistVel operator/(const TwistVel& lhs,const doubleVel& rhs);
|
||||
|
||||
IMETHOD friend TwistVel operator+(const TwistVel &lhs, const TwistVel &rhs);
|
||||
IMETHOD friend TwistVel operator-(const TwistVel &lhs, const TwistVel &rhs);
|
||||
IMETHOD friend TwistVel operator-(const TwistVel &arg);
|
||||
IMETHOD friend void SetToZero(TwistVel &v);
|
||||
IMETHOD friend TwistVel operator+(const TwistVel& lhs,const TwistVel& rhs);
|
||||
IMETHOD friend TwistVel operator-(const TwistVel& lhs,const TwistVel& rhs);
|
||||
IMETHOD friend TwistVel operator-(const TwistVel& arg);
|
||||
IMETHOD friend void SetToZero(TwistVel& v);
|
||||
|
||||
// = Zero
|
||||
static IMETHOD TwistVel Zero();
|
||||
|
||||
// = Reverse Sign
|
||||
IMETHOD void ReverseSign();
|
||||
// = Zero
|
||||
static IMETHOD TwistVel Zero();
|
||||
|
||||
// = Change Reference point
|
||||
IMETHOD TwistVel RefPoint(const VectorVel &v_base_AB);
|
||||
// Changes the reference point of the TwistVel.
|
||||
// The VectorVel v_base_AB is expressed in the same base as the TwistVel
|
||||
// The VectorVel v_base_AB is a VectorVel from the old point to
|
||||
// the new point.
|
||||
// Complexity : 6M+6A
|
||||
// = Reverse Sign
|
||||
IMETHOD void ReverseSign();
|
||||
|
||||
// = Equality operators
|
||||
// do not use operator == because the definition of Equal(.,.) is slightly
|
||||
// different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
IMETHOD friend bool Equal(const TwistVel &a, const TwistVel &b, double eps);
|
||||
IMETHOD friend bool Equal(const Twist &a, const TwistVel &b, double eps);
|
||||
IMETHOD friend bool Equal(const TwistVel &a, const Twist &b, double eps);
|
||||
// = Change Reference point
|
||||
IMETHOD TwistVel RefPoint(const VectorVel& v_base_AB);
|
||||
// Changes the reference point of the TwistVel.
|
||||
// The VectorVel v_base_AB is expressed in the same base as the TwistVel
|
||||
// The VectorVel v_base_AB is a VectorVel from the old point to
|
||||
// the new point.
|
||||
// Complexity : 6M+6A
|
||||
|
||||
// = Equality operators
|
||||
// do not use operator == because the definition of Equal(.,.) is slightly
|
||||
// different. It compares whether the 2 arguments are equal in an eps-interval
|
||||
IMETHOD friend bool Equal(const TwistVel& a,const TwistVel& b,double eps);
|
||||
IMETHOD friend bool Equal(const Twist& a,const TwistVel& b,double eps);
|
||||
IMETHOD friend bool Equal(const TwistVel& a,const Twist& b,double eps);
|
||||
|
||||
// = Conversion to other entities
|
||||
IMETHOD Twist GetTwist() const;
|
||||
IMETHOD Twist GetTwistDot() const;
|
||||
// = Friends
|
||||
friend class RotationVel;
|
||||
friend class FrameVel;
|
||||
|
||||
// = Conversion to other entities
|
||||
IMETHOD Twist GetTwist() const;
|
||||
IMETHOD Twist GetTwistDot() const;
|
||||
// = Friends
|
||||
friend class RotationVel;
|
||||
friend class FrameVel;
|
||||
};
|
||||
|
||||
IMETHOD bool Equal(const VectorVel &, const VectorVel &, double = epsilon);
|
||||
IMETHOD bool Equal(const Vector &, const VectorVel &, double = epsilon);
|
||||
IMETHOD bool Equal(const VectorVel &, const Vector &, double = epsilon);
|
||||
IMETHOD bool Equal(const RotationVel &, const RotationVel &, double = epsilon);
|
||||
IMETHOD bool Equal(const Rotation &, const RotationVel &, double = epsilon);
|
||||
IMETHOD bool Equal(const RotationVel &, const Rotation &, double = epsilon);
|
||||
IMETHOD bool Equal(const FrameVel &, const FrameVel &, double = epsilon);
|
||||
IMETHOD bool Equal(const Frame &, const FrameVel &, double = epsilon);
|
||||
IMETHOD bool Equal(const FrameVel &, const Frame &, double = epsilon);
|
||||
IMETHOD bool Equal(const TwistVel &, const TwistVel &, double = epsilon);
|
||||
IMETHOD bool Equal(const Twist &, const TwistVel &, double = epsilon);
|
||||
IMETHOD bool Equal(const TwistVel &, const Twist &, double = epsilon);
|
||||
IMETHOD bool Equal(const VectorVel&, const VectorVel&, double = epsilon);
|
||||
IMETHOD bool Equal(const Vector&, const VectorVel&, double = epsilon);
|
||||
IMETHOD bool Equal(const VectorVel&, const Vector&, double = epsilon);
|
||||
IMETHOD bool Equal(const RotationVel&, const RotationVel&, double = epsilon);
|
||||
IMETHOD bool Equal(const Rotation&, const RotationVel&, double = epsilon);
|
||||
IMETHOD bool Equal(const RotationVel&, const Rotation&, double = epsilon);
|
||||
IMETHOD bool Equal(const FrameVel&, const FrameVel&, double = epsilon);
|
||||
IMETHOD bool Equal(const Frame&, const FrameVel&, double = epsilon);
|
||||
IMETHOD bool Equal(const FrameVel&, const Frame&, double = epsilon);
|
||||
IMETHOD bool Equal(const TwistVel&, const TwistVel&, double = epsilon);
|
||||
IMETHOD bool Equal(const Twist&, const TwistVel&, double = epsilon);
|
||||
IMETHOD bool Equal(const TwistVel&, const Twist&, double = epsilon);
|
||||
|
||||
IMETHOD VectorVel diff(const VectorVel &a, const VectorVel &b, double dt = 1.0)
|
||||
{
|
||||
return VectorVel(diff(a.p, b.p, dt), diff(a.v, b.v, dt));
|
||||
IMETHOD VectorVel diff(const VectorVel& a,const VectorVel& b,double dt=1.0) {
|
||||
return VectorVel(diff(a.p,b.p,dt),diff(a.v,b.v,dt));
|
||||
}
|
||||
|
||||
IMETHOD VectorVel addDelta(const VectorVel &a, const VectorVel &da, double dt = 1.0)
|
||||
{
|
||||
return VectorVel(addDelta(a.p, da.p, dt), addDelta(a.v, da.v, dt));
|
||||
IMETHOD VectorVel addDelta(const VectorVel& a,const VectorVel&da,double dt=1.0) {
|
||||
return VectorVel(addDelta(a.p,da.p,dt),addDelta(a.v,da.v,dt));
|
||||
}
|
||||
IMETHOD VectorVel diff(const RotationVel &a, const RotationVel &b, double dt = 1.0)
|
||||
{
|
||||
return VectorVel(diff(a.R, b.R, dt), diff(a.w, b.w, dt));
|
||||
IMETHOD VectorVel diff(const RotationVel& a,const RotationVel& b,double dt = 1.0) {
|
||||
return VectorVel(diff(a.R,b.R,dt),diff(a.w,b.w,dt));
|
||||
}
|
||||
|
||||
IMETHOD RotationVel addDelta(const RotationVel &a, const VectorVel &da, double dt = 1.0)
|
||||
{
|
||||
return RotationVel(addDelta(a.R, da.p, dt), addDelta(a.w, da.v, dt));
|
||||
IMETHOD RotationVel addDelta(const RotationVel& a,const VectorVel&da,double dt=1.0) {
|
||||
return RotationVel(addDelta(a.R,da.p,dt),addDelta(a.w,da.v,dt));
|
||||
}
|
||||
|
||||
IMETHOD TwistVel diff(const FrameVel &a, const FrameVel &b, double dt = 1.0)
|
||||
{
|
||||
return TwistVel(diff(a.M, b.M, dt), diff(a.p, b.p, dt));
|
||||
IMETHOD TwistVel diff(const FrameVel& a,const FrameVel& b,double dt=1.0) {
|
||||
return TwistVel(diff(a.M,b.M,dt),diff(a.p,b.p,dt));
|
||||
}
|
||||
|
||||
IMETHOD FrameVel addDelta(const FrameVel &a, const TwistVel &da, double dt = 1.0)
|
||||
{
|
||||
return FrameVel(addDelta(a.M, da.rot, dt), addDelta(a.p, da.vel, dt));
|
||||
IMETHOD FrameVel addDelta(const FrameVel& a,const TwistVel& da,double dt=1.0) {
|
||||
return FrameVel(
|
||||
addDelta(a.M,da.rot,dt),
|
||||
addDelta(a.p,da.vel,dt)
|
||||
);
|
||||
}
|
||||
|
||||
IMETHOD void random(VectorVel &a)
|
||||
{
|
||||
random(a.p);
|
||||
random(a.v);
|
||||
IMETHOD void random(VectorVel& a) {
|
||||
random(a.p);
|
||||
random(a.v);
|
||||
}
|
||||
IMETHOD void random(TwistVel &a)
|
||||
{
|
||||
random(a.vel);
|
||||
random(a.rot);
|
||||
IMETHOD void random(TwistVel& a) {
|
||||
random(a.vel);
|
||||
random(a.rot);
|
||||
}
|
||||
|
||||
IMETHOD void random(RotationVel &R)
|
||||
{
|
||||
random(R.R);
|
||||
random(R.w);
|
||||
IMETHOD void random(RotationVel& R) {
|
||||
random(R.R);
|
||||
random(R.w);
|
||||
}
|
||||
|
||||
IMETHOD void random(FrameVel &F)
|
||||
{
|
||||
random(F.M);
|
||||
random(F.p);
|
||||
IMETHOD void random(FrameVel& F) {
|
||||
random(F.M);
|
||||
random(F.p);
|
||||
}
|
||||
IMETHOD void posrandom(VectorVel &a)
|
||||
{
|
||||
posrandom(a.p);
|
||||
posrandom(a.v);
|
||||
IMETHOD void posrandom(VectorVel& a) {
|
||||
posrandom(a.p);
|
||||
posrandom(a.v);
|
||||
}
|
||||
IMETHOD void posrandom(TwistVel &a)
|
||||
{
|
||||
posrandom(a.vel);
|
||||
posrandom(a.rot);
|
||||
IMETHOD void posrandom(TwistVel& a) {
|
||||
posrandom(a.vel);
|
||||
posrandom(a.rot);
|
||||
}
|
||||
|
||||
IMETHOD void posrandom(RotationVel &R)
|
||||
{
|
||||
posrandom(R.R);
|
||||
posrandom(R.w);
|
||||
IMETHOD void posrandom(RotationVel& R) {
|
||||
posrandom(R.R);
|
||||
posrandom(R.w);
|
||||
}
|
||||
|
||||
IMETHOD void posrandom(FrameVel &F)
|
||||
{
|
||||
posrandom(F.M);
|
||||
posrandom(F.p);
|
||||
IMETHOD void posrandom(FrameVel& F) {
|
||||
posrandom(F.M);
|
||||
posrandom(F.p);
|
||||
}
|
||||
|
||||
#ifdef KDL_INLINE
|
||||
# include "framevel.inl"
|
||||
#include "framevel.inl"
|
||||
#endif
|
||||
|
||||
} // namespace KDL
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -29,19 +29,23 @@
|
||||
namespace KDL {
|
||||
using namespace Eigen;
|
||||
|
||||
Inertia::Inertia(double m, double Ixx, double Iyy, double Izz, double Ixy, double Ixz, double Iyz)
|
||||
: data(Matrix<double, 6, 6>::Zero())
|
||||
Inertia::Inertia(double m,double Ixx,double Iyy,double Izz,double Ixy,double Ixz,double Iyz):
|
||||
data(Matrix<double,6,6>::Zero())
|
||||
{
|
||||
data(0, 0) = Ixx;
|
||||
data(1, 1) = Iyy;
|
||||
data(2, 2) = Izz;
|
||||
data(2, 1) = data(1, 2) = Ixy;
|
||||
data(3, 1) = data(1, 3) = Ixz;
|
||||
data(3, 2) = data(2, 3) = Iyz;
|
||||
data(0,0)=Ixx;
|
||||
data(1,1)=Iyy;
|
||||
data(2,2)=Izz;
|
||||
data(2,1)=data(1,2)=Ixy;
|
||||
data(3,1)=data(1,3)=Ixz;
|
||||
data(3,2)=data(2,3)=Iyz;
|
||||
|
||||
data.block(3, 3, 3, 3) = m * Matrix<double, 3, 3>::Identity();
|
||||
data.block(3,3,3,3)=m*Matrix<double,3,3>::Identity();
|
||||
}
|
||||
|
||||
Inertia::~Inertia() {}
|
||||
Inertia::~Inertia()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
#ifndef KDLINERTIA_HPP
|
||||
#define KDLINERTIA_HPP
|
||||
|
||||
#include "frames.hpp"
|
||||
#include <Eigen/Core>
|
||||
#include "frames.hpp"
|
||||
|
||||
namespace KDL {
|
||||
|
||||
@@ -34,39 +34,37 @@ using namespace Eigen;
|
||||
* An inertia is defined in a certain reference point and a certain reference base.
|
||||
* The reference point does not have to coincide with the origin of the reference frame.
|
||||
*/
|
||||
class Inertia {
|
||||
public:
|
||||
/**
|
||||
* This constructor creates a cartesian space inertia matrix,
|
||||
* the arguments are the mass and the inertia moments in the cog.
|
||||
*/
|
||||
Inertia(double m = 0,
|
||||
double Ixx = 0,
|
||||
double Iyy = 0,
|
||||
double Izz = 0,
|
||||
double Ixy = 0,
|
||||
double Ixz = 0,
|
||||
double Iyz = 0);
|
||||
class Inertia{
|
||||
public:
|
||||
|
||||
static inline Inertia Zero()
|
||||
{
|
||||
return Inertia(0, 0, 0, 0, 0, 0, 0);
|
||||
};
|
||||
/**
|
||||
* This constructor creates a cartesian space inertia matrix,
|
||||
* the arguments are the mass and the inertia moments in the cog.
|
||||
*/
|
||||
Inertia(double m=0,double Ixx=0,double Iyy=0,double Izz=0,double Ixy=0,double Ixz=0,double Iyz=0);
|
||||
|
||||
friend class Rotation;
|
||||
friend class Frame;
|
||||
static inline Inertia Zero(){
|
||||
return Inertia(0,0,0,0,0,0,0);
|
||||
};
|
||||
|
||||
/**
|
||||
* F = m*a
|
||||
*/
|
||||
// Wrench operator* (const AccelerationTwist& acc);
|
||||
friend class Rotation;
|
||||
friend class Frame;
|
||||
|
||||
~Inertia();
|
||||
/**
|
||||
* F = m*a
|
||||
*/
|
||||
// Wrench operator* (const AccelerationTwist& acc);
|
||||
|
||||
|
||||
~Inertia();
|
||||
private:
|
||||
Matrix<double,6,6,RowMajor> data;
|
||||
|
||||
private:
|
||||
Matrix<double, 6, 6, RowMajor> data;
|
||||
};
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,106 +24,109 @@
|
||||
|
||||
#include "jacobian.hpp"
|
||||
|
||||
namespace KDL {
|
||||
Jacobian::Jacobian(unsigned int _size, unsigned int _nr_blocks)
|
||||
: size(_size), nr_blocks(_nr_blocks)
|
||||
namespace KDL
|
||||
{
|
||||
twists = new Twist[size * nr_blocks];
|
||||
}
|
||||
Jacobian::Jacobian(unsigned int _size,unsigned int _nr_blocks):
|
||||
size(_size),nr_blocks(_nr_blocks)
|
||||
{
|
||||
twists = new Twist[size*nr_blocks];
|
||||
}
|
||||
|
||||
Jacobian::Jacobian(const Jacobian &arg) : size(arg.columns()), nr_blocks(arg.nr_blocks)
|
||||
{
|
||||
twists = new Twist[size * nr_blocks];
|
||||
for (unsigned int i = 0; i < size * nr_blocks; i++)
|
||||
twists[i] = arg.twists[i];
|
||||
}
|
||||
Jacobian::Jacobian(const Jacobian& arg):
|
||||
size(arg.columns()),
|
||||
nr_blocks(arg.nr_blocks)
|
||||
{
|
||||
twists = new Twist[size*nr_blocks];
|
||||
for(unsigned int i=0;i<size*nr_blocks;i++)
|
||||
twists[i] = arg.twists[i];
|
||||
}
|
||||
|
||||
Jacobian &Jacobian::operator=(const Jacobian &arg)
|
||||
{
|
||||
assert(size == arg.size);
|
||||
assert(nr_blocks == arg.nr_blocks);
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
twists[i] = arg.twists[i];
|
||||
return *this;
|
||||
}
|
||||
Jacobian& Jacobian::operator = (const Jacobian& arg)
|
||||
{
|
||||
assert(size==arg.size);
|
||||
assert(nr_blocks==arg.nr_blocks);
|
||||
for(unsigned int i=0;i<size;i++)
|
||||
twists[i]=arg.twists[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
Jacobian::~Jacobian()
|
||||
{
|
||||
delete[] twists;
|
||||
}
|
||||
|
||||
double Jacobian::operator()(int i, int j) const
|
||||
{
|
||||
assert(i < 6 * (int)nr_blocks && j < (int)size);
|
||||
return twists[j + 6 * (int)(floor((double)i / 6))](i % 6);
|
||||
}
|
||||
Jacobian::~Jacobian()
|
||||
{
|
||||
delete [] twists;
|
||||
}
|
||||
|
||||
double &Jacobian::operator()(int i, int j)
|
||||
{
|
||||
assert(i < 6 * (int)nr_blocks && j < (int)size);
|
||||
return twists[j + 6 * (int)(floor((double)i / 6))](i % 6);
|
||||
}
|
||||
double Jacobian::operator()(int i,int j)const
|
||||
{
|
||||
assert(i<6*(int)nr_blocks&&j<(int)size);
|
||||
return twists[j+6*(int)(floor((double)i/6))](i%6);
|
||||
}
|
||||
|
||||
unsigned int Jacobian::rows() const
|
||||
{
|
||||
return 6 * nr_blocks;
|
||||
}
|
||||
double& Jacobian::operator()(int i,int j)
|
||||
{
|
||||
assert(i<6*(int)nr_blocks&&j<(int)size);
|
||||
return twists[j+6*(int)(floor((double)i/6))](i%6);
|
||||
}
|
||||
|
||||
unsigned int Jacobian::columns() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
unsigned int Jacobian::rows()const
|
||||
{
|
||||
return 6*nr_blocks;
|
||||
}
|
||||
|
||||
void SetToZero(Jacobian &jac)
|
||||
{
|
||||
for (unsigned int i = 0; i < jac.size * jac.nr_blocks; i++)
|
||||
SetToZero(jac.twists[i]);
|
||||
}
|
||||
unsigned int Jacobian::columns()const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
void changeRefPoint(const Jacobian &src1, const Vector &base_AB, Jacobian &dest)
|
||||
{
|
||||
assert(src1.size == dest.size);
|
||||
assert(src1.nr_blocks == dest.nr_blocks);
|
||||
for (unsigned int i = 0; i < src1.size * src1.nr_blocks; i++)
|
||||
dest.twists[i] = src1.twists[i].RefPoint(base_AB);
|
||||
}
|
||||
void SetToZero(Jacobian& jac)
|
||||
{
|
||||
for(unsigned int i=0;i<jac.size*jac.nr_blocks;i++)
|
||||
SetToZero(jac.twists[i]);
|
||||
}
|
||||
|
||||
void changeBase(const Jacobian &src1, const Rotation &rot, Jacobian &dest)
|
||||
{
|
||||
assert(src1.size == dest.size);
|
||||
assert(src1.nr_blocks == dest.nr_blocks);
|
||||
for (unsigned int i = 0; i < src1.size * src1.nr_blocks; i++)
|
||||
dest.twists[i] = rot * src1.twists[i];
|
||||
}
|
||||
void changeRefPoint(const Jacobian& src1, const Vector& base_AB, Jacobian& dest)
|
||||
{
|
||||
assert(src1.size==dest.size);
|
||||
assert(src1.nr_blocks==dest.nr_blocks);
|
||||
for(unsigned int i=0;i<src1.size*src1.nr_blocks;i++)
|
||||
dest.twists[i]=src1.twists[i].RefPoint(base_AB);
|
||||
}
|
||||
|
||||
void changeRefFrame(const Jacobian &src1, const Frame &frame, Jacobian &dest)
|
||||
{
|
||||
assert(src1.size == dest.size);
|
||||
assert(src1.nr_blocks == dest.nr_blocks);
|
||||
for (unsigned int i = 0; i < src1.size * src1.nr_blocks; i++)
|
||||
dest.twists[i] = frame * src1.twists[i];
|
||||
}
|
||||
void changeBase(const Jacobian& src1, const Rotation& rot, Jacobian& dest)
|
||||
{
|
||||
assert(src1.size==dest.size);
|
||||
assert(src1.nr_blocks==dest.nr_blocks);
|
||||
for(unsigned int i=0;i<src1.size*src1.nr_blocks;i++)
|
||||
dest.twists[i]=rot*src1.twists[i];
|
||||
}
|
||||
|
||||
bool Jacobian::operator==(const Jacobian &arg)
|
||||
{
|
||||
return Equal((*this), arg);
|
||||
}
|
||||
void changeRefFrame(const Jacobian& src1,const Frame& frame, Jacobian& dest)
|
||||
{
|
||||
assert(src1.size==dest.size);
|
||||
assert(src1.nr_blocks==dest.nr_blocks);
|
||||
for(unsigned int i=0;i<src1.size*src1.nr_blocks;i++)
|
||||
dest.twists[i]=frame*src1.twists[i];
|
||||
}
|
||||
|
||||
bool Jacobian::operator!=(const Jacobian &arg)
|
||||
{
|
||||
return !Equal((*this), arg);
|
||||
bool Jacobian::operator ==(const Jacobian& arg)
|
||||
{
|
||||
return Equal((*this),arg);
|
||||
}
|
||||
|
||||
bool Jacobian::operator!=(const Jacobian& arg)
|
||||
{
|
||||
return !Equal((*this),arg);
|
||||
}
|
||||
|
||||
bool Equal(const Jacobian& a,const Jacobian& b,double eps)
|
||||
{
|
||||
if(a.rows()==b.rows()&&a.columns()==b.columns()){
|
||||
bool rc=true;
|
||||
for(unsigned int i=0;i<a.columns();i++)
|
||||
rc&=Equal(a.twists[i],b.twists[i],eps);
|
||||
return rc;
|
||||
}else
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool Equal(const Jacobian &a, const Jacobian &b, double eps)
|
||||
{
|
||||
if (a.rows() == b.rows() && a.columns() == b.columns()) {
|
||||
bool rc = true;
|
||||
for (unsigned int i = 0; i < a.columns(); i++)
|
||||
rc &= Equal(a.twists[i], b.twists[i], eps);
|
||||
return rc;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
@@ -24,43 +24,46 @@
|
||||
|
||||
#include "frames.hpp"
|
||||
|
||||
namespace KDL {
|
||||
// Forward declaration
|
||||
class ChainJntToJacSolver;
|
||||
namespace KDL
|
||||
{
|
||||
//Forward declaration
|
||||
class ChainJntToJacSolver;
|
||||
|
||||
class Jacobian {
|
||||
friend class ChainJntToJacSolver;
|
||||
class Jacobian
|
||||
{
|
||||
friend class ChainJntToJacSolver;
|
||||
private:
|
||||
unsigned int size;
|
||||
unsigned int nr_blocks;
|
||||
public:
|
||||
Twist* twists;
|
||||
Jacobian(unsigned int size,unsigned int nr=1);
|
||||
Jacobian(const Jacobian& arg);
|
||||
|
||||
private:
|
||||
unsigned int size;
|
||||
unsigned int nr_blocks;
|
||||
Jacobian& operator=(const Jacobian& arg);
|
||||
|
||||
public:
|
||||
Twist *twists;
|
||||
Jacobian(unsigned int size, unsigned int nr = 1);
|
||||
Jacobian(const Jacobian &arg);
|
||||
bool operator ==(const Jacobian& arg);
|
||||
bool operator !=(const Jacobian& arg);
|
||||
|
||||
friend bool Equal(const Jacobian& a,const Jacobian& b,double eps);
|
||||
|
||||
|
||||
Jacobian &operator=(const Jacobian &arg);
|
||||
~Jacobian();
|
||||
|
||||
bool operator==(const Jacobian &arg);
|
||||
bool operator!=(const Jacobian &arg);
|
||||
double operator()(int i,int j)const;
|
||||
double& operator()(int i,int j);
|
||||
unsigned int rows()const;
|
||||
unsigned int columns()const;
|
||||
|
||||
friend bool Equal(const Jacobian &a, const Jacobian &b, double eps);
|
||||
friend void SetToZero(Jacobian& jac);
|
||||
|
||||
~Jacobian();
|
||||
friend void changeRefPoint(const Jacobian& src1, const Vector& base_AB, Jacobian& dest);
|
||||
friend void changeBase(const Jacobian& src1, const Rotation& rot, Jacobian& dest);
|
||||
friend void changeRefFrame(const Jacobian& src1,const Frame& frame, Jacobian& dest);
|
||||
|
||||
double operator()(int i, int j) const;
|
||||
double &operator()(int i, int j);
|
||||
unsigned int rows() const;
|
||||
unsigned int columns() const;
|
||||
|
||||
friend void SetToZero(Jacobian &jac);
|
||||
|
||||
friend void changeRefPoint(const Jacobian &src1, const Vector &base_AB, Jacobian &dest);
|
||||
friend void changeBase(const Jacobian &src1, const Rotation &rot, Jacobian &dest);
|
||||
friend void changeRefFrame(const Jacobian &src1, const Frame &frame, Jacobian &dest);
|
||||
};
|
||||
bool Equal(const Jacobian &, const Jacobian &, double = epsilon);
|
||||
} // namespace KDL
|
||||
};
|
||||
bool Equal(const Jacobian&, const Jacobian&, double = epsilon);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,129 +24,137 @@
|
||||
|
||||
#include "jntarray.hpp"
|
||||
|
||||
namespace KDL {
|
||||
JntArray::JntArray() : size(0), data(NULL) {}
|
||||
|
||||
JntArray::JntArray(unsigned int _size) : size(_size)
|
||||
namespace KDL
|
||||
{
|
||||
assert(0 < size);
|
||||
data = new double[size];
|
||||
SetToZero(*this);
|
||||
JntArray::JntArray():
|
||||
size(0),
|
||||
data(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
JntArray::JntArray(unsigned int _size):
|
||||
size(_size)
|
||||
{
|
||||
assert(0 < size);
|
||||
data = new double[size];
|
||||
SetToZero(*this);
|
||||
}
|
||||
|
||||
|
||||
JntArray::JntArray(const JntArray& arg):
|
||||
size(arg.size)
|
||||
{
|
||||
data = ((0 < size) ? new double[size] : NULL);
|
||||
for(unsigned int i=0;i<size;i++)
|
||||
data[i]=arg.data[i];
|
||||
}
|
||||
|
||||
JntArray& JntArray::operator = (const JntArray& arg)
|
||||
{
|
||||
assert(size==arg.size);
|
||||
for(unsigned int i=0;i<size;i++)
|
||||
data[i]=arg.data[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
JntArray::~JntArray()
|
||||
{
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
void JntArray::resize(unsigned int newSize)
|
||||
{
|
||||
delete [] data;
|
||||
size = newSize;
|
||||
data = new double[size];
|
||||
SetToZero(*this);
|
||||
}
|
||||
|
||||
double JntArray::operator[](unsigned int i)const
|
||||
{
|
||||
assert(i<size);
|
||||
return data[i];
|
||||
}
|
||||
|
||||
double& JntArray::operator[](unsigned int i)
|
||||
{
|
||||
assert(i<size);
|
||||
return data[i];
|
||||
}
|
||||
|
||||
double* JntArray::operator()(unsigned int i)
|
||||
{
|
||||
if (i>=size)
|
||||
return NULL;
|
||||
return &data[i];
|
||||
}
|
||||
|
||||
unsigned int JntArray::rows()const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned int JntArray::columns()const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Add(const JntArray& src1,const JntArray& src2,JntArray& dest)
|
||||
{
|
||||
assert(src1.size==src2.size&&src1.size==dest.size);
|
||||
for(unsigned int i=0;i<dest.size;i++)
|
||||
dest.data[i]=src1.data[i]+src2.data[i];
|
||||
}
|
||||
|
||||
void Subtract(const JntArray& src1,const JntArray& src2,JntArray& dest)
|
||||
{
|
||||
assert(src1.size==src2.size&&src1.size==dest.size);
|
||||
for(unsigned int i=0;i<dest.size;i++)
|
||||
dest.data[i]=src1.data[i]-src2.data[i];
|
||||
}
|
||||
|
||||
void Multiply(const JntArray& src,const double& factor,JntArray& dest)
|
||||
{
|
||||
assert(src.size==dest.size);
|
||||
for(unsigned int i=0;i<dest.size;i++)
|
||||
dest.data[i]=factor*src.data[i];
|
||||
}
|
||||
|
||||
void Divide(const JntArray& src,const double& factor,JntArray& dest)
|
||||
{
|
||||
assert(src.rows()==dest.size);
|
||||
for(unsigned int i=0;i<dest.size;i++)
|
||||
dest.data[i]=src.data[i]/factor;
|
||||
}
|
||||
|
||||
void MultiplyJacobian(const Jacobian& jac, const JntArray& src, Twist& dest)
|
||||
{
|
||||
assert(jac.columns()==src.size);
|
||||
SetToZero(dest);
|
||||
for(unsigned int i=0;i<6;i++)
|
||||
for(unsigned int j=0;j<src.size;j++)
|
||||
dest(i)+=jac(i,j)*src.data[j];
|
||||
}
|
||||
|
||||
void SetToZero(JntArray& array)
|
||||
{
|
||||
for(unsigned int i=0;i<array.size;i++)
|
||||
array.data[i]=0;
|
||||
}
|
||||
|
||||
bool Equal(const JntArray& src1, const JntArray& src2,double eps)
|
||||
{
|
||||
assert(src1.size==src2.size);
|
||||
bool ret = true;
|
||||
for(unsigned int i=0;i<src1.size;i++)
|
||||
ret = ret && Equal(src1.data[i],src2.data[i],eps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool operator==(const JntArray& src1,const JntArray& src2){return Equal(src1,src2);};
|
||||
//bool operator!=(const JntArray& src1,const JntArray& src2){return Equal(src1,src2);};
|
||||
|
||||
}
|
||||
|
||||
JntArray::JntArray(const JntArray &arg) : size(arg.size)
|
||||
{
|
||||
data = ((0 < size) ? new double[size] : NULL);
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
data[i] = arg.data[i];
|
||||
}
|
||||
|
||||
JntArray &JntArray::operator=(const JntArray &arg)
|
||||
{
|
||||
assert(size == arg.size);
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
data[i] = arg.data[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
JntArray::~JntArray()
|
||||
{
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
void JntArray::resize(unsigned int newSize)
|
||||
{
|
||||
delete[] data;
|
||||
size = newSize;
|
||||
data = new double[size];
|
||||
SetToZero(*this);
|
||||
}
|
||||
|
||||
double JntArray::operator[](unsigned int i) const
|
||||
{
|
||||
assert(i < size);
|
||||
return data[i];
|
||||
}
|
||||
|
||||
double &JntArray::operator[](unsigned int i)
|
||||
{
|
||||
assert(i < size);
|
||||
return data[i];
|
||||
}
|
||||
|
||||
double *JntArray::operator()(unsigned int i)
|
||||
{
|
||||
if (i >= size)
|
||||
return NULL;
|
||||
return &data[i];
|
||||
}
|
||||
|
||||
unsigned int JntArray::rows() const
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
unsigned int JntArray::columns() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Add(const JntArray &src1, const JntArray &src2, JntArray &dest)
|
||||
{
|
||||
assert(src1.size == src2.size && src1.size == dest.size);
|
||||
for (unsigned int i = 0; i < dest.size; i++)
|
||||
dest.data[i] = src1.data[i] + src2.data[i];
|
||||
}
|
||||
|
||||
void Subtract(const JntArray &src1, const JntArray &src2, JntArray &dest)
|
||||
{
|
||||
assert(src1.size == src2.size && src1.size == dest.size);
|
||||
for (unsigned int i = 0; i < dest.size; i++)
|
||||
dest.data[i] = src1.data[i] - src2.data[i];
|
||||
}
|
||||
|
||||
void Multiply(const JntArray &src, const double &factor, JntArray &dest)
|
||||
{
|
||||
assert(src.size == dest.size);
|
||||
for (unsigned int i = 0; i < dest.size; i++)
|
||||
dest.data[i] = factor * src.data[i];
|
||||
}
|
||||
|
||||
void Divide(const JntArray &src, const double &factor, JntArray &dest)
|
||||
{
|
||||
assert(src.rows() == dest.size);
|
||||
for (unsigned int i = 0; i < dest.size; i++)
|
||||
dest.data[i] = src.data[i] / factor;
|
||||
}
|
||||
|
||||
void MultiplyJacobian(const Jacobian &jac, const JntArray &src, Twist &dest)
|
||||
{
|
||||
assert(jac.columns() == src.size);
|
||||
SetToZero(dest);
|
||||
for (unsigned int i = 0; i < 6; i++)
|
||||
for (unsigned int j = 0; j < src.size; j++)
|
||||
dest(i) += jac(i, j) * src.data[j];
|
||||
}
|
||||
|
||||
void SetToZero(JntArray &array)
|
||||
{
|
||||
for (unsigned int i = 0; i < array.size; i++)
|
||||
array.data[i] = 0;
|
||||
}
|
||||
|
||||
bool Equal(const JntArray &src1, const JntArray &src2, double eps)
|
||||
{
|
||||
assert(src1.size == src2.size);
|
||||
bool ret = true;
|
||||
for (unsigned int i = 0; i < src1.size; i++)
|
||||
ret = ret && Equal(src1.data[i], src2.data[i], eps);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool operator==(const JntArray &src1, const JntArray &src2)
|
||||
{
|
||||
return Equal(src1, src2);
|
||||
};
|
||||
// bool operator!=(const JntArray& src1,const JntArray& src2){return Equal(src1,src2);};
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
@@ -25,198 +25,199 @@
|
||||
#include "frames.hpp"
|
||||
#include "jacobian.hpp"
|
||||
|
||||
namespace KDL {
|
||||
/**
|
||||
* @brief This class represents an fixed size array containing
|
||||
* joint values of a KDL::Chain.
|
||||
*
|
||||
* \warning An object constructed with the default constructor provides
|
||||
* a valid, but inert, object. Many of the member functions will do
|
||||
* the correct thing and have no affect on this object, but some
|
||||
* member functions can _NOT_ deal with an inert/empty object. These
|
||||
* functions will assert() and exit the program instead. The intended use
|
||||
* case for the default constructor (in an RTT/OCL setting) is outlined in
|
||||
* code below - the default constructor plus the resize() function allow
|
||||
* use of JntArray objects whose size is set within a configureHook() call
|
||||
* (typically based on a size determined from a property).
|
||||
|
||||
namespace KDL
|
||||
{
|
||||
/**
|
||||
* @brief This class represents an fixed size array containing
|
||||
* joint values of a KDL::Chain.
|
||||
*
|
||||
* \warning An object constructed with the default constructor provides
|
||||
* a valid, but inert, object. Many of the member functions will do
|
||||
* the correct thing and have no affect on this object, but some
|
||||
* member functions can _NOT_ deal with an inert/empty object. These
|
||||
* functions will assert() and exit the program instead. The intended use
|
||||
* case for the default constructor (in an RTT/OCL setting) is outlined in
|
||||
* code below - the default constructor plus the resize() function allow
|
||||
* use of JntArray objects whose size is set within a configureHook() call
|
||||
* (typically based on a size determined from a property).
|
||||
|
||||
\code
|
||||
class MyTask : public RTT::TaskContext
|
||||
{
|
||||
JntArray j;
|
||||
MyTask()
|
||||
{} // invokes j's default constructor
|
||||
JntArray j;
|
||||
MyTask()
|
||||
{} // invokes j's default constructor
|
||||
|
||||
bool configureHook()
|
||||
{
|
||||
unsigned int size = some_property.rvalue();
|
||||
j.resize(size)
|
||||
...
|
||||
}
|
||||
bool configureHook()
|
||||
{
|
||||
unsigned int size = some_property.rvalue();
|
||||
j.resize(size)
|
||||
...
|
||||
}
|
||||
|
||||
void updateHook()
|
||||
{
|
||||
** use j here
|
||||
}
|
||||
void updateHook()
|
||||
{
|
||||
** use j here
|
||||
}
|
||||
};
|
||||
\endcode
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
class JntArray {
|
||||
private:
|
||||
unsigned int size;
|
||||
double *data;
|
||||
class JntArray
|
||||
{
|
||||
private:
|
||||
unsigned int size;
|
||||
double* data;
|
||||
public:
|
||||
/** Construct with _no_ data array
|
||||
* @post NULL == data
|
||||
* @post 0 == rows()
|
||||
* @warning use of an object constructed like this, without
|
||||
* a resize() first, may result in program exit! See class
|
||||
* documentation.
|
||||
*/
|
||||
JntArray();
|
||||
/**
|
||||
* Constructor of the joint array
|
||||
*
|
||||
* @param size size of the array, this cannot be changed
|
||||
* afterwards.
|
||||
* @pre 0 < size
|
||||
* @post NULL != data
|
||||
* @post 0 < rows()
|
||||
* @post all elements in data have 0 value
|
||||
*/
|
||||
JntArray(unsigned int size);
|
||||
/** Copy constructor
|
||||
* @note Will correctly copy an empty object
|
||||
*/
|
||||
JntArray(const JntArray& arg);
|
||||
~JntArray();
|
||||
/** Resize the array
|
||||
* @warning This causes a dynamic allocation (and potentially
|
||||
* also a dynamic deallocation). This _will_ negatively affect
|
||||
* real-time performance!
|
||||
*
|
||||
* @post newSize == rows()
|
||||
* @post NULL != data
|
||||
* @post all elements in data have 0 value
|
||||
*/
|
||||
void resize(unsigned int newSize);
|
||||
|
||||
JntArray& operator = ( const JntArray& arg);
|
||||
/**
|
||||
* get_item operator for the joint array
|
||||
*
|
||||
*
|
||||
* @return the joint value at position i, starting from 0
|
||||
* @pre 0 != size (ie non-default constructor or resize() called)
|
||||
*/
|
||||
double operator[](unsigned int i) const;
|
||||
/**
|
||||
* set_item operator
|
||||
*
|
||||
* @return reference to the joint value at position i,starting
|
||||
*from zero.
|
||||
* @pre 0 != size (ie non-default constructor or resize() called)
|
||||
*/
|
||||
double& operator[](unsigned int i);
|
||||
/**
|
||||
* access operator for the joint array. Use pointer here to allow
|
||||
* access to sequential joint angles (required for ndof joints)
|
||||
*
|
||||
*
|
||||
* @return the joint value at position i, NULL if i is outside the valid range
|
||||
*/
|
||||
double* operator()(unsigned int i);
|
||||
/**
|
||||
* Returns the number of rows (size) of the array
|
||||
*
|
||||
*/
|
||||
unsigned int rows()const;
|
||||
/**
|
||||
* Returns the number of columns of the array, always 1.
|
||||
*/
|
||||
unsigned int columns()const;
|
||||
|
||||
public:
|
||||
/** Construct with _no_ data array
|
||||
* @post NULL == data
|
||||
* @post 0 == rows()
|
||||
* @warning use of an object constructed like this, without
|
||||
* a resize() first, may result in program exit! See class
|
||||
* documentation.
|
||||
*/
|
||||
JntArray();
|
||||
/**
|
||||
* Constructor of the joint array
|
||||
*
|
||||
* @param size size of the array, this cannot be changed
|
||||
* afterwards.
|
||||
* @pre 0 < size
|
||||
* @post NULL != data
|
||||
* @post 0 < rows()
|
||||
* @post all elements in data have 0 value
|
||||
*/
|
||||
JntArray(unsigned int size);
|
||||
/** Copy constructor
|
||||
* @note Will correctly copy an empty object
|
||||
*/
|
||||
JntArray(const JntArray &arg);
|
||||
~JntArray();
|
||||
/** Resize the array
|
||||
* @warning This causes a dynamic allocation (and potentially
|
||||
* also a dynamic deallocation). This _will_ negatively affect
|
||||
* real-time performance!
|
||||
*
|
||||
* @post newSize == rows()
|
||||
* @post NULL != data
|
||||
* @post all elements in data have 0 value
|
||||
*/
|
||||
void resize(unsigned int newSize);
|
||||
/**
|
||||
* Function to add two joint arrays, all the arguments must
|
||||
* have the same size: A + B = C. This function is
|
||||
* aliasing-safe, A or B can be the same array as C.
|
||||
*
|
||||
* @param src1 A
|
||||
* @param src2 B
|
||||
* @param dest C
|
||||
*/
|
||||
friend void Add(const JntArray& src1,const JntArray& src2,JntArray& dest);
|
||||
/**
|
||||
* Function to subtract two joint arrays, all the arguments must
|
||||
* have the same size: A - B = C. This function is
|
||||
* aliasing-safe, A or B can be the same array as C.
|
||||
*
|
||||
* @param src1 A
|
||||
* @param src2 B
|
||||
* @param dest C
|
||||
*/
|
||||
friend void Subtract(const JntArray& src1,const JntArray& src2,JntArray& dest);
|
||||
/**
|
||||
* Function to multiply all the array values with a scalar
|
||||
* factor: A*b=C. This function is aliasing-safe, A can be the
|
||||
* same array as C.
|
||||
*
|
||||
* @param src A
|
||||
* @param factor b
|
||||
* @param dest C
|
||||
*/
|
||||
friend void Multiply(const JntArray& src,const double& factor,JntArray& dest);
|
||||
/**
|
||||
* Function to divide all the array values with a scalar
|
||||
* factor: A/b=C. This function is aliasing-safe, A can be the
|
||||
* same array as C.
|
||||
*
|
||||
* @param src A
|
||||
* @param factor b
|
||||
* @param dest C
|
||||
*/
|
||||
friend void Divide(const JntArray& src,const double& factor,JntArray& dest);
|
||||
/**
|
||||
* Function to multiply a KDL::Jacobian with a KDL::JntArray
|
||||
* to get a KDL::Twist, it should not be used to calculate the
|
||||
* forward velocity kinematics, the solver classes are built
|
||||
* for this purpose.
|
||||
* J*q = t
|
||||
*
|
||||
* @param jac J
|
||||
* @param src q
|
||||
* @param dest t
|
||||
* @post dest==Twist::Zero() if 0==src.rows() (ie src is empty)
|
||||
*/
|
||||
friend void MultiplyJacobian(const Jacobian& jac, const JntArray& src, Twist& dest);
|
||||
/**
|
||||
* Function to set all the values of the array to 0
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
friend void SetToZero(JntArray& array);
|
||||
/**
|
||||
* Function to check if two arrays are the same with a
|
||||
*precision of eps
|
||||
*
|
||||
* @param src1
|
||||
* @param src2
|
||||
* @param eps default: epsilon
|
||||
* @return true if each element of src1 is within eps of the same
|
||||
* element in src2, or if both src1 and src2 have no data (ie 0==rows())
|
||||
*/
|
||||
friend bool Equal(const JntArray& src1,const JntArray& src2,double eps);
|
||||
|
||||
JntArray &operator=(const JntArray &arg);
|
||||
/**
|
||||
* get_item operator for the joint array
|
||||
*
|
||||
*
|
||||
* @return the joint value at position i, starting from 0
|
||||
* @pre 0 != size (ie non-default constructor or resize() called)
|
||||
*/
|
||||
double operator[](unsigned int i) const;
|
||||
/**
|
||||
* set_item operator
|
||||
*
|
||||
* @return reference to the joint value at position i,starting
|
||||
*from zero.
|
||||
* @pre 0 != size (ie non-default constructor or resize() called)
|
||||
*/
|
||||
double &operator[](unsigned int i);
|
||||
/**
|
||||
* access operator for the joint array. Use pointer here to allow
|
||||
* access to sequential joint angles (required for ndof joints)
|
||||
*
|
||||
*
|
||||
* @return the joint value at position i, NULL if i is outside the valid range
|
||||
*/
|
||||
double *operator()(unsigned int i);
|
||||
/**
|
||||
* Returns the number of rows (size) of the array
|
||||
*
|
||||
*/
|
||||
unsigned int rows() const;
|
||||
/**
|
||||
* Returns the number of columns of the array, always 1.
|
||||
*/
|
||||
unsigned int columns() const;
|
||||
friend bool operator==(const JntArray& src1,const JntArray& src2);
|
||||
//friend bool operator!=(const JntArray& src1,const JntArray& src2);
|
||||
};
|
||||
bool Equal(const JntArray&,const JntArray&, double = epsilon);
|
||||
bool operator==(const JntArray& src1,const JntArray& src2);
|
||||
//bool operator!=(const JntArray& src1,const JntArray& src2);
|
||||
|
||||
/**
|
||||
* Function to add two joint arrays, all the arguments must
|
||||
* have the same size: A + B = C. This function is
|
||||
* aliasing-safe, A or B can be the same array as C.
|
||||
*
|
||||
* @param src1 A
|
||||
* @param src2 B
|
||||
* @param dest C
|
||||
*/
|
||||
friend void Add(const JntArray &src1, const JntArray &src2, JntArray &dest);
|
||||
/**
|
||||
* Function to subtract two joint arrays, all the arguments must
|
||||
* have the same size: A - B = C. This function is
|
||||
* aliasing-safe, A or B can be the same array as C.
|
||||
*
|
||||
* @param src1 A
|
||||
* @param src2 B
|
||||
* @param dest C
|
||||
*/
|
||||
friend void Subtract(const JntArray &src1, const JntArray &src2, JntArray &dest);
|
||||
/**
|
||||
* Function to multiply all the array values with a scalar
|
||||
* factor: A*b=C. This function is aliasing-safe, A can be the
|
||||
* same array as C.
|
||||
*
|
||||
* @param src A
|
||||
* @param factor b
|
||||
* @param dest C
|
||||
*/
|
||||
friend void Multiply(const JntArray &src, const double &factor, JntArray &dest);
|
||||
/**
|
||||
* Function to divide all the array values with a scalar
|
||||
* factor: A/b=C. This function is aliasing-safe, A can be the
|
||||
* same array as C.
|
||||
*
|
||||
* @param src A
|
||||
* @param factor b
|
||||
* @param dest C
|
||||
*/
|
||||
friend void Divide(const JntArray &src, const double &factor, JntArray &dest);
|
||||
/**
|
||||
* Function to multiply a KDL::Jacobian with a KDL::JntArray
|
||||
* to get a KDL::Twist, it should not be used to calculate the
|
||||
* forward velocity kinematics, the solver classes are built
|
||||
* for this purpose.
|
||||
* J*q = t
|
||||
*
|
||||
* @param jac J
|
||||
* @param src q
|
||||
* @param dest t
|
||||
* @post dest==Twist::Zero() if 0==src.rows() (ie src is empty)
|
||||
*/
|
||||
friend void MultiplyJacobian(const Jacobian &jac, const JntArray &src, Twist &dest);
|
||||
/**
|
||||
* Function to set all the values of the array to 0
|
||||
*
|
||||
* @param array
|
||||
*/
|
||||
friend void SetToZero(JntArray &array);
|
||||
/**
|
||||
* Function to check if two arrays are the same with a
|
||||
*precision of eps
|
||||
*
|
||||
* @param src1
|
||||
* @param src2
|
||||
* @param eps default: epsilon
|
||||
* @return true if each element of src1 is within eps of the same
|
||||
* element in src2, or if both src1 and src2 have no data (ie 0==rows())
|
||||
*/
|
||||
friend bool Equal(const JntArray &src1, const JntArray &src2, double eps);
|
||||
|
||||
friend bool operator==(const JntArray &src1, const JntArray &src2);
|
||||
// friend bool operator!=(const JntArray& src1,const JntArray& src2);
|
||||
};
|
||||
bool Equal(const JntArray &, const JntArray &, double = epsilon);
|
||||
bool operator==(const JntArray &src1, const JntArray &src2);
|
||||
// bool operator!=(const JntArray& src1,const JntArray& src2);
|
||||
|
||||
} // namespace KDL
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,145 +24,150 @@
|
||||
|
||||
#include "jntarrayacc.hpp"
|
||||
|
||||
namespace KDL {
|
||||
JntArrayAcc::JntArrayAcc(unsigned int size) : q(size), qdot(size), qdotdot(size) {}
|
||||
JntArrayAcc::JntArrayAcc(const JntArray &qin, const JntArray &qdotin, const JntArray &qdotdotin)
|
||||
: q(qin), qdot(qdotin), qdotdot(qdotdotin)
|
||||
namespace KDL
|
||||
{
|
||||
assert(q.rows() == qdot.rows() && qdot.rows() == qdotdot.rows());
|
||||
}
|
||||
JntArrayAcc::JntArrayAcc(const JntArray &qin, const JntArray &qdotin)
|
||||
: q(qin), qdot(qdotin), qdotdot(q.rows())
|
||||
{
|
||||
assert(q.rows() == qdot.rows());
|
||||
}
|
||||
JntArrayAcc::JntArrayAcc(const JntArray &qin) : q(qin), qdot(q.rows()), qdotdot(q.rows()) {}
|
||||
JntArrayAcc::JntArrayAcc(unsigned int size):
|
||||
q(size),qdot(size),qdotdot(size)
|
||||
{
|
||||
}
|
||||
JntArrayAcc::JntArrayAcc(const JntArray& qin, const JntArray& qdotin,const JntArray& qdotdotin):
|
||||
q(qin),qdot(qdotin),qdotdot(qdotdotin)
|
||||
{
|
||||
assert(q.rows()==qdot.rows()&&qdot.rows()==qdotdot.rows());
|
||||
}
|
||||
JntArrayAcc::JntArrayAcc(const JntArray& qin, const JntArray& qdotin):
|
||||
q(qin),qdot(qdotin),qdotdot(q.rows())
|
||||
{
|
||||
assert(q.rows()==qdot.rows());
|
||||
}
|
||||
JntArrayAcc::JntArrayAcc(const JntArray& qin):
|
||||
q(qin),qdot(q.rows()),qdotdot(q.rows())
|
||||
{
|
||||
}
|
||||
|
||||
JntArray JntArrayAcc::value() const
|
||||
{
|
||||
return q;
|
||||
JntArray JntArrayAcc::value()const
|
||||
{
|
||||
return q;
|
||||
}
|
||||
|
||||
JntArray JntArrayAcc::deriv()const
|
||||
{
|
||||
return qdot;
|
||||
}
|
||||
JntArray JntArrayAcc::dderiv()const
|
||||
{
|
||||
return qdotdot;
|
||||
}
|
||||
|
||||
void Add(const JntArrayAcc& src1,const JntArrayAcc& src2,JntArrayAcc& dest)
|
||||
{
|
||||
Add(src1.q,src2.q,dest.q);
|
||||
Add(src1.qdot,src2.qdot,dest.qdot);
|
||||
Add(src1.qdotdot,src2.qdotdot,dest.qdotdot);
|
||||
}
|
||||
void Add(const JntArrayAcc& src1,const JntArrayVel& src2,JntArrayAcc& dest)
|
||||
{
|
||||
Add(src1.q,src2.q,dest.q);
|
||||
Add(src1.qdot,src2.qdot,dest.qdot);
|
||||
dest.qdotdot=src1.qdotdot;
|
||||
}
|
||||
void Add(const JntArrayAcc& src1,const JntArray& src2,JntArrayAcc& dest)
|
||||
{
|
||||
Add(src1.q,src2,dest.q);
|
||||
dest.qdot=src1.qdot;
|
||||
dest.qdotdot=src1.qdotdot;
|
||||
}
|
||||
|
||||
void Subtract(const JntArrayAcc& src1,const JntArrayAcc& src2,JntArrayAcc& dest)
|
||||
{
|
||||
Subtract(src1.q,src2.q,dest.q);
|
||||
Subtract(src1.qdot,src2.qdot,dest.qdot);
|
||||
Subtract(src1.qdotdot,src2.qdotdot,dest.qdotdot);
|
||||
}
|
||||
void Subtract(const JntArrayAcc& src1,const JntArrayVel& src2,JntArrayAcc& dest)
|
||||
{
|
||||
Subtract(src1.q,src2.q,dest.q);
|
||||
Subtract(src1.qdot,src2.qdot,dest.qdot);
|
||||
dest.qdotdot=src1.qdotdot;
|
||||
}
|
||||
void Subtract(const JntArrayAcc& src1,const JntArray& src2,JntArrayAcc& dest)
|
||||
{
|
||||
Subtract(src1.q,src2,dest.q);
|
||||
dest.qdot=src1.qdot;
|
||||
dest.qdotdot=src1.qdotdot;
|
||||
}
|
||||
|
||||
void Multiply(const JntArrayAcc& src,const double& factor,JntArrayAcc& dest)
|
||||
{
|
||||
Multiply(src.q,factor,dest.q);
|
||||
Multiply(src.qdot,factor,dest.qdot);
|
||||
Multiply(src.qdotdot,factor,dest.qdotdot);
|
||||
}
|
||||
void Multiply(const JntArrayAcc& src,const doubleVel& factor,JntArrayAcc& dest)
|
||||
{
|
||||
Multiply(src.qdot,factor.grad*2,dest.qdot);
|
||||
Multiply(src.qdotdot,factor.t,dest.qdotdot);
|
||||
Add(dest.qdot,dest.qdotdot,dest.qdotdot);
|
||||
Multiply(src.q,factor.grad,dest.q);
|
||||
Multiply(src.qdot,factor.t,dest.qdot);
|
||||
Add(dest.qdot,dest.q,dest.qdot);
|
||||
Multiply(src.q,factor.t,dest.q);
|
||||
}
|
||||
void Multiply(const JntArrayAcc& src,const doubleAcc& factor,JntArrayAcc& dest)
|
||||
{
|
||||
Multiply(src.q,factor.dd,dest.q);
|
||||
Multiply(src.qdot,factor.d*2,dest.qdot);
|
||||
Multiply(src.qdotdot,factor.t,dest.qdotdot);
|
||||
Add(dest.qdotdot,dest.qdot,dest.qdotdot);
|
||||
Add(dest.qdotdot,dest.q,dest.qdotdot);
|
||||
Multiply(src.q,factor.d,dest.q);
|
||||
Multiply(src.qdot,factor.t,dest.qdot);
|
||||
Add(dest.qdot,dest.q,dest.qdot);
|
||||
Multiply(src.q,factor.t,dest.q);
|
||||
}
|
||||
|
||||
void Divide(const JntArrayAcc& src,const double& factor,JntArrayAcc& dest)
|
||||
{
|
||||
Divide(src.q,factor,dest.q);
|
||||
Divide(src.qdot,factor,dest.qdot);
|
||||
Divide(src.qdotdot,factor,dest.qdotdot);
|
||||
}
|
||||
void Divide(const JntArrayAcc& src,const doubleVel& factor,JntArrayAcc& dest)
|
||||
{
|
||||
Multiply(src.q,(2*factor.grad*factor.grad)/(factor.t*factor.t*factor.t),dest.q);
|
||||
Multiply(src.qdot,(2*factor.grad)/(factor.t*factor.t),dest.qdot);
|
||||
Divide(src.qdotdot,factor.t,dest.qdotdot);
|
||||
Subtract(dest.qdotdot,dest.qdot,dest.qdotdot);
|
||||
Add(dest.qdotdot,dest.q,dest.qdotdot);
|
||||
Multiply(src.q,factor.grad/(factor.t*factor.t),dest.q);
|
||||
Divide(src.qdot,factor.t,dest.qdot);
|
||||
Subtract(dest.qdot,dest.q,dest.qdot);
|
||||
Divide(src.q,factor.t,dest.q);
|
||||
}
|
||||
void Divide(const JntArrayAcc& src,const doubleAcc& factor,JntArrayAcc& dest)
|
||||
{
|
||||
Multiply(src.q,(2*factor.d*factor.d)/(factor.t*factor.t*factor.t)-factor.dd/(factor.t*factor.t),dest.q);
|
||||
Multiply(src.qdot,(2*factor.d)/(factor.t*factor.t),dest.qdot);
|
||||
Divide(src.qdotdot,factor.t,dest.qdotdot);
|
||||
Subtract(dest.qdotdot,dest.qdot,dest.qdotdot);
|
||||
Add(dest.qdotdot,dest.q,dest.qdotdot);
|
||||
Multiply(src.q,factor.d/(factor.t*factor.t),dest.q);
|
||||
Divide(src.qdot,factor.t,dest.qdot);
|
||||
Subtract(dest.qdot,dest.q,dest.qdot);
|
||||
Divide(src.q,factor.t,dest.q);
|
||||
}
|
||||
|
||||
void SetToZero(JntArrayAcc& array)
|
||||
{
|
||||
SetToZero(array.q);
|
||||
SetToZero(array.qdot);
|
||||
SetToZero(array.qdotdot);
|
||||
}
|
||||
|
||||
bool Equal(const JntArrayAcc& src1,const JntArrayAcc& src2,double eps)
|
||||
{
|
||||
return (Equal(src1.q,src2.q,eps)&&Equal(src1.qdot,src2.qdot,eps)&&Equal(src1.qdotdot,src2.qdotdot,eps));
|
||||
}
|
||||
}
|
||||
|
||||
JntArray JntArrayAcc::deriv() const
|
||||
{
|
||||
return qdot;
|
||||
}
|
||||
JntArray JntArrayAcc::dderiv() const
|
||||
{
|
||||
return qdotdot;
|
||||
}
|
||||
|
||||
void Add(const JntArrayAcc &src1, const JntArrayAcc &src2, JntArrayAcc &dest)
|
||||
{
|
||||
Add(src1.q, src2.q, dest.q);
|
||||
Add(src1.qdot, src2.qdot, dest.qdot);
|
||||
Add(src1.qdotdot, src2.qdotdot, dest.qdotdot);
|
||||
}
|
||||
void Add(const JntArrayAcc &src1, const JntArrayVel &src2, JntArrayAcc &dest)
|
||||
{
|
||||
Add(src1.q, src2.q, dest.q);
|
||||
Add(src1.qdot, src2.qdot, dest.qdot);
|
||||
dest.qdotdot = src1.qdotdot;
|
||||
}
|
||||
void Add(const JntArrayAcc &src1, const JntArray &src2, JntArrayAcc &dest)
|
||||
{
|
||||
Add(src1.q, src2, dest.q);
|
||||
dest.qdot = src1.qdot;
|
||||
dest.qdotdot = src1.qdotdot;
|
||||
}
|
||||
|
||||
void Subtract(const JntArrayAcc &src1, const JntArrayAcc &src2, JntArrayAcc &dest)
|
||||
{
|
||||
Subtract(src1.q, src2.q, dest.q);
|
||||
Subtract(src1.qdot, src2.qdot, dest.qdot);
|
||||
Subtract(src1.qdotdot, src2.qdotdot, dest.qdotdot);
|
||||
}
|
||||
void Subtract(const JntArrayAcc &src1, const JntArrayVel &src2, JntArrayAcc &dest)
|
||||
{
|
||||
Subtract(src1.q, src2.q, dest.q);
|
||||
Subtract(src1.qdot, src2.qdot, dest.qdot);
|
||||
dest.qdotdot = src1.qdotdot;
|
||||
}
|
||||
void Subtract(const JntArrayAcc &src1, const JntArray &src2, JntArrayAcc &dest)
|
||||
{
|
||||
Subtract(src1.q, src2, dest.q);
|
||||
dest.qdot = src1.qdot;
|
||||
dest.qdotdot = src1.qdotdot;
|
||||
}
|
||||
|
||||
void Multiply(const JntArrayAcc &src, const double &factor, JntArrayAcc &dest)
|
||||
{
|
||||
Multiply(src.q, factor, dest.q);
|
||||
Multiply(src.qdot, factor, dest.qdot);
|
||||
Multiply(src.qdotdot, factor, dest.qdotdot);
|
||||
}
|
||||
void Multiply(const JntArrayAcc &src, const doubleVel &factor, JntArrayAcc &dest)
|
||||
{
|
||||
Multiply(src.qdot, factor.grad * 2, dest.qdot);
|
||||
Multiply(src.qdotdot, factor.t, dest.qdotdot);
|
||||
Add(dest.qdot, dest.qdotdot, dest.qdotdot);
|
||||
Multiply(src.q, factor.grad, dest.q);
|
||||
Multiply(src.qdot, factor.t, dest.qdot);
|
||||
Add(dest.qdot, dest.q, dest.qdot);
|
||||
Multiply(src.q, factor.t, dest.q);
|
||||
}
|
||||
void Multiply(const JntArrayAcc &src, const doubleAcc &factor, JntArrayAcc &dest)
|
||||
{
|
||||
Multiply(src.q, factor.dd, dest.q);
|
||||
Multiply(src.qdot, factor.d * 2, dest.qdot);
|
||||
Multiply(src.qdotdot, factor.t, dest.qdotdot);
|
||||
Add(dest.qdotdot, dest.qdot, dest.qdotdot);
|
||||
Add(dest.qdotdot, dest.q, dest.qdotdot);
|
||||
Multiply(src.q, factor.d, dest.q);
|
||||
Multiply(src.qdot, factor.t, dest.qdot);
|
||||
Add(dest.qdot, dest.q, dest.qdot);
|
||||
Multiply(src.q, factor.t, dest.q);
|
||||
}
|
||||
|
||||
void Divide(const JntArrayAcc &src, const double &factor, JntArrayAcc &dest)
|
||||
{
|
||||
Divide(src.q, factor, dest.q);
|
||||
Divide(src.qdot, factor, dest.qdot);
|
||||
Divide(src.qdotdot, factor, dest.qdotdot);
|
||||
}
|
||||
void Divide(const JntArrayAcc &src, const doubleVel &factor, JntArrayAcc &dest)
|
||||
{
|
||||
Multiply(src.q, (2 * factor.grad * factor.grad) / (factor.t * factor.t * factor.t), dest.q);
|
||||
Multiply(src.qdot, (2 * factor.grad) / (factor.t * factor.t), dest.qdot);
|
||||
Divide(src.qdotdot, factor.t, dest.qdotdot);
|
||||
Subtract(dest.qdotdot, dest.qdot, dest.qdotdot);
|
||||
Add(dest.qdotdot, dest.q, dest.qdotdot);
|
||||
Multiply(src.q, factor.grad / (factor.t * factor.t), dest.q);
|
||||
Divide(src.qdot, factor.t, dest.qdot);
|
||||
Subtract(dest.qdot, dest.q, dest.qdot);
|
||||
Divide(src.q, factor.t, dest.q);
|
||||
}
|
||||
void Divide(const JntArrayAcc &src, const doubleAcc &factor, JntArrayAcc &dest)
|
||||
{
|
||||
Multiply(src.q,
|
||||
(2 * factor.d * factor.d) / (factor.t * factor.t * factor.t) -
|
||||
factor.dd / (factor.t * factor.t),
|
||||
dest.q);
|
||||
Multiply(src.qdot, (2 * factor.d) / (factor.t * factor.t), dest.qdot);
|
||||
Divide(src.qdotdot, factor.t, dest.qdotdot);
|
||||
Subtract(dest.qdotdot, dest.qdot, dest.qdotdot);
|
||||
Add(dest.qdotdot, dest.q, dest.qdotdot);
|
||||
Multiply(src.q, factor.d / (factor.t * factor.t), dest.q);
|
||||
Divide(src.qdot, factor.t, dest.qdot);
|
||||
Subtract(dest.qdot, dest.q, dest.qdot);
|
||||
Divide(src.q, factor.t, dest.q);
|
||||
}
|
||||
|
||||
void SetToZero(JntArrayAcc &array)
|
||||
{
|
||||
SetToZero(array.q);
|
||||
SetToZero(array.qdot);
|
||||
SetToZero(array.qdotdot);
|
||||
}
|
||||
|
||||
bool Equal(const JntArrayAcc &src1, const JntArrayAcc &src2, double eps)
|
||||
{
|
||||
return (Equal(src1.q, src2.q, eps) && Equal(src1.qdot, src2.qdot, eps) &&
|
||||
Equal(src1.qdotdot, src2.qdotdot, eps));
|
||||
}
|
||||
} // namespace KDL
|
||||
|
||||
@@ -22,45 +22,46 @@
|
||||
#ifndef KDL_JNTARRAYACC_HPP
|
||||
#define KDL_JNTARRAYACC_HPP
|
||||
|
||||
#include "frameacc.hpp"
|
||||
#include "utilities/utility.h"
|
||||
#include "jntarray.hpp"
|
||||
#include "jntarrayvel.hpp"
|
||||
#include "utilities/utility.h"
|
||||
#include "frameacc.hpp"
|
||||
|
||||
namespace KDL {
|
||||
class JntArrayAcc {
|
||||
public:
|
||||
JntArray q;
|
||||
JntArray qdot;
|
||||
JntArray qdotdot;
|
||||
namespace KDL
|
||||
{
|
||||
class JntArrayAcc
|
||||
{
|
||||
public:
|
||||
JntArray q;
|
||||
JntArray qdot;
|
||||
JntArray qdotdot;
|
||||
public:
|
||||
JntArrayAcc(unsigned int size);
|
||||
JntArrayAcc(const JntArray& q,const JntArray& qdot,const JntArray& qdotdot);
|
||||
JntArrayAcc(const JntArray& q,const JntArray& qdot);
|
||||
JntArrayAcc(const JntArray& q);
|
||||
|
||||
public:
|
||||
JntArrayAcc(unsigned int size);
|
||||
JntArrayAcc(const JntArray &q, const JntArray &qdot, const JntArray &qdotdot);
|
||||
JntArrayAcc(const JntArray &q, const JntArray &qdot);
|
||||
JntArrayAcc(const JntArray &q);
|
||||
JntArray value()const;
|
||||
JntArray deriv()const;
|
||||
JntArray dderiv()const;
|
||||
|
||||
JntArray value() const;
|
||||
JntArray deriv() const;
|
||||
JntArray dderiv() const;
|
||||
friend void Add(const JntArrayAcc& src1,const JntArrayAcc& src2,JntArrayAcc& dest);
|
||||
friend void Add(const JntArrayAcc& src1,const JntArrayVel& src2,JntArrayAcc& dest);
|
||||
friend void Add(const JntArrayAcc& src1,const JntArray& src2,JntArrayAcc& dest);
|
||||
friend void Subtract(const JntArrayAcc& src1,const JntArrayAcc& src2,JntArrayAcc& dest);
|
||||
friend void Subtract(const JntArrayAcc& src1,const JntArrayVel& src2,JntArrayAcc& dest);
|
||||
friend void Subtract(const JntArrayAcc& src1,const JntArray& src2,JntArrayAcc& dest);
|
||||
friend void Multiply(const JntArrayAcc& src,const double& factor,JntArrayAcc& dest);
|
||||
friend void Multiply(const JntArrayAcc& src,const doubleVel& factor,JntArrayAcc& dest);
|
||||
friend void Multiply(const JntArrayAcc& src,const doubleAcc& factor,JntArrayAcc& dest);
|
||||
friend void Divide(const JntArrayAcc& src,const double& factor,JntArrayAcc& dest);
|
||||
friend void Divide(const JntArrayAcc& src,const doubleVel& factor,JntArrayAcc& dest);
|
||||
friend void Divide(const JntArrayAcc& src,const doubleAcc& factor,JntArrayAcc& dest);
|
||||
friend void SetToZero(JntArrayAcc& array);
|
||||
friend bool Equal(const JntArrayAcc& src1,const JntArrayAcc& src2,double eps);
|
||||
};
|
||||
|
||||
friend void Add(const JntArrayAcc &src1, const JntArrayAcc &src2, JntArrayAcc &dest);
|
||||
friend void Add(const JntArrayAcc &src1, const JntArrayVel &src2, JntArrayAcc &dest);
|
||||
friend void Add(const JntArrayAcc &src1, const JntArray &src2, JntArrayAcc &dest);
|
||||
friend void Subtract(const JntArrayAcc &src1, const JntArrayAcc &src2, JntArrayAcc &dest);
|
||||
friend void Subtract(const JntArrayAcc &src1, const JntArrayVel &src2, JntArrayAcc &dest);
|
||||
friend void Subtract(const JntArrayAcc &src1, const JntArray &src2, JntArrayAcc &dest);
|
||||
friend void Multiply(const JntArrayAcc &src, const double &factor, JntArrayAcc &dest);
|
||||
friend void Multiply(const JntArrayAcc &src, const doubleVel &factor, JntArrayAcc &dest);
|
||||
friend void Multiply(const JntArrayAcc &src, const doubleAcc &factor, JntArrayAcc &dest);
|
||||
friend void Divide(const JntArrayAcc &src, const double &factor, JntArrayAcc &dest);
|
||||
friend void Divide(const JntArrayAcc &src, const doubleVel &factor, JntArrayAcc &dest);
|
||||
friend void Divide(const JntArrayAcc &src, const doubleAcc &factor, JntArrayAcc &dest);
|
||||
friend void SetToZero(JntArrayAcc &array);
|
||||
friend bool Equal(const JntArrayAcc &src1, const JntArrayAcc &src2, double eps);
|
||||
};
|
||||
|
||||
bool Equal(const JntArrayAcc &, const JntArrayAcc &, double = epsilon);
|
||||
} // namespace KDL
|
||||
bool Equal(const JntArrayAcc&, const JntArrayAcc&, double = epsilon);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,82 +22,93 @@
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
#include "jntarrayacc.hpp"
|
||||
|
||||
namespace KDL {
|
||||
JntArrayVel::JntArrayVel(unsigned int size) : q(size), qdot(size) {}
|
||||
JntArrayVel::JntArrayVel(const JntArray &qin, const JntArray &qdotin) : q(qin), qdot(qdotin)
|
||||
namespace KDL
|
||||
{
|
||||
assert(q.rows() == qdot.rows());
|
||||
}
|
||||
JntArrayVel::JntArrayVel(const JntArray &qin) : q(qin), qdot(q.rows()) {}
|
||||
JntArrayVel::JntArrayVel(unsigned int size):
|
||||
q(size),qdot(size)
|
||||
{
|
||||
}
|
||||
JntArrayVel::JntArrayVel(const JntArray& qin, const JntArray& qdotin):
|
||||
q(qin),qdot(qdotin)
|
||||
{
|
||||
assert(q.rows()==qdot.rows());
|
||||
}
|
||||
JntArrayVel::JntArrayVel(const JntArray& qin):
|
||||
q(qin),qdot(q.rows())
|
||||
{
|
||||
}
|
||||
|
||||
JntArray JntArrayVel::value() const
|
||||
{
|
||||
return q;
|
||||
JntArray JntArrayVel::value()const
|
||||
{
|
||||
return q;
|
||||
}
|
||||
|
||||
JntArray JntArrayVel::deriv()const
|
||||
{
|
||||
return qdot;
|
||||
}
|
||||
|
||||
void Add(const JntArrayVel& src1,const JntArrayVel& src2,JntArrayVel& dest)
|
||||
{
|
||||
Add(src1.q,src2.q,dest.q);
|
||||
Add(src1.qdot,src2.qdot,dest.qdot);
|
||||
}
|
||||
void Add(const JntArrayVel& src1,const JntArray& src2,JntArrayVel& dest)
|
||||
{
|
||||
Add(src1.q,src2,dest.q);
|
||||
dest.qdot=src1.qdot;
|
||||
}
|
||||
|
||||
void Subtract(const JntArrayVel& src1,const JntArrayVel& src2,JntArrayVel& dest)
|
||||
{
|
||||
Subtract(src1.q,src2.q,dest.q);
|
||||
Subtract(src1.qdot,src2.qdot,dest.qdot);
|
||||
}
|
||||
void Subtract(const JntArrayVel& src1,const JntArray& src2,JntArrayVel& dest)
|
||||
{
|
||||
Subtract(src1.q,src2,dest.q);
|
||||
dest.qdot=src1.qdot;
|
||||
}
|
||||
|
||||
void Multiply(const JntArrayVel& src,const double& factor,JntArrayVel& dest)
|
||||
{
|
||||
Multiply(src.q,factor,dest.q);
|
||||
Multiply(src.qdot,factor,dest.qdot);
|
||||
}
|
||||
void Multiply(const JntArrayVel& src,const doubleVel& factor,JntArrayVel& dest)
|
||||
{
|
||||
Multiply(src.q,factor.grad,dest.q);
|
||||
Multiply(src.qdot,factor.t,dest.qdot);
|
||||
Add(dest.qdot,dest.q,dest.qdot);
|
||||
Multiply(src.q,factor.t,dest.q);
|
||||
}
|
||||
|
||||
void Divide(const JntArrayVel& src,const double& factor,JntArrayVel& dest)
|
||||
{
|
||||
Divide(src.q,factor,dest.q);
|
||||
Divide(src.qdot,factor,dest.qdot);
|
||||
}
|
||||
void Divide(const JntArrayVel& src,const doubleVel& factor,JntArrayVel& dest)
|
||||
{
|
||||
Multiply(src.q,(factor.grad/factor.t/factor.t),dest.q);
|
||||
Divide(src.qdot,factor.t,dest.qdot);
|
||||
Subtract(dest.qdot,dest.q,dest.qdot);
|
||||
Divide(src.q,factor.t,dest.q);
|
||||
}
|
||||
|
||||
void SetToZero(JntArrayVel& array)
|
||||
{
|
||||
SetToZero(array.q);
|
||||
SetToZero(array.qdot);
|
||||
}
|
||||
|
||||
bool Equal(const JntArrayVel& src1,const JntArrayVel& src2,double eps)
|
||||
{
|
||||
return Equal(src1.q,src2.q,eps)&&Equal(src1.qdot,src2.qdot,eps);
|
||||
}
|
||||
}
|
||||
|
||||
JntArray JntArrayVel::deriv() const
|
||||
{
|
||||
return qdot;
|
||||
}
|
||||
|
||||
void Add(const JntArrayVel &src1, const JntArrayVel &src2, JntArrayVel &dest)
|
||||
{
|
||||
Add(src1.q, src2.q, dest.q);
|
||||
Add(src1.qdot, src2.qdot, dest.qdot);
|
||||
}
|
||||
void Add(const JntArrayVel &src1, const JntArray &src2, JntArrayVel &dest)
|
||||
{
|
||||
Add(src1.q, src2, dest.q);
|
||||
dest.qdot = src1.qdot;
|
||||
}
|
||||
|
||||
void Subtract(const JntArrayVel &src1, const JntArrayVel &src2, JntArrayVel &dest)
|
||||
{
|
||||
Subtract(src1.q, src2.q, dest.q);
|
||||
Subtract(src1.qdot, src2.qdot, dest.qdot);
|
||||
}
|
||||
void Subtract(const JntArrayVel &src1, const JntArray &src2, JntArrayVel &dest)
|
||||
{
|
||||
Subtract(src1.q, src2, dest.q);
|
||||
dest.qdot = src1.qdot;
|
||||
}
|
||||
|
||||
void Multiply(const JntArrayVel &src, const double &factor, JntArrayVel &dest)
|
||||
{
|
||||
Multiply(src.q, factor, dest.q);
|
||||
Multiply(src.qdot, factor, dest.qdot);
|
||||
}
|
||||
void Multiply(const JntArrayVel &src, const doubleVel &factor, JntArrayVel &dest)
|
||||
{
|
||||
Multiply(src.q, factor.grad, dest.q);
|
||||
Multiply(src.qdot, factor.t, dest.qdot);
|
||||
Add(dest.qdot, dest.q, dest.qdot);
|
||||
Multiply(src.q, factor.t, dest.q);
|
||||
}
|
||||
|
||||
void Divide(const JntArrayVel &src, const double &factor, JntArrayVel &dest)
|
||||
{
|
||||
Divide(src.q, factor, dest.q);
|
||||
Divide(src.qdot, factor, dest.qdot);
|
||||
}
|
||||
void Divide(const JntArrayVel &src, const doubleVel &factor, JntArrayVel &dest)
|
||||
{
|
||||
Multiply(src.q, (factor.grad / factor.t / factor.t), dest.q);
|
||||
Divide(src.qdot, factor.t, dest.qdot);
|
||||
Subtract(dest.qdot, dest.q, dest.qdot);
|
||||
Divide(src.q, factor.t, dest.q);
|
||||
}
|
||||
|
||||
void SetToZero(JntArrayVel &array)
|
||||
{
|
||||
SetToZero(array.q);
|
||||
SetToZero(array.qdot);
|
||||
}
|
||||
|
||||
bool Equal(const JntArrayVel &src1, const JntArrayVel &src2, double eps)
|
||||
{
|
||||
return Equal(src1.q, src2.q, eps) && Equal(src1.qdot, src2.qdot, eps);
|
||||
}
|
||||
} // namespace KDL
|
||||
|
||||
@@ -22,38 +22,39 @@
|
||||
#ifndef KDL_JNTARRAYVEL_HPP
|
||||
#define KDL_JNTARRAYVEL_HPP
|
||||
|
||||
#include "framevel.hpp"
|
||||
#include "jntarray.hpp"
|
||||
#include "utilities/utility.h"
|
||||
#include "jntarray.hpp"
|
||||
#include "framevel.hpp"
|
||||
|
||||
namespace KDL {
|
||||
namespace KDL
|
||||
{
|
||||
|
||||
class JntArrayVel {
|
||||
public:
|
||||
JntArray q;
|
||||
JntArray qdot;
|
||||
class JntArrayVel
|
||||
{
|
||||
public:
|
||||
JntArray q;
|
||||
JntArray qdot;
|
||||
public:
|
||||
JntArrayVel(unsigned int size);
|
||||
JntArrayVel(const JntArray& q,const JntArray& qdot);
|
||||
JntArrayVel(const JntArray& q);
|
||||
|
||||
public:
|
||||
JntArrayVel(unsigned int size);
|
||||
JntArrayVel(const JntArray &q, const JntArray &qdot);
|
||||
JntArrayVel(const JntArray &q);
|
||||
JntArray value()const;
|
||||
JntArray deriv()const;
|
||||
|
||||
JntArray value() const;
|
||||
JntArray deriv() const;
|
||||
friend void Add(const JntArrayVel& src1,const JntArrayVel& src2,JntArrayVel& dest);
|
||||
friend void Add(const JntArrayVel& src1,const JntArray& src2,JntArrayVel& dest);
|
||||
friend void Subtract(const JntArrayVel& src1,const JntArrayVel& src2,JntArrayVel& dest);
|
||||
friend void Subtract(const JntArrayVel& src1,const JntArray& src2,JntArrayVel& dest);
|
||||
friend void Multiply(const JntArrayVel& src,const double& factor,JntArrayVel& dest);
|
||||
friend void Multiply(const JntArrayVel& src,const doubleVel& factor,JntArrayVel& dest);
|
||||
friend void Divide(const JntArrayVel& src,const double& factor,JntArrayVel& dest);
|
||||
friend void Divide(const JntArrayVel& src,const doubleVel& factor,JntArrayVel& dest);
|
||||
friend void SetToZero(JntArrayVel& array);
|
||||
friend bool Equal(const JntArrayVel& src1,const JntArrayVel& src2,double eps);
|
||||
};
|
||||
|
||||
friend void Add(const JntArrayVel &src1, const JntArrayVel &src2, JntArrayVel &dest);
|
||||
friend void Add(const JntArrayVel &src1, const JntArray &src2, JntArrayVel &dest);
|
||||
friend void Subtract(const JntArrayVel &src1, const JntArrayVel &src2, JntArrayVel &dest);
|
||||
friend void Subtract(const JntArrayVel &src1, const JntArray &src2, JntArrayVel &dest);
|
||||
friend void Multiply(const JntArrayVel &src, const double &factor, JntArrayVel &dest);
|
||||
friend void Multiply(const JntArrayVel &src, const doubleVel &factor, JntArrayVel &dest);
|
||||
friend void Divide(const JntArrayVel &src, const double &factor, JntArrayVel &dest);
|
||||
friend void Divide(const JntArrayVel &src, const doubleVel &factor, JntArrayVel &dest);
|
||||
friend void SetToZero(JntArrayVel &array);
|
||||
friend bool Equal(const JntArrayVel &src1, const JntArrayVel &src2, double eps);
|
||||
};
|
||||
|
||||
bool Equal(const JntArrayVel &, const JntArrayVel &, double = epsilon);
|
||||
} // namespace KDL
|
||||
bool Equal(const JntArrayVel&, const JntArrayVel&, double = epsilon);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,149 +26,139 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
Joint::Joint(const JointType &_type,
|
||||
const double &_scale,
|
||||
const double &_offset,
|
||||
const double &_inertia,
|
||||
const double &_damping,
|
||||
const double &_stiffness)
|
||||
: type(_type),
|
||||
scale(_scale),
|
||||
offset(_offset),
|
||||
inertia(_inertia),
|
||||
damping(_damping),
|
||||
stiffness(_stiffness)
|
||||
{
|
||||
// for sphere and swing, offset is not used, assume no offset
|
||||
}
|
||||
Joint::Joint(const JointType& _type, const double& _scale, const double& _offset,
|
||||
const double& _inertia, const double& _damping, const double& _stiffness):
|
||||
type(_type),scale(_scale),offset(_offset),inertia(_inertia),damping(_damping),stiffness(_stiffness)
|
||||
{
|
||||
// for sphere and swing, offset is not used, assume no offset
|
||||
}
|
||||
|
||||
Joint::Joint(const Joint &in)
|
||||
: type(in.type),
|
||||
scale(in.scale),
|
||||
offset(in.offset),
|
||||
inertia(in.inertia),
|
||||
damping(in.damping),
|
||||
stiffness(in.stiffness)
|
||||
{
|
||||
}
|
||||
Joint::Joint(const Joint& in):
|
||||
type(in.type),scale(in.scale),offset(in.offset),
|
||||
inertia(in.inertia),damping(in.damping),stiffness(in.stiffness)
|
||||
{
|
||||
}
|
||||
|
||||
Joint &Joint::operator=(const Joint &in)
|
||||
{
|
||||
type = in.type;
|
||||
scale = in.scale;
|
||||
offset = in.offset;
|
||||
inertia = in.inertia;
|
||||
damping = in.damping;
|
||||
stiffness = in.stiffness;
|
||||
return *this;
|
||||
}
|
||||
Joint& Joint::operator=(const Joint& in)
|
||||
{
|
||||
type=in.type;
|
||||
scale=in.scale;
|
||||
offset=in.offset;
|
||||
inertia=in.inertia;
|
||||
damping=in.damping;
|
||||
stiffness=in.stiffness;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Joint::~Joint() {}
|
||||
|
||||
Frame Joint::pose(const double *q) const
|
||||
{
|
||||
Joint::~Joint()
|
||||
{
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case RotX:
|
||||
assert(q);
|
||||
return Frame(Rotation::RotX(scale * q[0] + offset));
|
||||
break;
|
||||
case RotY:
|
||||
assert(q);
|
||||
return Frame(Rotation::RotY(scale * q[0] + offset));
|
||||
break;
|
||||
case RotZ:
|
||||
assert(q);
|
||||
return Frame(Rotation::RotZ(scale * q[0] + offset));
|
||||
break;
|
||||
case TransX:
|
||||
assert(q);
|
||||
return Frame(Vector(scale * q[0] + offset, 0.0, 0.0));
|
||||
break;
|
||||
case TransY:
|
||||
assert(q);
|
||||
return Frame(Vector(0.0, scale * q[0] + offset, 0.0));
|
||||
break;
|
||||
case TransZ:
|
||||
assert(q);
|
||||
return Frame(Vector(0.0, 0.0, scale * q[0] + offset));
|
||||
break;
|
||||
case Sphere:
|
||||
// the joint angles represent a rotation vector expressed in the base frame of the joint
|
||||
// (= the frame you get when there is no offset nor rotation)
|
||||
assert(q);
|
||||
return Frame(Rot(Vector(q[0], q[1], q[2])));
|
||||
break;
|
||||
case Swing:
|
||||
// the joint angles represent a 2D rotation vector in the XZ planee of the base frame of the
|
||||
// joint
|
||||
// (= the frame you get when there is no offset nor rotation)
|
||||
assert(q);
|
||||
return Frame(Rot(Vector(q[0], 0.0, q[1])));
|
||||
break;
|
||||
default:
|
||||
return Frame::Identity();
|
||||
break;
|
||||
}
|
||||
}
|
||||
Frame Joint::pose(const double* q)const
|
||||
{
|
||||
|
||||
Twist Joint::twist(const double &qdot, int dof) const
|
||||
{
|
||||
switch (type) {
|
||||
case RotX:
|
||||
return Twist(Vector(0.0, 0.0, 0.0), Vector(scale * qdot, 0.0, 0.0));
|
||||
break;
|
||||
case RotY:
|
||||
return Twist(Vector(0.0, 0.0, 0.0), Vector(0.0, scale * qdot, 0.0));
|
||||
break;
|
||||
case RotZ:
|
||||
return Twist(Vector(0.0, 0.0, 0.0), Vector(0.0, 0.0, scale * qdot));
|
||||
break;
|
||||
case TransX:
|
||||
return Twist(Vector(scale * qdot, 0.0, 0.0), Vector(0.0, 0.0, 0.0));
|
||||
break;
|
||||
case TransY:
|
||||
return Twist(Vector(0.0, scale * qdot, 0.0), Vector(0.0, 0.0, 0.0));
|
||||
break;
|
||||
case TransZ:
|
||||
return Twist(Vector(0.0, 0.0, scale * qdot), Vector(0.0, 0.0, 0.0));
|
||||
break;
|
||||
case Swing:
|
||||
switch (dof) {
|
||||
case 0:
|
||||
return Twist(Vector(0.0, 0.0, 0.0), Vector(scale * qdot, 0.0, 0.0));
|
||||
case 1:
|
||||
return Twist(Vector(0.0, 0.0, 0.0), Vector(0.0, 0.0, scale * qdot));
|
||||
}
|
||||
return Twist::Zero();
|
||||
case Sphere:
|
||||
switch (dof) {
|
||||
case 0:
|
||||
return Twist(Vector(0.0, 0.0, 0.0), Vector(scale * qdot, 0.0, 0.0));
|
||||
case 1:
|
||||
return Twist(Vector(0.0, 0.0, 0.0), Vector(0.0, scale * qdot, 0.0));
|
||||
case 2:
|
||||
return Twist(Vector(0.0, 0.0, 0.0), Vector(0.0, 0.0, scale * qdot));
|
||||
}
|
||||
return Twist::Zero();
|
||||
default:
|
||||
return Twist::Zero();
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch(type){
|
||||
case RotX:
|
||||
assert(q);
|
||||
return Frame(Rotation::RotX(scale*q[0]+offset));
|
||||
break;
|
||||
case RotY:
|
||||
assert(q);
|
||||
return Frame(Rotation::RotY(scale*q[0]+offset));
|
||||
break;
|
||||
case RotZ:
|
||||
assert(q);
|
||||
return Frame(Rotation::RotZ(scale*q[0]+offset));
|
||||
break;
|
||||
case TransX:
|
||||
assert(q);
|
||||
return Frame(Vector(scale*q[0]+offset,0.0,0.0));
|
||||
break;
|
||||
case TransY:
|
||||
assert(q);
|
||||
return Frame(Vector(0.0,scale*q[0]+offset,0.0));
|
||||
break;
|
||||
case TransZ:
|
||||
assert(q);
|
||||
return Frame(Vector(0.0,0.0,scale*q[0]+offset));
|
||||
break;
|
||||
case Sphere:
|
||||
// the joint angles represent a rotation vector expressed in the base frame of the joint
|
||||
// (= the frame you get when there is no offset nor rotation)
|
||||
assert(q);
|
||||
return Frame(Rot(Vector(q[0], q[1], q[2])));
|
||||
break;
|
||||
case Swing:
|
||||
// the joint angles represent a 2D rotation vector in the XZ planee of the base frame of the joint
|
||||
// (= the frame you get when there is no offset nor rotation)
|
||||
assert(q);
|
||||
return Frame(Rot(Vector(q[0], 0.0, q[1])));
|
||||
break;
|
||||
default:
|
||||
return Frame::Identity();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Joint::getNDof() const
|
||||
{
|
||||
switch (type) {
|
||||
case Sphere:
|
||||
return 3;
|
||||
case Swing:
|
||||
return 2;
|
||||
case None:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
Twist Joint::twist(const double& qdot, int dof)const
|
||||
{
|
||||
switch(type){
|
||||
case RotX:
|
||||
return Twist(Vector(0.0,0.0,0.0),Vector(scale*qdot,0.0,0.0));
|
||||
break;
|
||||
case RotY:
|
||||
return Twist(Vector(0.0,0.0,0.0),Vector(0.0,scale*qdot,0.0));
|
||||
break;
|
||||
case RotZ:
|
||||
return Twist(Vector(0.0,0.0,0.0),Vector(0.0,0.0,scale*qdot));
|
||||
break;
|
||||
case TransX:
|
||||
return Twist(Vector(scale*qdot,0.0,0.0),Vector(0.0,0.0,0.0));
|
||||
break;
|
||||
case TransY:
|
||||
return Twist(Vector(0.0,scale*qdot,0.0),Vector(0.0,0.0,0.0));
|
||||
break;
|
||||
case TransZ:
|
||||
return Twist(Vector(0.0,0.0,scale*qdot),Vector(0.0,0.0,0.0));
|
||||
break;
|
||||
case Swing:
|
||||
switch (dof) {
|
||||
case 0:
|
||||
return Twist(Vector(0.0,0.0,0.0),Vector(scale*qdot,0.0,0.0));
|
||||
case 1:
|
||||
return Twist(Vector(0.0,0.0,0.0),Vector(0.0,0.0,scale*qdot));
|
||||
}
|
||||
return Twist::Zero();
|
||||
case Sphere:
|
||||
switch (dof) {
|
||||
case 0:
|
||||
return Twist(Vector(0.0,0.0,0.0),Vector(scale*qdot,0.0,0.0));
|
||||
case 1:
|
||||
return Twist(Vector(0.0,0.0,0.0),Vector(0.0,scale*qdot,0.0));
|
||||
case 2:
|
||||
return Twist(Vector(0.0,0.0,0.0),Vector(0.0,0.0,scale*qdot));
|
||||
}
|
||||
return Twist::Zero();
|
||||
default:
|
||||
return Twist::Zero();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Joint::getNDof() const
|
||||
{
|
||||
switch (type) {
|
||||
case Sphere:
|
||||
return 3;
|
||||
case Swing:
|
||||
return 2;
|
||||
case None:
|
||||
return 0;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
} // end of namespace KDL
|
||||
|
||||
} // end of namespace KDL
|
||||
|
||||
@@ -27,116 +27,112 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/**
|
||||
* \brief This class encapsulates a simple joint, that is with one
|
||||
* parameterized degree of freedom and with scalar dynamic properties.
|
||||
*
|
||||
* A simple joint is described by the following properties :
|
||||
* - scale: ratio between motion input and motion output
|
||||
* - offset: between the "physical" and the "logical" zero position.
|
||||
* - type: revolute or translational, along one of the basic frame axes
|
||||
* - inertia, stiffness and damping: scalars representing the physical
|
||||
* effects along/about the joint axis only.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class Joint {
|
||||
public:
|
||||
typedef enum { RotX, RotY, RotZ, TransX, TransY, TransZ, Sphere, Swing, None } JointType;
|
||||
/**
|
||||
* Constructor of a joint.
|
||||
*
|
||||
* @param type type of the joint, default: Joint::None
|
||||
* @param scale scale between joint input and actual geometric
|
||||
* movement, default: 1
|
||||
* @param offset offset between joint input and actual
|
||||
* geometric input, default: 0
|
||||
* @param inertia 1D inertia along the joint axis, default: 0
|
||||
* @param damping 1D damping along the joint axis, default: 0
|
||||
* @param stiffness 1D stiffness along the joint axis,
|
||||
* default: 0
|
||||
*/
|
||||
Joint(const JointType &type = None,
|
||||
const double &scale = 1,
|
||||
const double &offset = 0,
|
||||
const double &inertia = 0,
|
||||
const double &damping = 0,
|
||||
const double &stiffness = 0);
|
||||
Joint(const Joint &in);
|
||||
/**
|
||||
* \brief This class encapsulates a simple joint, that is with one
|
||||
* parameterized degree of freedom and with scalar dynamic properties.
|
||||
*
|
||||
* A simple joint is described by the following properties :
|
||||
* - scale: ratio between motion input and motion output
|
||||
* - offset: between the "physical" and the "logical" zero position.
|
||||
* - type: revolute or translational, along one of the basic frame axes
|
||||
* - inertia, stiffness and damping: scalars representing the physical
|
||||
* effects along/about the joint axis only.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class Joint {
|
||||
public:
|
||||
typedef enum { RotX,RotY,RotZ,TransX,TransY,TransZ,Sphere,Swing,None} JointType;
|
||||
/**
|
||||
* Constructor of a joint.
|
||||
*
|
||||
* @param type type of the joint, default: Joint::None
|
||||
* @param scale scale between joint input and actual geometric
|
||||
* movement, default: 1
|
||||
* @param offset offset between joint input and actual
|
||||
* geometric input, default: 0
|
||||
* @param inertia 1D inertia along the joint axis, default: 0
|
||||
* @param damping 1D damping along the joint axis, default: 0
|
||||
* @param stiffness 1D stiffness along the joint axis,
|
||||
* default: 0
|
||||
*/
|
||||
Joint(const JointType& type=None,const double& scale=1,const double& offset=0,
|
||||
const double& inertia=0,const double& damping=0,const double& stiffness=0);
|
||||
Joint(const Joint& in);
|
||||
|
||||
Joint &operator=(const Joint &arg);
|
||||
Joint& operator=(const Joint& arg);
|
||||
|
||||
/**
|
||||
* Request the 6D-pose between the beginning and the end of
|
||||
* the joint at joint position q
|
||||
*
|
||||
* @param q the 1D joint position
|
||||
*
|
||||
* @return the resulting 6D-pose
|
||||
*/
|
||||
Frame pose(const double *q) const;
|
||||
/**
|
||||
* Request the resulting 6D-velocity with a joint velocity qdot
|
||||
*
|
||||
* @param qdot the 1D joint velocity
|
||||
*
|
||||
* @return the resulting 6D-velocity
|
||||
*/
|
||||
Twist twist(const double &qdot, int dof = 0) const;
|
||||
/**
|
||||
* Request the 6D-pose between the beginning and the end of
|
||||
* the joint at joint position q
|
||||
*
|
||||
* @param q the 1D joint position
|
||||
*
|
||||
* @return the resulting 6D-pose
|
||||
*/
|
||||
Frame pose(const double* q)const;
|
||||
/**
|
||||
* Request the resulting 6D-velocity with a joint velocity qdot
|
||||
*
|
||||
* @param qdot the 1D joint velocity
|
||||
*
|
||||
* @return the resulting 6D-velocity
|
||||
*/
|
||||
Twist twist(const double& qdot, int dof=0)const;
|
||||
|
||||
/**
|
||||
* Request the type of the joint.
|
||||
*
|
||||
* @return const reference to the type
|
||||
*/
|
||||
const JointType &getType() const
|
||||
{
|
||||
return type;
|
||||
};
|
||||
/**
|
||||
* Request the type of the joint.
|
||||
*
|
||||
* @return const reference to the type
|
||||
*/
|
||||
const JointType& getType() const
|
||||
{
|
||||
return type;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request the stringified type of the joint.
|
||||
*
|
||||
* @return const string
|
||||
*/
|
||||
const std::string getTypeName() const
|
||||
{
|
||||
switch (type) {
|
||||
case RotX:
|
||||
return "RotX";
|
||||
case RotY:
|
||||
return "RotY";
|
||||
case RotZ:
|
||||
return "RotZ";
|
||||
case TransX:
|
||||
return "TransX";
|
||||
case TransY:
|
||||
return "TransY";
|
||||
case TransZ:
|
||||
return "TransZ";
|
||||
case Sphere:
|
||||
return "Sphere";
|
||||
case Swing:
|
||||
return "Swing";
|
||||
case None:
|
||||
return "None";
|
||||
default:
|
||||
return "None";
|
||||
}
|
||||
};
|
||||
unsigned int getNDof() const;
|
||||
/**
|
||||
* Request the stringified type of the joint.
|
||||
*
|
||||
* @return const string
|
||||
*/
|
||||
const std::string getTypeName() const
|
||||
{
|
||||
switch (type) {
|
||||
case RotX:
|
||||
return "RotX";
|
||||
case RotY:
|
||||
return "RotY";
|
||||
case RotZ:
|
||||
return "RotZ";
|
||||
case TransX:
|
||||
return "TransX";
|
||||
case TransY:
|
||||
return "TransY";
|
||||
case TransZ:
|
||||
return "TransZ";
|
||||
case Sphere:
|
||||
return "Sphere";
|
||||
case Swing:
|
||||
return "Swing";
|
||||
case None:
|
||||
return "None";
|
||||
default:
|
||||
return "None";
|
||||
}
|
||||
};
|
||||
unsigned int getNDof() const;
|
||||
|
||||
virtual ~Joint();
|
||||
virtual ~Joint();
|
||||
|
||||
private:
|
||||
Joint::JointType type;
|
||||
double scale;
|
||||
double offset;
|
||||
double inertia;
|
||||
double damping;
|
||||
double stiffness;
|
||||
};
|
||||
private:
|
||||
Joint::JointType type;
|
||||
double scale;
|
||||
double offset;
|
||||
double inertia;
|
||||
double damping;
|
||||
double stiffness;
|
||||
};
|
||||
|
||||
} // end of namespace KDL
|
||||
} // end of namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,92 +26,79 @@
|
||||
#include "frames_io.hpp"
|
||||
|
||||
namespace KDL {
|
||||
std::ostream &operator<<(std::ostream &os, const Joint &joint)
|
||||
{
|
||||
return os << joint.getTypeName();
|
||||
std::ostream& operator <<(std::ostream& os, const Joint& joint) {
|
||||
return os << joint.getTypeName();
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Joint &joint)
|
||||
{
|
||||
return is;
|
||||
std::istream& operator >>(std::istream& is, Joint& joint) {
|
||||
return is;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Segment &segment)
|
||||
{
|
||||
os << "[" << segment.getJoint() << ",\n" << segment.getFrameToTip() << "]";
|
||||
return os;
|
||||
std::ostream& operator <<(std::ostream& os, const Segment& segment) {
|
||||
os << "[" << segment.getJoint() << ",\n" << segment.getFrameToTip() << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Segment &segment)
|
||||
{
|
||||
return is;
|
||||
std::istream& operator >>(std::istream& is, Segment& segment) {
|
||||
return is;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Chain &chain)
|
||||
{
|
||||
os << "[";
|
||||
for (unsigned int i = 0; i < chain.getNrOfSegments(); i++)
|
||||
os << chain.getSegment(i) << "\n";
|
||||
os << "]";
|
||||
return os;
|
||||
std::ostream& operator <<(std::ostream& os, const Chain& chain) {
|
||||
os << "[";
|
||||
for (unsigned int i = 0; i < chain.getNrOfSegments(); i++)
|
||||
os << chain.getSegment(i) << "\n";
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Chain &chain)
|
||||
{
|
||||
return is;
|
||||
std::istream& operator >>(std::istream& is, Chain& chain) {
|
||||
return is;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Tree &tree)
|
||||
{
|
||||
SegmentMap::const_iterator root = tree.getSegment("root");
|
||||
return os << root;
|
||||
std::ostream& operator <<(std::ostream& os, const Tree& tree) {
|
||||
SegmentMap::const_iterator root = tree.getSegment("root");
|
||||
return os << root;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, SegmentMap::const_iterator root)
|
||||
{
|
||||
// os<<root->first<<": "<<root->second.segment<<"\n";
|
||||
os << root->first << "(q_nr: " << root->second.q_nr << ")"
|
||||
<< "\n \t";
|
||||
for (unsigned int i = 0; i < root->second.children.size(); i++) {
|
||||
os << (root->second.children[i]) << "\t";
|
||||
}
|
||||
return os << "\n";
|
||||
std::ostream& operator <<(std::ostream& os, SegmentMap::const_iterator root) {
|
||||
//os<<root->first<<": "<<root->second.segment<<"\n";
|
||||
os << root->first<<"(q_nr: "<<root->second.q_nr<<")"<<"\n \t";
|
||||
for (unsigned int i = 0; i < root->second.children.size(); i++) {
|
||||
os <<(root->second.children[i])<<"\t";
|
||||
}
|
||||
return os << "\n";
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Tree &tree)
|
||||
{
|
||||
return is;
|
||||
std::istream& operator >>(std::istream& is, Tree& tree) {
|
||||
return is;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const JntArray &array)
|
||||
{
|
||||
os << "[";
|
||||
for (unsigned int i = 0; i < array.rows(); i++)
|
||||
os << std::setw(KDL_FRAME_WIDTH) << array[i];
|
||||
os << "]";
|
||||
return os;
|
||||
std::ostream& operator <<(std::ostream& os, const JntArray& array) {
|
||||
os << "[";
|
||||
for (unsigned int i = 0; i < array.rows(); i++)
|
||||
os << std::setw(KDL_FRAME_WIDTH) << array[i];
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, JntArray &array)
|
||||
{
|
||||
return is;
|
||||
std::istream& operator >>(std::istream& is, JntArray& array) {
|
||||
return is;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Jacobian &jac)
|
||||
{
|
||||
os << "[";
|
||||
for (unsigned int i = 0; i < jac.rows(); i++) {
|
||||
for (unsigned int j = 0; j < jac.columns(); j++)
|
||||
os << std::setw(KDL_FRAME_WIDTH) << jac(i, j);
|
||||
os << std::endl;
|
||||
}
|
||||
os << "]";
|
||||
return os;
|
||||
std::ostream& operator <<(std::ostream& os, const Jacobian& jac) {
|
||||
os << "[";
|
||||
for (unsigned int i = 0; i < jac.rows(); i++) {
|
||||
for (unsigned int j = 0; j < jac.columns(); j++)
|
||||
os << std::setw(KDL_FRAME_WIDTH) << jac(i, j);
|
||||
os << std::endl;
|
||||
}
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
|
||||
std::istream& operator >>(std::istream& is, Jacobian& jac) {
|
||||
return is;
|
||||
}
|
||||
|
||||
std::istream &operator>>(std::istream &is, Jacobian &jac)
|
||||
{
|
||||
return is;
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
@@ -22,46 +22,49 @@
|
||||
#ifndef KDL_KINFAM_IO_HPP
|
||||
#define KDL_KINFAM_IO_HPP
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "chain.hpp"
|
||||
#include "jacobian.hpp"
|
||||
#include "jntarray.hpp"
|
||||
#include "joint.hpp"
|
||||
#include "segment.hpp"
|
||||
#include "chain.hpp"
|
||||
#include "jntarray.hpp"
|
||||
#include "jacobian.hpp"
|
||||
#include "tree.hpp"
|
||||
|
||||
namespace KDL {
|
||||
std::ostream &operator<<(std::ostream &os, const Joint &joint);
|
||||
std::istream &operator>>(std::istream &is, Joint &joint);
|
||||
std::ostream &operator<<(std::ostream &os, const Segment &segment);
|
||||
std::istream &operator>>(std::istream &is, Segment &segment);
|
||||
std::ostream &operator<<(std::ostream &os, const Chain &chain);
|
||||
std::istream &operator>>(std::istream &is, Chain &chain);
|
||||
std::ostream& operator <<(std::ostream& os, const Joint& joint);
|
||||
std::istream& operator >>(std::istream& is, Joint& joint);
|
||||
std::ostream& operator <<(std::ostream& os, const Segment& segment);
|
||||
std::istream& operator >>(std::istream& is, Segment& segment);
|
||||
std::ostream& operator <<(std::ostream& os, const Chain& chain);
|
||||
std::istream& operator >>(std::istream& is, Chain& chain);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Tree &tree);
|
||||
std::istream &operator>>(std::istream &is, Tree &tree);
|
||||
std::ostream& operator <<(std::ostream& os, const Tree& tree);
|
||||
std::istream& operator >>(std::istream& is, Tree& tree);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, SegmentMap::const_iterator it);
|
||||
std::ostream& operator <<(std::ostream& os, SegmentMap::const_iterator it);
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const JntArray &array);
|
||||
std::istream &operator>>(std::istream &is, JntArray &array);
|
||||
std::ostream &operator<<(std::ostream &os, const Jacobian &jac);
|
||||
std::istream &operator>>(std::istream &is, Jacobian &jac);
|
||||
std::ostream& operator <<(std::ostream& os, const JntArray& array);
|
||||
std::istream& operator >>(std::istream& is, JntArray& array);
|
||||
std::ostream& operator <<(std::ostream& os, const Jacobian& jac);
|
||||
std::istream& operator >>(std::istream& is, Jacobian& jac);
|
||||
|
||||
template<typename T> std::ostream &operator<<(std::ostream &os, const std::vector<T> &vec)
|
||||
{
|
||||
os << "[";
|
||||
for (unsigned int i = 0; i < vec.size(); i++)
|
||||
os << vec[i] << " ";
|
||||
os << "]";
|
||||
return os;
|
||||
};
|
||||
template<typename T>
|
||||
std::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {
|
||||
os << "[";
|
||||
for (unsigned int i = 0; i < vec.size(); i++)
|
||||
os << vec[i] << " ";
|
||||
os << "]";
|
||||
return os;
|
||||
}
|
||||
;
|
||||
|
||||
template<typename T> std::istream &operator>>(std::istream &is, std::vector<T> &vec)
|
||||
{
|
||||
return is;
|
||||
};
|
||||
} // namespace KDL
|
||||
template<typename T>
|
||||
std::istream& operator >>(std::istream& is, std::vector<T>& vec) {
|
||||
return is;
|
||||
}
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -24,40 +24,48 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
Segment::Segment(const Joint &_joint, const Frame &_f_tip, const Inertia &_M)
|
||||
: M(_M), joint(_joint), f_tip(_f_tip)
|
||||
{
|
||||
}
|
||||
Segment::Segment(const Joint& _joint, const Frame& _f_tip, const Inertia& _M):
|
||||
M(_M),joint(_joint),
|
||||
f_tip(_f_tip)
|
||||
{
|
||||
}
|
||||
|
||||
Segment::Segment(const Segment &in) : M(in.M), joint(in.joint), f_tip(in.f_tip) {}
|
||||
Segment::Segment(const Segment& in):
|
||||
M(in.M),joint(in.joint),
|
||||
f_tip(in.f_tip)
|
||||
{
|
||||
}
|
||||
|
||||
Segment &Segment::operator=(const Segment &arg)
|
||||
{
|
||||
joint = arg.joint;
|
||||
M = arg.M;
|
||||
f_tip = arg.f_tip;
|
||||
return *this;
|
||||
}
|
||||
Segment& Segment::operator=(const Segment& arg)
|
||||
{
|
||||
joint=arg.joint;
|
||||
M=arg.M;
|
||||
f_tip=arg.f_tip;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Segment::~Segment() {}
|
||||
Segment::~Segment()
|
||||
{
|
||||
}
|
||||
|
||||
Frame Segment::pose(const double *q) const
|
||||
{
|
||||
return joint.pose(q) * f_tip;
|
||||
}
|
||||
Frame Segment::pose(const double* q)const
|
||||
{
|
||||
return joint.pose(q)*f_tip;
|
||||
}
|
||||
|
||||
Twist Segment::twist(const double *q, const double &qdot, int dof) const
|
||||
{
|
||||
return joint.twist(qdot, dof).RefPoint(pose(q).p);
|
||||
}
|
||||
Twist Segment::twist(const double* q, const double& qdot, int dof)const
|
||||
{
|
||||
return joint.twist(qdot, dof).RefPoint(pose(q).p);
|
||||
}
|
||||
|
||||
Twist Segment::twist(const Vector &p, const double &qdot, int dof) const
|
||||
{
|
||||
return joint.twist(qdot, dof).RefPoint(p);
|
||||
}
|
||||
Twist Segment::twist(const Vector& p, const double& qdot, int dof)const
|
||||
{
|
||||
return joint.twist(qdot, dof).RefPoint(p);
|
||||
}
|
||||
|
||||
Twist Segment::twist(const Frame& f, const double& qdot, int dof)const
|
||||
{
|
||||
return (f.M*joint.twist(qdot, dof)).RefPoint(f.p);
|
||||
}
|
||||
}//end of namespace KDL
|
||||
|
||||
Twist Segment::twist(const Frame &f, const double &qdot, int dof) const
|
||||
{
|
||||
return (f.M * joint.twist(qdot, dof)).RefPoint(f.p);
|
||||
}
|
||||
} // end of namespace KDL
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
#ifndef KDL_SEGMENT_HPP
|
||||
#define KDL_SEGMENT_HPP
|
||||
|
||||
@@ -29,122 +30,120 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/**
|
||||
* \brief This class encapsulates a simple segment, that is a "rigid
|
||||
* body" (i.e., a frame and an inertia) with a joint and with
|
||||
* "handles", root and tip to connect to other segments.
|
||||
*
|
||||
* A simple segment is described by the following properties :
|
||||
* - Joint
|
||||
* - inertia: of the rigid body part of the Segment
|
||||
* - Offset from the end of the joint to the tip of the segment:
|
||||
* the joint is located at the root of the segment.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class Segment {
|
||||
friend class Chain;
|
||||
/**
|
||||
* \brief This class encapsulates a simple segment, that is a "rigid
|
||||
* body" (i.e., a frame and an inertia) with a joint and with
|
||||
* "handles", root and tip to connect to other segments.
|
||||
*
|
||||
* A simple segment is described by the following properties :
|
||||
* - Joint
|
||||
* - inertia: of the rigid body part of the Segment
|
||||
* - Offset from the end of the joint to the tip of the segment:
|
||||
* the joint is located at the root of the segment.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class Segment {
|
||||
friend class Chain;
|
||||
private:
|
||||
Inertia M;
|
||||
Joint joint;
|
||||
Frame f_tip;
|
||||
|
||||
private:
|
||||
Inertia M;
|
||||
Joint joint;
|
||||
Frame f_tip;
|
||||
public:
|
||||
/**
|
||||
* Constructor of the segment
|
||||
*
|
||||
* @param joint joint of the segment, default:
|
||||
* Joint(Joint::None)
|
||||
* @param f_tip frame from the end of the joint to the tip of
|
||||
* the segment, default: Frame::Identity()
|
||||
* @param M rigid body inertia of the segment, default: Inertia::Zero()
|
||||
*/
|
||||
Segment(const Joint& joint=Joint(), const Frame& f_tip=Frame::Identity(),const Inertia& M = Inertia::Zero());
|
||||
Segment(const Segment& in);
|
||||
Segment& operator=(const Segment& arg);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor of the segment
|
||||
*
|
||||
* @param joint joint of the segment, default:
|
||||
* Joint(Joint::None)
|
||||
* @param f_tip frame from the end of the joint to the tip of
|
||||
* the segment, default: Frame::Identity()
|
||||
* @param M rigid body inertia of the segment, default: Inertia::Zero()
|
||||
*/
|
||||
Segment(const Joint &joint = Joint(),
|
||||
const Frame &f_tip = Frame::Identity(),
|
||||
const Inertia &M = Inertia::Zero());
|
||||
Segment(const Segment &in);
|
||||
Segment &operator=(const Segment &arg);
|
||||
virtual ~Segment();
|
||||
|
||||
virtual ~Segment();
|
||||
/**
|
||||
* Request the pose of the segment, given the joint position q.
|
||||
*
|
||||
* @param q 1D position of the joint
|
||||
*
|
||||
* @return pose from the root to the tip of the segment
|
||||
*/
|
||||
Frame pose(const double* q)const;
|
||||
/**
|
||||
* Request the 6D-velocity of the tip of the segment, given
|
||||
* the joint position q and the joint velocity qdot.
|
||||
*
|
||||
* @param q ND position of the joint
|
||||
* @param qdot ND velocity of the joint
|
||||
*
|
||||
* @return 6D-velocity of the tip of the segment, expressed
|
||||
*in the base-frame of the segment(root) and with the tip of
|
||||
*the segment as reference point.
|
||||
*/
|
||||
Twist twist(const double* q,const double& qdot, int dof=0)const;
|
||||
|
||||
/**
|
||||
* Request the pose of the segment, given the joint position q.
|
||||
*
|
||||
* @param q 1D position of the joint
|
||||
*
|
||||
* @return pose from the root to the tip of the segment
|
||||
*/
|
||||
Frame pose(const double *q) const;
|
||||
/**
|
||||
* Request the 6D-velocity of the tip of the segment, given
|
||||
* the joint position q and the joint velocity qdot.
|
||||
*
|
||||
* @param q ND position of the joint
|
||||
* @param qdot ND velocity of the joint
|
||||
*
|
||||
* @return 6D-velocity of the tip of the segment, expressed
|
||||
*in the base-frame of the segment(root) and with the tip of
|
||||
*the segment as reference point.
|
||||
*/
|
||||
Twist twist(const double *q, const double &qdot, int dof = 0) const;
|
||||
/**
|
||||
* Request the 6D-velocity at a given point p, relative to base frame of the segment
|
||||
* givven the joint velocity qdot.
|
||||
*
|
||||
* @param p reference point
|
||||
* @param qdot ND velocity of the joint
|
||||
*
|
||||
* @return 6D-velocity at a given point p, expressed
|
||||
* in the base-frame of the segment(root)
|
||||
*/
|
||||
Twist twist(const Vector& p, const double& qdot, int dof=0)const;
|
||||
|
||||
/**
|
||||
* Request the 6D-velocity at a given point p, relative to base frame of the segment
|
||||
* givven the joint velocity qdot.
|
||||
*
|
||||
* @param p reference point
|
||||
* @param qdot ND velocity of the joint
|
||||
*
|
||||
* @return 6D-velocity at a given point p, expressed
|
||||
* in the base-frame of the segment(root)
|
||||
*/
|
||||
Twist twist(const Vector &p, const double &qdot, int dof = 0) const;
|
||||
/**
|
||||
* Request the 6D-velocity at a given frame origin, relative to base frame of the segment
|
||||
* assuming the frame rotation is the rotation of the joint.
|
||||
*
|
||||
* @param f joint pose frame + reference point
|
||||
* @param qdot ND velocity of the joint
|
||||
*
|
||||
* @return 6D-velocity at frame reference point, expressed
|
||||
* in the base-frame of the segment(root)
|
||||
*/
|
||||
Twist twist(const Frame& f, const double& qdot, int dof)const;
|
||||
|
||||
/**
|
||||
* Request the 6D-velocity at a given frame origin, relative to base frame of the segment
|
||||
* assuming the frame rotation is the rotation of the joint.
|
||||
*
|
||||
* @param f joint pose frame + reference point
|
||||
* @param qdot ND velocity of the joint
|
||||
*
|
||||
* @return 6D-velocity at frame reference point, expressed
|
||||
* in the base-frame of the segment(root)
|
||||
*/
|
||||
Twist twist(const Frame &f, const double &qdot, int dof) const;
|
||||
/**
|
||||
* Request the joint of the segment
|
||||
*
|
||||
*
|
||||
* @return const reference to the joint of the segment
|
||||
*/
|
||||
const Joint& getJoint()const
|
||||
{
|
||||
return joint;
|
||||
}
|
||||
/**
|
||||
* Request the inertia of the segment
|
||||
*
|
||||
*
|
||||
* @return const reference to the inertia of the segment
|
||||
*/
|
||||
const Inertia& getInertia()const
|
||||
{
|
||||
return M;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the joint of the segment
|
||||
*
|
||||
*
|
||||
* @return const reference to the joint of the segment
|
||||
*/
|
||||
const Joint &getJoint() const
|
||||
{
|
||||
return joint;
|
||||
}
|
||||
/**
|
||||
* Request the inertia of the segment
|
||||
*
|
||||
*
|
||||
* @return const reference to the inertia of the segment
|
||||
*/
|
||||
const Inertia &getInertia() const
|
||||
{
|
||||
return M;
|
||||
}
|
||||
/**
|
||||
* Request the pose from the joint end to the tip of the
|
||||
*segment.
|
||||
*
|
||||
* @return const reference to the joint end - segment tip pose.
|
||||
*/
|
||||
const Frame& getFrameToTip()const
|
||||
{
|
||||
return f_tip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the pose from the joint end to the tip of the
|
||||
*segment.
|
||||
*
|
||||
* @return const reference to the joint end - segment tip pose.
|
||||
*/
|
||||
const Frame &getFrameToTip() const
|
||||
{
|
||||
return f_tip;
|
||||
}
|
||||
};
|
||||
} // end of namespace KDL
|
||||
};
|
||||
}//end of namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,104 +27,100 @@
|
||||
namespace KDL {
|
||||
using namespace std;
|
||||
|
||||
Tree::Tree() : nrOfJoints(0), nrOfSegments(0)
|
||||
{
|
||||
TreeElement root;
|
||||
std::pair<std::string, TreeElement> val("root", root);
|
||||
segments.insert(val);
|
||||
Tree::Tree() :
|
||||
nrOfJoints(0), nrOfSegments(0) {
|
||||
TreeElement root;
|
||||
std::pair<std::string, TreeElement> val("root", root);
|
||||
segments.insert(val);
|
||||
}
|
||||
|
||||
Tree::Tree(const Tree &in)
|
||||
{
|
||||
segments.clear();
|
||||
nrOfSegments = 0;
|
||||
nrOfJoints = 0;
|
||||
TreeElement root;
|
||||
std::pair<std::string, TreeElement> val("root", root);
|
||||
segments.insert(val);
|
||||
this->addTree(in, "", "root");
|
||||
Tree::Tree(const Tree& in) {
|
||||
segments.clear();
|
||||
nrOfSegments = 0;
|
||||
nrOfJoints = 0;
|
||||
TreeElement root;
|
||||
std::pair<std::string, TreeElement> val("root", root);
|
||||
segments.insert(val);
|
||||
this->addTree(in, "", "root");
|
||||
|
||||
}
|
||||
|
||||
Tree &Tree::operator=(const Tree &in)
|
||||
{
|
||||
segments.clear();
|
||||
nrOfSegments = 0;
|
||||
nrOfJoints = 0;
|
||||
TreeElement root;
|
||||
std::pair<std::string, TreeElement> val("root", root);
|
||||
segments.insert(val);
|
||||
this->addTree(in, "", "root");
|
||||
return *this;
|
||||
Tree& Tree::operator=(const Tree& in) {
|
||||
segments.clear();
|
||||
nrOfSegments = 0;
|
||||
nrOfJoints = 0;
|
||||
TreeElement root;
|
||||
std::pair<std::string, TreeElement> val("root", root);
|
||||
segments.insert(val);
|
||||
this->addTree(in, "", "root");
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool Tree::addSegment(const Segment &segment,
|
||||
const std::string &segment_name,
|
||||
const std::string &hook_name)
|
||||
{
|
||||
SegmentMap::iterator parent = segments.find(hook_name);
|
||||
// check if parent exists
|
||||
if (parent == segments.end())
|
||||
return false;
|
||||
pair<SegmentMap::iterator, bool> retval;
|
||||
// insert new element
|
||||
TreeElement elem(segment, *parent, nrOfJoints);
|
||||
std::pair<std::string, TreeElement> val(segment_name, elem);
|
||||
bool Tree::addSegment(const Segment& segment, const std::string& segment_name,
|
||||
const std::string& hook_name) {
|
||||
SegmentMap::iterator parent = segments.find(hook_name);
|
||||
//check if parent exists
|
||||
if (parent == segments.end())
|
||||
return false;
|
||||
pair<SegmentMap::iterator, bool> retval;
|
||||
//insert new element
|
||||
TreeElement elem(segment, *parent, nrOfJoints);
|
||||
std::pair<std::string, TreeElement> val(segment_name, elem);
|
||||
|
||||
retval = segments.insert(val);
|
||||
// check if insertion succeeded
|
||||
if (!retval.second)
|
||||
return false;
|
||||
// add iterator to new element in parents children list
|
||||
parent->second.children.push_back(retval.first);
|
||||
// increase number of segments
|
||||
nrOfSegments++;
|
||||
// increase number of joints
|
||||
nrOfJoints += segment.getJoint().getNDof();
|
||||
return true;
|
||||
retval = segments.insert(val);
|
||||
//check if insertion succeeded
|
||||
if (!retval.second)
|
||||
return false;
|
||||
//add iterator to new element in parents children list
|
||||
parent->second.children.push_back(retval.first);
|
||||
//increase number of segments
|
||||
nrOfSegments++;
|
||||
//increase number of joints
|
||||
nrOfJoints += segment.getJoint().getNDof();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tree::addChain(const Chain &chain,
|
||||
const std::string &chain_name,
|
||||
const std::string &hook_name)
|
||||
{
|
||||
string parent_name = hook_name;
|
||||
for (unsigned int i = 0; i < chain.getNrOfSegments(); i++) {
|
||||
ostringstream segment_name;
|
||||
segment_name << chain_name << "Segment" << i;
|
||||
if (this->addSegment(chain.getSegment(i), segment_name.str(), parent_name))
|
||||
parent_name = segment_name.str();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
bool Tree::addChain(const Chain& chain, const std::string& chain_name,
|
||||
const std::string& hook_name) {
|
||||
string parent_name = hook_name;
|
||||
for (unsigned int i = 0; i < chain.getNrOfSegments(); i++) {
|
||||
ostringstream segment_name;
|
||||
segment_name << chain_name << "Segment" << i;
|
||||
if (this->addSegment(chain.getSegment(i), segment_name.str(),
|
||||
parent_name))
|
||||
parent_name = segment_name.str();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Tree::addTree(const Tree &tree, const std::string &tree_name, const std::string &hook_name)
|
||||
{
|
||||
return this->addTreeRecursive(tree.getSegment("root"), tree_name, hook_name);
|
||||
bool Tree::addTree(const Tree& tree, const std::string& tree_name,
|
||||
const std::string& hook_name) {
|
||||
return this->addTreeRecursive(tree.getSegment("root"), tree_name, hook_name);
|
||||
}
|
||||
|
||||
bool Tree::addTreeRecursive(SegmentMap::const_iterator root,
|
||||
const std::string &tree_name,
|
||||
const std::string &hook_name)
|
||||
{
|
||||
// get iterator for root-segment
|
||||
SegmentMap::const_iterator child;
|
||||
// try to add all of root's children
|
||||
for (unsigned int i = 0; i < root->second.children.size(); i++) {
|
||||
child = root->second.children[i];
|
||||
// Try to add the child
|
||||
if (this->addSegment(child->second.segment, tree_name + child->first, hook_name)) {
|
||||
// if child is added, add all the child's children
|
||||
if (!(this->addTreeRecursive(child, tree_name, tree_name + child->first)))
|
||||
// if it didn't work, return false
|
||||
return false;
|
||||
const std::string& tree_name, const std::string& hook_name) {
|
||||
//get iterator for root-segment
|
||||
SegmentMap::const_iterator child;
|
||||
//try to add all of root's children
|
||||
for (unsigned int i = 0; i < root->second.children.size(); i++) {
|
||||
child = root->second.children[i];
|
||||
//Try to add the child
|
||||
if (this->addSegment(child->second.segment, tree_name + child->first,
|
||||
hook_name)) {
|
||||
//if child is added, add all the child's children
|
||||
if (!(this->addTreeRecursive(child, tree_name, tree_name
|
||||
+ child->first)))
|
||||
//if it didn't work, return false
|
||||
return false;
|
||||
} else
|
||||
//If the child could not be added, return false
|
||||
return false;
|
||||
}
|
||||
else
|
||||
// If the child could not be added, return false
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
@@ -22,161 +22,156 @@
|
||||
#ifndef KDL_TREE_HPP
|
||||
#define KDL_TREE_HPP
|
||||
|
||||
#include "chain.hpp"
|
||||
#include "segment.hpp"
|
||||
#include "chain.hpp"
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <Eigen/Core>
|
||||
|
||||
namespace KDL {
|
||||
// Forward declaration
|
||||
class TreeElement;
|
||||
// Eigen allocator is needed for alignment of Eigen data types
|
||||
typedef std::map<std::string,
|
||||
TreeElement,
|
||||
std::less<std::string>,
|
||||
Eigen::aligned_allocator<std::pair<const std::string, TreeElement>>>
|
||||
SegmentMap;
|
||||
namespace KDL
|
||||
{
|
||||
//Forward declaration
|
||||
class TreeElement;
|
||||
// Eigen allocator is needed for alignment of Eigen data types
|
||||
typedef std::map<std::string,TreeElement, std::less<std::string>, Eigen::aligned_allocator<std::pair<const std::string, TreeElement> > > SegmentMap;
|
||||
|
||||
class TreeElement {
|
||||
public:
|
||||
TreeElement() : q_nr(0), parent(0){};
|
||||
class TreeElement
|
||||
{
|
||||
public:
|
||||
TreeElement():q_nr(0),parent(0)
|
||||
{};
|
||||
public:
|
||||
Segment segment;
|
||||
unsigned int q_nr;
|
||||
SegmentMap::value_type const *parent;
|
||||
std::vector<SegmentMap::const_iterator > children;
|
||||
TreeElement(const Segment& segment_in,const SegmentMap::value_type& parent_in,unsigned int q_nr_in)
|
||||
{
|
||||
q_nr=q_nr_in;
|
||||
segment=segment_in;
|
||||
parent=&parent_in;
|
||||
};
|
||||
static TreeElement Root()
|
||||
{
|
||||
return TreeElement();
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
Segment segment;
|
||||
unsigned int q_nr;
|
||||
SegmentMap::value_type const *parent;
|
||||
std::vector<SegmentMap::const_iterator> children;
|
||||
TreeElement(const Segment &segment_in,
|
||||
const SegmentMap::value_type &parent_in,
|
||||
unsigned int q_nr_in)
|
||||
{
|
||||
q_nr = q_nr_in;
|
||||
segment = segment_in;
|
||||
parent = &parent_in;
|
||||
};
|
||||
static TreeElement Root()
|
||||
{
|
||||
return TreeElement();
|
||||
};
|
||||
};
|
||||
/**
|
||||
* \brief This class encapsulates a <strong>tree</strong>
|
||||
* kinematic interconnection structure. It is build out of segments.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class Tree
|
||||
{
|
||||
private:
|
||||
SegmentMap segments;
|
||||
unsigned int nrOfJoints;
|
||||
unsigned int nrOfSegments;
|
||||
|
||||
/**
|
||||
* \brief This class encapsulates a <strong>tree</strong>
|
||||
* kinematic interconnection structure. It is build out of segments.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class Tree {
|
||||
private:
|
||||
SegmentMap segments;
|
||||
unsigned int nrOfJoints;
|
||||
unsigned int nrOfSegments;
|
||||
bool addTreeRecursive(SegmentMap::const_iterator root, const std::string& tree_name, const std::string& hook_name);
|
||||
|
||||
bool addTreeRecursive(SegmentMap::const_iterator root,
|
||||
const std::string &tree_name,
|
||||
const std::string &hook_name);
|
||||
public:
|
||||
/**
|
||||
* The constructor of a tree, a new tree is always empty
|
||||
*/
|
||||
Tree();
|
||||
Tree(const Tree& in);
|
||||
Tree& operator= (const Tree& arg);
|
||||
|
||||
public:
|
||||
/**
|
||||
* The constructor of a tree, a new tree is always empty
|
||||
*/
|
||||
Tree();
|
||||
Tree(const Tree &in);
|
||||
Tree &operator=(const Tree &arg);
|
||||
/**
|
||||
* Adds a new segment to the end of the segment with
|
||||
* hook_name as segment_name
|
||||
*
|
||||
* @param segment new segment to add
|
||||
* @param segment_name name of the new segment
|
||||
* @param hook_name name of the segment to connect this
|
||||
* segment with.
|
||||
*
|
||||
* @return false if hook_name could not be found.
|
||||
*/
|
||||
bool addSegment(const Segment& segment, const std::string& segment_name, const std::string& hook_name);
|
||||
|
||||
/**
|
||||
* Adds a new segment to the end of the segment with
|
||||
* hook_name as segment_name
|
||||
*
|
||||
* @param segment new segment to add
|
||||
* @param segment_name name of the new segment
|
||||
* @param hook_name name of the segment to connect this
|
||||
* segment with.
|
||||
*
|
||||
* @return false if hook_name could not be found.
|
||||
*/
|
||||
bool addSegment(const Segment &segment,
|
||||
const std::string &segment_name,
|
||||
const std::string &hook_name);
|
||||
/**
|
||||
* Adds a complete chain to the end of the segment with
|
||||
* hook_name as segment_name. Segment i of
|
||||
* the chain will get chain_name+".Segment"+i as segment_name.
|
||||
*
|
||||
* @param chain Chain to add
|
||||
* @param chain_name name of the chain
|
||||
* @param hook_name name of the segment to connect the chain with.
|
||||
*
|
||||
* @return false if hook_name could not be found.
|
||||
*/
|
||||
bool addChain(const Chain& chain, const std::string& chain_name, const std::string& hook_name);
|
||||
|
||||
/**
|
||||
* Adds a complete chain to the end of the segment with
|
||||
* hook_name as segment_name. Segment i of
|
||||
* the chain will get chain_name+".Segment"+i as segment_name.
|
||||
*
|
||||
* @param chain Chain to add
|
||||
* @param chain_name name of the chain
|
||||
* @param hook_name name of the segment to connect the chain with.
|
||||
*
|
||||
* @return false if hook_name could not be found.
|
||||
*/
|
||||
bool addChain(const Chain &chain, const std::string &chain_name, const std::string &hook_name);
|
||||
/**
|
||||
* Adds a complete tree to the end of the segment with
|
||||
* hookname as segment_name. The segments of the tree will get
|
||||
* tree_name+segment_name as segment_name.
|
||||
*
|
||||
* @param tree Tree to add
|
||||
* @param tree_name name of the tree
|
||||
* @param hook_name name of the segment to connect the tree with
|
||||
*
|
||||
* @return false if hook_name could not be found
|
||||
*/
|
||||
bool addTree(const Tree& tree, const std::string& tree_name,const std::string& hook_name);
|
||||
|
||||
/**
|
||||
* Adds a complete tree to the end of the segment with
|
||||
* hookname as segment_name. The segments of the tree will get
|
||||
* tree_name+segment_name as segment_name.
|
||||
*
|
||||
* @param tree Tree to add
|
||||
* @param tree_name name of the tree
|
||||
* @param hook_name name of the segment to connect the tree with
|
||||
*
|
||||
* @return false if hook_name could not be found
|
||||
*/
|
||||
bool addTree(const Tree &tree, const std::string &tree_name, const std::string &hook_name);
|
||||
/**
|
||||
* Request the total number of joints in the tree.\n
|
||||
* <strong> Important:</strong> It is not the same as the
|
||||
* total number of segments since a segment does not need to have
|
||||
* a joint.
|
||||
*
|
||||
* @return total nr of joints
|
||||
*/
|
||||
unsigned int getNrOfJoints()const
|
||||
{
|
||||
return nrOfJoints;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request the total number of joints in the tree.\n
|
||||
* <strong> Important:</strong> It is not the same as the
|
||||
* total number of segments since a segment does not need to have
|
||||
* a joint.
|
||||
*
|
||||
* @return total nr of joints
|
||||
*/
|
||||
unsigned int getNrOfJoints() const
|
||||
{
|
||||
return nrOfJoints;
|
||||
};
|
||||
/**
|
||||
* Request the total number of segments in the tree.
|
||||
* @return total number of segments
|
||||
*/
|
||||
unsigned int getNrOfSegments()const {return nrOfSegments;};
|
||||
|
||||
/**
|
||||
* Request the total number of segments in the tree.
|
||||
* @return total number of segments
|
||||
*/
|
||||
unsigned int getNrOfSegments() const
|
||||
{
|
||||
return nrOfSegments;
|
||||
};
|
||||
/**
|
||||
* Request the segment of the tree with name segment_name.
|
||||
*
|
||||
* @param segment_name the name of the requested segment
|
||||
*
|
||||
* @return constant iterator pointing to the requested segment
|
||||
*/
|
||||
SegmentMap::const_iterator getSegment(const std::string& segment_name)const
|
||||
{
|
||||
return segments.find(segment_name);
|
||||
};
|
||||
|
||||
/**
|
||||
* Request the segment of the tree with name segment_name.
|
||||
*
|
||||
* @param segment_name the name of the requested segment
|
||||
*
|
||||
* @return constant iterator pointing to the requested segment
|
||||
*/
|
||||
SegmentMap::const_iterator getSegment(const std::string &segment_name) const
|
||||
{
|
||||
return segments.find(segment_name);
|
||||
};
|
||||
SegmentMap::value_type const* getSegmentPtr(const std::string& segment_name)const
|
||||
{
|
||||
SegmentMap::const_iterator it = segments.find(segment_name);
|
||||
|
||||
if (it == segments.end())
|
||||
return 0;
|
||||
|
||||
SegmentMap::value_type const *getSegmentPtr(const std::string &segment_name) const
|
||||
{
|
||||
SegmentMap::const_iterator it = segments.find(segment_name);
|
||||
return &*it;
|
||||
};
|
||||
|
||||
if (it == segments.end())
|
||||
return 0;
|
||||
const SegmentMap& getSegments()const
|
||||
{
|
||||
return segments;
|
||||
}
|
||||
|
||||
return &*it;
|
||||
};
|
||||
|
||||
const SegmentMap &getSegments() const
|
||||
{
|
||||
return segments;
|
||||
}
|
||||
|
||||
virtual ~Tree(){};
|
||||
};
|
||||
} // namespace KDL
|
||||
virtual ~Tree(){};
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -26,87 +26,85 @@
|
||||
#include <string>
|
||||
|
||||
#include "tree.hpp"
|
||||
// #include "framevel.hpp"
|
||||
// #include "frameacc.hpp"
|
||||
//#include "framevel.hpp"
|
||||
//#include "frameacc.hpp"
|
||||
#include "jntarray.hpp"
|
||||
// #include "jntarrayvel.hpp"
|
||||
// #include "jntarrayacc.hpp"
|
||||
//#include "jntarrayvel.hpp"
|
||||
//#include "jntarrayacc.hpp"
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a
|
||||
* solver for the forward position kinematics for a KDL::Tree.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a
|
||||
* solver for the forward position kinematics for a KDL::Tree.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
|
||||
// Forward definition
|
||||
class TreeFkSolverPos {
|
||||
public:
|
||||
/**
|
||||
* Calculate forward position kinematics for a KDL::Tree,
|
||||
* from joint coordinates to cartesian pose.
|
||||
*
|
||||
* @param q_in input joint coordinates
|
||||
* @param p_out reference to output cartesian pose
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
virtual int JntToCart(const JntArray &q_in,
|
||||
Frame &p_out,
|
||||
const std::string &segmentName,
|
||||
const std::string &baseName) = 0;
|
||||
virtual ~TreeFkSolverPos(){};
|
||||
};
|
||||
//Forward definition
|
||||
class TreeFkSolverPos {
|
||||
public:
|
||||
/**
|
||||
* Calculate forward position kinematics for a KDL::Tree,
|
||||
* from joint coordinates to cartesian pose.
|
||||
*
|
||||
* @param q_in input joint coordinates
|
||||
* @param p_out reference to output cartesian pose
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
virtual int JntToCart(const JntArray& q_in, Frame& p_out, const std::string& segmentName, const std::string& baseName)=0;
|
||||
virtual ~TreeFkSolverPos(){};
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a solver
|
||||
* for the forward velocity kinematics for a KDL::Tree.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a solver
|
||||
* for the forward velocity kinematics for a KDL::Tree.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
// class TreeFkSolverVel {
|
||||
// public:
|
||||
/**
|
||||
* Calculate forward position and velocity kinematics, from
|
||||
* joint coordinates to cartesian coordinates.
|
||||
*
|
||||
* @param q_in input joint coordinates (position and velocity)
|
||||
* @param out output cartesian coordinates (position and velocity)
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
/**
|
||||
* Calculate forward position and velocity kinematics, from
|
||||
* joint coordinates to cartesian coordinates.
|
||||
*
|
||||
* @param q_in input joint coordinates (position and velocity)
|
||||
* @param out output cartesian coordinates (position and velocity)
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
// virtual int JntToCart(const JntArrayVel& q_in, FrameVel& out,int segmentNr=-1)=0;
|
||||
|
||||
// virtual ~TreeFkSolverVel(){};
|
||||
// };
|
||||
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a solver
|
||||
* for the forward acceleration kinematics for a KDL::Tree.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief This <strong>abstract</strong> class encapsulates a solver
|
||||
* for the forward acceleration kinematics for a KDL::Tree.
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
|
||||
// class TreeFkSolverAcc {
|
||||
// public:
|
||||
/**
|
||||
* Calculate forward position, velocity and accelaration
|
||||
* kinematics, from joint coordinates to cartesian coordinates
|
||||
*
|
||||
* @param q_in input joint coordinates (position, velocity and
|
||||
* acceleration
|
||||
@param out output cartesian coordinates (position, velocity
|
||||
* and acceleration
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
/**
|
||||
* Calculate forward position, velocity and accelaration
|
||||
* kinematics, from joint coordinates to cartesian coordinates
|
||||
*
|
||||
* @param q_in input joint coordinates (position, velocity and
|
||||
* acceleration
|
||||
@param out output cartesian coordinates (position, velocity
|
||||
* and acceleration
|
||||
*
|
||||
* @return if < 0 something went wrong
|
||||
*/
|
||||
// virtual int JntToCart(const JntArrayAcc& q_in, FrameAcc& out,int segmentNr=-1)=0;
|
||||
|
||||
// virtual ~TreeFkSolverAcc()=0;
|
||||
// };
|
||||
|
||||
} // end of namespace KDL
|
||||
|
||||
}//end of namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,44 +28,45 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
TreeFkSolverPos_recursive::TreeFkSolverPos_recursive(const Tree &_tree) : tree(_tree) {}
|
||||
TreeFkSolverPos_recursive::TreeFkSolverPos_recursive(const Tree& _tree):
|
||||
tree(_tree)
|
||||
{
|
||||
}
|
||||
|
||||
int TreeFkSolverPos_recursive::JntToCart(const JntArray& q_in, Frame& p_out, const std::string& segmentName, const std::string& baseName)
|
||||
{
|
||||
SegmentMap::value_type const* it = tree.getSegmentPtr(segmentName);
|
||||
SegmentMap::value_type const* baseit = tree.getSegmentPtr(baseName);
|
||||
|
||||
if(q_in.rows() != tree.getNrOfJoints())
|
||||
return -1;
|
||||
else if(!it) //if the segment name is not found
|
||||
return -2;
|
||||
else if(!baseit) //if the base segment name is not found
|
||||
return -3;
|
||||
else{
|
||||
p_out = recursiveFk(q_in, it, baseit);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Frame TreeFkSolverPos_recursive::recursiveFk(const JntArray& q_in, SegmentMap::value_type const* it, SegmentMap::value_type const* baseit)
|
||||
{
|
||||
//gets the frame for the current element (segment)
|
||||
const TreeElement& currentElement = it->second;
|
||||
|
||||
if(it == baseit){
|
||||
return KDL::Frame::Identity();
|
||||
}
|
||||
else{
|
||||
Frame currentFrame = currentElement.segment.pose(((JntArray&)q_in)(currentElement.q_nr));
|
||||
return recursiveFk(q_in, currentElement.parent, baseit) * currentFrame;
|
||||
}
|
||||
}
|
||||
|
||||
TreeFkSolverPos_recursive::~TreeFkSolverPos_recursive()
|
||||
{
|
||||
}
|
||||
|
||||
int TreeFkSolverPos_recursive::JntToCart(const JntArray &q_in,
|
||||
Frame &p_out,
|
||||
const std::string &segmentName,
|
||||
const std::string &baseName)
|
||||
{
|
||||
SegmentMap::value_type const *it = tree.getSegmentPtr(segmentName);
|
||||
SegmentMap::value_type const *baseit = tree.getSegmentPtr(baseName);
|
||||
|
||||
if (q_in.rows() != tree.getNrOfJoints())
|
||||
return -1;
|
||||
else if (!it) // if the segment name is not found
|
||||
return -2;
|
||||
else if (!baseit) // if the base segment name is not found
|
||||
return -3;
|
||||
else {
|
||||
p_out = recursiveFk(q_in, it, baseit);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Frame TreeFkSolverPos_recursive::recursiveFk(const JntArray &q_in,
|
||||
SegmentMap::value_type const *it,
|
||||
SegmentMap::value_type const *baseit)
|
||||
{
|
||||
// gets the frame for the current element (segment)
|
||||
const TreeElement ¤tElement = it->second;
|
||||
|
||||
if (it == baseit) {
|
||||
return KDL::Frame::Identity();
|
||||
}
|
||||
else {
|
||||
Frame currentFrame = currentElement.segment.pose(((JntArray &)q_in)(currentElement.q_nr));
|
||||
return recursiveFk(q_in, currentElement.parent, baseit) * currentFrame;
|
||||
}
|
||||
}
|
||||
|
||||
TreeFkSolverPos_recursive::~TreeFkSolverPos_recursive() {}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
@@ -27,31 +27,27 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/**
|
||||
* Implementation of a recursive forward position kinematics
|
||||
* algorithm to calculate the position transformation from joint
|
||||
* space to Cartesian space of a general kinematic tree (KDL::Tree).
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class TreeFkSolverPos_recursive : public TreeFkSolverPos {
|
||||
public:
|
||||
TreeFkSolverPos_recursive(const Tree &tree);
|
||||
~TreeFkSolverPos_recursive();
|
||||
/**
|
||||
* Implementation of a recursive forward position kinematics
|
||||
* algorithm to calculate the position transformation from joint
|
||||
* space to Cartesian space of a general kinematic tree (KDL::Tree).
|
||||
*
|
||||
* @ingroup KinematicFamily
|
||||
*/
|
||||
class TreeFkSolverPos_recursive : public TreeFkSolverPos
|
||||
{
|
||||
public:
|
||||
TreeFkSolverPos_recursive(const Tree& tree);
|
||||
~TreeFkSolverPos_recursive();
|
||||
|
||||
virtual int JntToCart(const JntArray &q_in,
|
||||
Frame &p_out,
|
||||
const std::string &segmentName,
|
||||
const std::string &baseName);
|
||||
virtual int JntToCart(const JntArray& q_in, Frame& p_out, const std::string& segmentName, const std::string& baseName);
|
||||
|
||||
private:
|
||||
const Tree tree;
|
||||
private:
|
||||
const Tree tree;
|
||||
|
||||
Frame recursiveFk(const JntArray& q_in, SegmentMap::value_type const* it, SegmentMap::value_type const* baseit);
|
||||
};
|
||||
|
||||
Frame recursiveFk(const JntArray &q_in,
|
||||
SegmentMap::value_type const *it,
|
||||
SegmentMap::value_type const *baseit);
|
||||
};
|
||||
|
||||
} // namespace KDL
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,66 +13,69 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
TreeJntToJacSolver::TreeJntToJacSolver(const Tree &tree_in) : tree(tree_in) {}
|
||||
TreeJntToJacSolver::TreeJntToJacSolver(const Tree& tree_in) :
|
||||
tree(tree_in) {
|
||||
}
|
||||
|
||||
TreeJntToJacSolver::~TreeJntToJacSolver() {}
|
||||
TreeJntToJacSolver::~TreeJntToJacSolver() {
|
||||
}
|
||||
|
||||
int TreeJntToJacSolver::JntToJac(const JntArray &q_in,
|
||||
Jacobian &jac,
|
||||
const std::string &segmentname)
|
||||
{
|
||||
// First we check all the sizes:
|
||||
if (q_in.rows() != tree.getNrOfJoints() || jac.columns() != tree.getNrOfJoints())
|
||||
return -1;
|
||||
int TreeJntToJacSolver::JntToJac(const JntArray& q_in, Jacobian& jac,
|
||||
const std::string& segmentname) {
|
||||
//First we check all the sizes:
|
||||
if (q_in.rows() != tree.getNrOfJoints() || jac.columns()
|
||||
!= tree.getNrOfJoints())
|
||||
return -1;
|
||||
|
||||
// Lets search the tree-element
|
||||
SegmentMap::value_type const *it = tree.getSegmentPtr(segmentname);
|
||||
//Lets search the tree-element
|
||||
SegmentMap::value_type const* it = tree.getSegmentPtr(segmentname);
|
||||
|
||||
// If segmentname is not inside the tree, back out:
|
||||
if (!it)
|
||||
return -2;
|
||||
//If segmentname is not inside the tree, back out:
|
||||
if (!it)
|
||||
return -2;
|
||||
|
||||
// Let's make the jacobian zero:
|
||||
SetToZero(jac);
|
||||
//Let's make the jacobian zero:
|
||||
SetToZero(jac);
|
||||
|
||||
SegmentMap::value_type const *root = tree.getSegmentPtr("root");
|
||||
SegmentMap::value_type const* root = tree.getSegmentPtr("root");
|
||||
|
||||
Frame T_total = Frame::Identity();
|
||||
Frame T_local, T_joint;
|
||||
Twist t_local;
|
||||
// Lets recursively iterate until we are in the root segment
|
||||
while (it != root) {
|
||||
// get the corresponding q_nr for this TreeElement:
|
||||
unsigned int q_nr = it->second.q_nr;
|
||||
Frame T_total = Frame::Identity();
|
||||
Frame T_local, T_joint;
|
||||
Twist t_local;
|
||||
//Lets recursively iterate until we are in the root segment
|
||||
while (it != root) {
|
||||
//get the corresponding q_nr for this TreeElement:
|
||||
unsigned int q_nr = it->second.q_nr;
|
||||
|
||||
// get the pose of the joint.
|
||||
T_joint = it->second.segment.getJoint().pose(((JntArray &)q_in)(q_nr));
|
||||
// combine with the tip to have the tip pose
|
||||
T_local = T_joint * it->second.segment.getFrameToTip();
|
||||
// calculate new T_end:
|
||||
T_total = T_local * T_total;
|
||||
//get the pose of the joint.
|
||||
T_joint = it->second.segment.getJoint().pose(((JntArray&)q_in)(q_nr));
|
||||
// combine with the tip to have the tip pose
|
||||
T_local = T_joint*it->second.segment.getFrameToTip();
|
||||
//calculate new T_end:
|
||||
T_total = T_local * T_total;
|
||||
|
||||
// get the twist of the segment:
|
||||
int ndof = it->second.segment.getJoint().getNDof();
|
||||
for (int dof = 0; dof < ndof; dof++) {
|
||||
// combine joint rotation with tip position to get a reference frame for the joint
|
||||
T_joint.p = T_local.p;
|
||||
// in which the twist can be computed (needed for NDof joint)
|
||||
t_local = it->second.segment.twist(T_joint, 1.0, dof);
|
||||
// transform the endpoint of the local twist to the global endpoint:
|
||||
t_local = t_local.RefPoint(T_total.p - T_local.p);
|
||||
// transform the base of the twist to the endpoint
|
||||
t_local = T_total.M.Inverse(t_local);
|
||||
// store the twist in the jacobian:
|
||||
jac.twists[q_nr + dof] = t_local;
|
||||
}
|
||||
// goto the parent
|
||||
it = it->second.parent;
|
||||
} // endwhile
|
||||
// Change the base of the complete jacobian from the endpoint to the base
|
||||
changeBase(jac, T_total.M, jac);
|
||||
//get the twist of the segment:
|
||||
int ndof = it->second.segment.getJoint().getNDof();
|
||||
for (int dof=0; dof<ndof; dof++) {
|
||||
// combine joint rotation with tip position to get a reference frame for the joint
|
||||
T_joint.p = T_local.p;
|
||||
// in which the twist can be computed (needed for NDof joint)
|
||||
t_local = it->second.segment.twist(T_joint, 1.0, dof);
|
||||
//transform the endpoint of the local twist to the global endpoint:
|
||||
t_local = t_local.RefPoint(T_total.p - T_local.p);
|
||||
//transform the base of the twist to the endpoint
|
||||
t_local = T_total.M.Inverse(t_local);
|
||||
//store the twist in the jacobian:
|
||||
jac.twists[q_nr+dof] = t_local;
|
||||
}
|
||||
//goto the parent
|
||||
it = it->second.parent;
|
||||
}//endwhile
|
||||
//Change the base of the complete jacobian from the endpoint to the base
|
||||
changeBase(jac, T_total.M, jac);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
}//end JntToJac
|
||||
}//end namespace
|
||||
|
||||
} // end JntToJac
|
||||
} // namespace KDL
|
||||
|
||||
@@ -8,30 +8,31 @@
|
||||
#ifndef TREEJNTTOJACSOLVER_HPP_
|
||||
#define TREEJNTTOJACSOLVER_HPP_
|
||||
|
||||
#include "tree.hpp"
|
||||
#include "jacobian.hpp"
|
||||
#include "jntarray.hpp"
|
||||
#include "tree.hpp"
|
||||
|
||||
namespace KDL {
|
||||
|
||||
class TreeJntToJacSolver {
|
||||
public:
|
||||
TreeJntToJacSolver(const Tree &tree);
|
||||
public:
|
||||
TreeJntToJacSolver(const Tree& tree);
|
||||
|
||||
virtual ~TreeJntToJacSolver();
|
||||
virtual ~TreeJntToJacSolver();
|
||||
|
||||
/*
|
||||
* Calculate the jacobian for a part of the tree: from a certain segment, given by segmentname to
|
||||
* the root. The resulting jacobian is expressed in the baseframe of the tree ("root"), the
|
||||
* reference point is in the end-segment
|
||||
*/
|
||||
/*
|
||||
* Calculate the jacobian for a part of the tree: from a certain segment, given by segmentname to the root.
|
||||
* The resulting jacobian is expressed in the baseframe of the tree ("root"), the reference point is in the end-segment
|
||||
*/
|
||||
|
||||
int JntToJac(const JntArray &q_in, Jacobian &jac, const std::string &segmentname);
|
||||
int JntToJac(const JntArray& q_in, Jacobian& jac,
|
||||
const std::string& segmentname);
|
||||
|
||||
private:
|
||||
KDL::Tree tree;
|
||||
|
||||
private:
|
||||
KDL::Tree tree;
|
||||
};
|
||||
|
||||
} // namespace KDL
|
||||
}//End of namespace
|
||||
|
||||
#endif /* TREEJNTTOJACSOLVER_H_ */
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/***************************************************************************
|
||||
tag: Erwin Aertbelien Mon Jan 10 16:38:38 CET 2005 error.h
|
||||
tag: Erwin Aertbelien Mon Jan 10 16:38:38 CET 2005 error.h
|
||||
|
||||
error.h - description
|
||||
-------------------
|
||||
begin : Mon January 10 2005
|
||||
copyright : (C) 2005 Erwin Aertbelien
|
||||
email : erwin.aertbelien@mech.kuleuven.ac.be
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
@@ -24,22 +24,23 @@
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* \file
|
||||
* \file
|
||||
* Defines the exception classes that can be thrown
|
||||
* Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
*
|
||||
* \version
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
* \par History
|
||||
* - $log$
|
||||
*
|
||||
* \par Release
|
||||
* $Name: $
|
||||
* $Name: $
|
||||
****************************************************************************/
|
||||
#ifndef ERROR_H_84822 // to make it unique, a random number
|
||||
#ifndef ERROR_H_84822 // to make it unique, a random number
|
||||
#define ERROR_H_84822
|
||||
|
||||
#include "utility.h"
|
||||
@@ -47,362 +48,196 @@
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/**
|
||||
* Base class for errors generated by ORO_Geometry
|
||||
/**
|
||||
* Base class for errors generated by ORO_Geometry
|
||||
*/
|
||||
class Error {
|
||||
public:
|
||||
/** Returns a description string describing the error.
|
||||
* the returned pointer only guaranteed to exists as long as
|
||||
* the Error object exists.
|
||||
*/
|
||||
virtual ~Error() {}
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Unspecified Error\n";
|
||||
}
|
||||
public:
|
||||
/** Returns a description string describing the error.
|
||||
* the returned pointer only guaranteed to exists as long as
|
||||
* the Error object exists.
|
||||
*/
|
||||
virtual ~Error() {}
|
||||
virtual const char* Description() const {return "Unspecified Error\n";}
|
||||
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual int GetType() const {return 0;}
|
||||
};
|
||||
|
||||
class Error_IO : public Error {
|
||||
std::string msg;
|
||||
int typenr;
|
||||
|
||||
public:
|
||||
Error_IO(const std::string &_msg = "Unspecified I/O Error", int typenr = 0) : msg(_msg) {}
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return msg.c_str();
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return typenr;
|
||||
}
|
||||
class Error_IO : public Error {
|
||||
std::string msg;
|
||||
int typenr;
|
||||
public:
|
||||
Error_IO(const std::string& _msg="Unspecified I/O Error",int typenr=0):msg(_msg) {}
|
||||
virtual const char* Description() const {return msg.c_str();}
|
||||
virtual int GetType() const {return typenr;}
|
||||
};
|
||||
class Error_BasicIO : public Error_IO {};
|
||||
class Error_BasicIO_File : public Error_BasicIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Error while reading stream";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Error while reading stream";}
|
||||
virtual int GetType() const {return 1;}
|
||||
};
|
||||
class Error_BasicIO_Exp_Delim : public Error_BasicIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Expected Delimiter not encountered";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Expected Delimiter not encountered";}
|
||||
virtual int GetType() const {return 2;}
|
||||
};
|
||||
class Error_BasicIO_Not_A_Space : public Error_BasicIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Expected space,tab or newline not encountered";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Expected space,tab or newline not encountered";}
|
||||
virtual int GetType() const {return 3;}
|
||||
};
|
||||
class Error_BasicIO_Unexpected : public Error_BasicIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Unexpected character";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Unexpected character";}
|
||||
virtual int GetType() const {return 4;}
|
||||
};
|
||||
|
||||
class Error_BasicIO_ToBig : public Error_BasicIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Word that is read out of stream is bigger than maxsize";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Word that is read out of stream is bigger than maxsize";}
|
||||
virtual int GetType() const {return 5;}
|
||||
};
|
||||
|
||||
class Error_BasicIO_Not_Opened : public Error_BasicIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "File cannot be opened";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "File cannot be opened";}
|
||||
virtual int GetType() const {return 6;}
|
||||
};
|
||||
class Error_FrameIO : public Error_IO {};
|
||||
class Error_Frame_Vector_Unexpected_id : public Error_FrameIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Unexpected identifier, expecting a vector (explicit or ZERO)";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 101;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Unexpected identifier, expecting a vector (explicit or ZERO)";}
|
||||
virtual int GetType() const {return 101;}
|
||||
};
|
||||
class Error_Frame_Frame_Unexpected_id : public Error_FrameIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Unexpected identifier, expecting a Frame (explicit or DH)";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 102;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Unexpected identifier, expecting a Frame (explicit or DH)";}
|
||||
virtual int GetType() const {return 102;}
|
||||
};
|
||||
class Error_Frame_Rotation_Unexpected_id : public Error_FrameIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Unexpected identifier, expecting a Rotation (explicit or EULERZYX, EULERZYZ, "
|
||||
"RPY,ROT,IDENTITY)";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 103;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Unexpected identifier, expecting a Rotation (explicit or EULERZYX, EULERZYZ, RPY,ROT,IDENTITY)";}
|
||||
virtual int GetType() const {return 103;}
|
||||
};
|
||||
class Error_ChainIO : public Error {};
|
||||
class Error_Chain_Unexpected_id : public Error_ChainIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Unexpected identifier, expecting TRANS or ROT";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 201;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Unexpected identifier, expecting TRANS or ROT";}
|
||||
virtual int GetType() const {return 201;}
|
||||
};
|
||||
//! Error_Redundancy indicates an error that occured during solving for redundancy.
|
||||
class Error_RedundancyIO : public Error_IO {};
|
||||
class Error_RedundancyIO:public Error_IO {};
|
||||
class Error_Redundancy_Illegal_Resolutiontype : public Error_RedundancyIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Illegal Resolutiontype is used in I/O with ResolutionTask";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 301;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Illegal Resolutiontype is used in I/O with ResolutionTask";}
|
||||
virtual int GetType() const {return 301;}
|
||||
};
|
||||
class Error_Redundancy : public Error {};
|
||||
class Error_Redundancy:public Error {};
|
||||
class Error_Redundancy_Unavoidable : public Error_Redundancy {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Joint limits cannot be avoided";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 1002;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const {return "Joint limits cannot be avoided";}
|
||||
virtual int GetType() const {return 1002;}
|
||||
};
|
||||
class Error_Redundancy_Low_Manip : public Error_Redundancy {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Manipulability is very low";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 1003;
|
||||
}
|
||||
class Error_Redundancy_Low_Manip: public Error_Redundancy {
|
||||
public:
|
||||
virtual const char* Description() const {return "Manipulability is very low";}
|
||||
virtual int GetType() const {return 1003;}
|
||||
};
|
||||
class Error_MotionIO : public Error {};
|
||||
class Error_MotionIO_Unexpected_MotProf : public Error_MotionIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Wrong keyword while reading motion profile";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 2001;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const { return "Wrong keyword while reading motion profile";}
|
||||
virtual int GetType() const {return 2001;}
|
||||
};
|
||||
class Error_MotionIO_Unexpected_Traj : public Error_MotionIO {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Trajectory type keyword not known";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 2002;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const { return "Trajectory type keyword not known";}
|
||||
virtual int GetType() const {return 2002;}
|
||||
};
|
||||
|
||||
class Error_MotionPlanning : public Error {};
|
||||
|
||||
class Error_MotionPlanning_Circle_ToSmall : public Error_MotionPlanning {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Circle : radius is too small";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 3001;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const { return "Circle : radius is too small";}
|
||||
virtual int GetType() const {return 3001;}
|
||||
};
|
||||
|
||||
class Error_MotionPlanning_Circle_No_Plane : public Error_MotionPlanning {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Circle : Plane for motion is not properly defined";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 3002;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const { return "Circle : Plane for motion is not properly defined";}
|
||||
virtual int GetType() const {return 3002;}
|
||||
};
|
||||
|
||||
class Error_MotionPlanning_Incompatible : public Error_MotionPlanning {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Acceleration of a rectangular velocityprofile cannot be used";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 3003;
|
||||
}
|
||||
class Error_MotionPlanning_Incompatible: public Error_MotionPlanning {
|
||||
public:
|
||||
virtual const char* Description() const { return "Acceleration of a rectangular velocityprofile cannot be used";}
|
||||
virtual int GetType() const {return 3003;}
|
||||
};
|
||||
|
||||
class Error_MotionPlanning_Not_Feasible : public Error_MotionPlanning {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Motion Profile with requested parameters is not feasible";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 3004;
|
||||
}
|
||||
class Error_MotionPlanning_Not_Feasible: public Error_MotionPlanning {
|
||||
public:
|
||||
virtual const char* Description() const { return "Motion Profile with requested parameters is not feasible";}
|
||||
virtual int GetType() const {return 3004;}
|
||||
};
|
||||
|
||||
class Error_MotionPlanning_Not_Applicable : public Error_MotionPlanning {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Method is not applicable for this derived object";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 3004;
|
||||
}
|
||||
class Error_MotionPlanning_Not_Applicable: public Error_MotionPlanning {
|
||||
public:
|
||||
virtual const char* Description() const { return "Method is not applicable for this derived object";}
|
||||
virtual int GetType() const {return 3004;}
|
||||
};
|
||||
//! Abstract subclass of all errors that can be thrown by Adaptive_Integrator
|
||||
class Error_Integrator : public Error {};
|
||||
|
||||
//! Error_Stepsize_Underflow is thrown if the stepsize becomes to small
|
||||
class Error_Stepsize_Underflow : public Error_Integrator {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Stepsize Underflow";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 4001;
|
||||
}
|
||||
class Error_Stepsize_Underflow : public Error_Integrator {
|
||||
public:
|
||||
virtual const char* Description() const { return "Stepsize Underflow";}
|
||||
virtual int GetType() const {return 4001;}
|
||||
};
|
||||
|
||||
//! Error_To_Many_Steps is thrown if the number of steps needed to
|
||||
//! integrate to the desired accuracy becomes to big.
|
||||
class Error_To_Many_Steps : public Error_Integrator {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "To many steps";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 4002;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const { return "To many steps"; }
|
||||
virtual int GetType() const {return 4002;}
|
||||
};
|
||||
|
||||
//! Error_Stepsize_To_Small is thrown if the stepsize becomes to small
|
||||
//! Error_Stepsize_To_Small is thrown if the stepsize becomes to small
|
||||
class Error_Stepsize_To_Small : public Error_Integrator {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Stepsize to small";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 4003;
|
||||
}
|
||||
public:
|
||||
virtual const char* Description() const { return "Stepsize to small"; }
|
||||
virtual int GetType() const {return 4003;}
|
||||
};
|
||||
|
||||
class Error_Criterium : public Error {};
|
||||
|
||||
class Error_Criterium_Unexpected_id : public Error_Criterium {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Unexpected identifier while reading a criterium";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 5001;
|
||||
}
|
||||
class Error_Criterium_Unexpected_id: public Error_Criterium {
|
||||
public:
|
||||
virtual const char* Description() const { return "Unexpected identifier while reading a criterium"; }
|
||||
virtual int GetType() const {return 5001;}
|
||||
};
|
||||
|
||||
class Error_Limits : public Error {};
|
||||
|
||||
class Error_Limits_Unexpected_id : public Error_Limits {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "Unexpected identifier while reading a jointlimits";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 6001;
|
||||
}
|
||||
class Error_Limits_Unexpected_id: public Error_Limits {
|
||||
public:
|
||||
virtual const char* Description() const { return "Unexpected identifier while reading a jointlimits"; }
|
||||
virtual int GetType() const {return 6001;}
|
||||
};
|
||||
|
||||
class Error_Not_Implemented : public Error {
|
||||
public:
|
||||
virtual const char *Description() const
|
||||
{
|
||||
return "The requested object/method/function is not implemented";
|
||||
}
|
||||
virtual int GetType() const
|
||||
{
|
||||
return 7000;
|
||||
}
|
||||
|
||||
class Error_Not_Implemented: public Error {
|
||||
public:
|
||||
virtual const char* Description() const { return "The requested object/method/function is not implemented"; }
|
||||
virtual int GetType() const {return 7000;}
|
||||
};
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,57 +4,57 @@
|
||||
/*****************************************************************************
|
||||
* Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
*
|
||||
* \version
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
* \par History
|
||||
* - $log$
|
||||
*
|
||||
* \par Release
|
||||
* $Name: $
|
||||
* $Name: $
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "error_stack.h"
|
||||
#include <cstring>
|
||||
#include <stack>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
|
||||
namespace KDL {
|
||||
|
||||
// Trace of the call stack of the I/O routines to help user
|
||||
// interprete error messages from I/O
|
||||
typedef std::stack<std::string> ErrorStack;
|
||||
typedef std::stack<std::string> ErrorStack;
|
||||
|
||||
ErrorStack errorstack;
|
||||
// should be in Thread Local Storage if this gets multithreaded one day...
|
||||
|
||||
void IOTrace(const std::string &description)
|
||||
{
|
||||
errorstack.push(description);
|
||||
|
||||
void IOTrace(const std::string& description) {
|
||||
errorstack.push(description);
|
||||
}
|
||||
|
||||
void IOTracePop()
|
||||
{
|
||||
errorstack.pop();
|
||||
}
|
||||
|
||||
void IOTraceOutput(std::ostream &os)
|
||||
{
|
||||
while (!errorstack.empty()) {
|
||||
os << errorstack.top().c_str() << std::endl;
|
||||
void IOTracePop() {
|
||||
errorstack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void IOTracePopStr(char *buffer, int size)
|
||||
{
|
||||
if (errorstack.empty()) {
|
||||
*buffer = 0;
|
||||
return;
|
||||
}
|
||||
strncpy(buffer, errorstack.top().c_str(), size);
|
||||
errorstack.pop();
|
||||
void IOTraceOutput(std::ostream& os) {
|
||||
while (!errorstack.empty()) {
|
||||
os << errorstack.top().c_str() << std::endl;
|
||||
errorstack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
void IOTracePopStr(char* buffer,int size) {
|
||||
if (errorstack.empty()) {
|
||||
*buffer = 0;
|
||||
return;
|
||||
}
|
||||
strncpy(buffer,errorstack.top().c_str(),size);
|
||||
errorstack.pop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/***************************************************************************
|
||||
tag: Erwin Aertbelien Mon Jan 10 16:38:39 CET 2005 error_stack.h
|
||||
tag: Erwin Aertbelien Mon Jan 10 16:38:39 CET 2005 error_stack.h
|
||||
|
||||
error_stack.h - description
|
||||
-------------------
|
||||
begin : Mon January 10 2005
|
||||
copyright : (C) 2005 Erwin Aertbelien
|
||||
email : erwin.aertbelien@mech.kuleuven.ac.be
|
||||
|
||||
|
||||
***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or *
|
||||
* modify it under the terms of the GNU Lesser General Public *
|
||||
@@ -24,12 +24,13 @@
|
||||
* Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \version
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
*
|
||||
* \par history
|
||||
* - changed layout of the comments to accommodate doxygen
|
||||
*/
|
||||
@@ -40,6 +41,7 @@
|
||||
#include "utility_io.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/*
|
||||
@@ -47,18 +49,21 @@ namespace KDL {
|
||||
* IOTrace-routines store in static memory, should be in thread-local memory.
|
||||
* pushes a description of the current routine on the IO-stack trace
|
||||
*/
|
||||
void IOTrace(const std::string &description);
|
||||
void IOTrace(const std::string& description);
|
||||
|
||||
//! pops a description of the IO-stack
|
||||
void IOTracePop();
|
||||
|
||||
|
||||
//! outputs the IO-stack to a stream to provide a better errormessage.
|
||||
void IOTraceOutput(std::ostream &os);
|
||||
void IOTraceOutput(std::ostream& os);
|
||||
|
||||
//! outputs one element of the IO-stack to the buffer (maximally size chars)
|
||||
//! returns empty string if no elements on the stack.
|
||||
void IOTracePopStr(char *buffer, int size);
|
||||
void IOTracePopStr(char* buffer,int size);
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
/* License along with this library; if not, write to the Free Software */
|
||||
/* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
|
||||
/* Methods are inlined */
|
||||
#define KDL_INLINE 1
|
||||
|
||||
|
||||
@@ -1,461 +1,476 @@
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
* \file
|
||||
* class for automatic differentiation on scalar values and 1st
|
||||
* \file
|
||||
* class for automatic differentiation on scalar values and 1st
|
||||
* derivatives .
|
||||
*
|
||||
*
|
||||
* Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
*
|
||||
* \version
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
* \par Note
|
||||
* VC6++ contains a bug, concerning the use of inlined friend functions
|
||||
* in combination with namespaces. So, try to avoid inlined friend
|
||||
* functions !
|
||||
* VC6++ contains a bug, concerning the use of inlined friend functions
|
||||
* in combination with namespaces. So, try to avoid inlined friend
|
||||
* functions !
|
||||
*
|
||||
* \par History
|
||||
* - $log$
|
||||
* - $log$
|
||||
*
|
||||
* \par Release
|
||||
* $Name: $
|
||||
* $Name: $
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#ifndef Rall1D_H
|
||||
#define Rall1D_H
|
||||
#include "utility.h"
|
||||
#include <assert.h>
|
||||
#include "utility.h"
|
||||
|
||||
namespace KDL {
|
||||
/**
|
||||
* Rall1d contains a value, and its gradient, and defines an algebraic structure on this pair.
|
||||
* This template class has 3 template parameters :
|
||||
* - T contains the type of the value.
|
||||
* - V contains the type of the gradient (can be a vector-like type).
|
||||
* - S defines a scalar type that can operate on Rall1d. This is the type that
|
||||
* is used to give back values of Norm() etc.
|
||||
* - V contains the type of the gradient (can be a vector-like type).
|
||||
* - S defines a scalar type that can operate on Rall1d. This is the type that
|
||||
* is used to give back values of Norm() etc.
|
||||
*
|
||||
* S is usefull when you recurse a Rall1d object into itself to create a 2nd, 3th, 4th,..
|
||||
* S is usefull when you recurse a Rall1d object into itself to create a 2nd, 3th, 4th,..
|
||||
* derivatives. (e.g. Rall1d< Rall1d<double>, Rall1d<double>, double> ).
|
||||
*
|
||||
* S is always passed by value.
|
||||
* S is always passed by value.
|
||||
*
|
||||
* \par Class Type
|
||||
* Concrete implementation
|
||||
*/
|
||||
template<typename T, typename V = T, typename S = T> class Rall1d {
|
||||
public:
|
||||
typedef T valuetype;
|
||||
typedef V gradienttype;
|
||||
typedef S scalartype;
|
||||
template <typename T,typename V=T,typename S=T>
|
||||
class Rall1d
|
||||
{
|
||||
public:
|
||||
typedef T valuetype;
|
||||
typedef V gradienttype;
|
||||
typedef S scalartype;
|
||||
public :
|
||||
T t; //!< value
|
||||
V grad; //!< gradient
|
||||
public :
|
||||
INLINE Rall1d() {}
|
||||
|
||||
public:
|
||||
T t; //!< value
|
||||
V grad; //!< gradient
|
||||
public:
|
||||
INLINE Rall1d() {}
|
||||
T value() const {
|
||||
return t;
|
||||
}
|
||||
V deriv() const {
|
||||
return grad;
|
||||
}
|
||||
|
||||
T value() const
|
||||
{
|
||||
return t;
|
||||
}
|
||||
V deriv() const
|
||||
{
|
||||
return grad;
|
||||
}
|
||||
explicit INLINE Rall1d(typename TI<T>::Arg c)
|
||||
{t=T(c);SetToZero(grad);}
|
||||
|
||||
explicit INLINE Rall1d(typename TI<T>::Arg c)
|
||||
{
|
||||
t = T(c);
|
||||
SetToZero(grad);
|
||||
}
|
||||
INLINE Rall1d(typename TI<T>::Arg tn, typename TI<V>::Arg afg):t(tn),grad(afg) {}
|
||||
|
||||
INLINE Rall1d(typename TI<T>::Arg tn, typename TI<V>::Arg afg) : t(tn), grad(afg) {}
|
||||
INLINE Rall1d(const Rall1d<T,V,S>& r):t(r.t),grad(r.grad) {}
|
||||
//if one defines this constructor, it's better optimized then the
|
||||
//automatically generated one ( this one set's up a loop to copy
|
||||
// word by word.
|
||||
|
||||
INLINE T& Value() {
|
||||
return t;
|
||||
}
|
||||
|
||||
INLINE Rall1d(const Rall1d<T, V, S> &r) : t(r.t), grad(r.grad) {}
|
||||
// if one defines this constructor, it's better optimized then the
|
||||
// automatically generated one ( this one set's up a loop to copy
|
||||
// word by word.
|
||||
INLINE V& Gradient() {
|
||||
return grad;
|
||||
}
|
||||
|
||||
INLINE T &Value()
|
||||
{
|
||||
return t;
|
||||
}
|
||||
INLINE static Rall1d<T,V,S> Zero() {
|
||||
Rall1d<T,V,S> tmp;
|
||||
SetToZero(tmp);
|
||||
return tmp;
|
||||
}
|
||||
INLINE static Rall1d<T,V,S> Identity() {
|
||||
Rall1d<T,V,S> tmp;
|
||||
SetToIdentity(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
INLINE V &Gradient()
|
||||
{
|
||||
return grad;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator =(S c)
|
||||
{t=c;SetToZero(grad);return *this;}
|
||||
|
||||
INLINE static Rall1d<T, V, S> Zero()
|
||||
{
|
||||
Rall1d<T, V, S> tmp;
|
||||
SetToZero(tmp);
|
||||
return tmp;
|
||||
}
|
||||
INLINE static Rall1d<T, V, S> Identity()
|
||||
{
|
||||
Rall1d<T, V, S> tmp;
|
||||
SetToIdentity(tmp);
|
||||
return tmp;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator =(const Rall1d<T,V,S>& r)
|
||||
{t=r.t;grad=r.grad;return *this;}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator=(S c)
|
||||
{
|
||||
t = c;
|
||||
SetToZero(grad);
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator /=(const Rall1d<T,V,S>& rhs)
|
||||
{
|
||||
grad = LinComb(rhs.t,grad,-t,rhs.grad) / (rhs.t*rhs.t);
|
||||
t /= rhs.t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator=(const Rall1d<T, V, S> &r)
|
||||
{
|
||||
t = r.t;
|
||||
grad = r.grad;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator *=(const Rall1d<T,V,S>& rhs)
|
||||
{
|
||||
LinCombR(rhs.t,grad,t,rhs.grad,grad);
|
||||
t *= rhs.t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator/=(const Rall1d<T, V, S> &rhs)
|
||||
{
|
||||
grad = LinComb(rhs.t, grad, -t, rhs.grad) / (rhs.t * rhs.t);
|
||||
t /= rhs.t;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator +=(const Rall1d<T,V,S>& rhs)
|
||||
{
|
||||
grad +=rhs.grad;
|
||||
t +=rhs.t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator*=(const Rall1d<T, V, S> &rhs)
|
||||
{
|
||||
LinCombR(rhs.t, grad, t, rhs.grad, grad);
|
||||
t *= rhs.t;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator -=(const Rall1d<T,V,S>& rhs)
|
||||
{
|
||||
grad -= rhs.grad;
|
||||
t -= rhs.t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator+=(const Rall1d<T, V, S> &rhs)
|
||||
{
|
||||
grad += rhs.grad;
|
||||
t += rhs.t;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator /=(S rhs)
|
||||
{
|
||||
grad /= rhs;
|
||||
t /= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator-=(const Rall1d<T, V, S> &rhs)
|
||||
{
|
||||
grad -= rhs.grad;
|
||||
t -= rhs.t;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator *=(S rhs)
|
||||
{
|
||||
grad *= rhs;
|
||||
t *= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator/=(S rhs)
|
||||
{
|
||||
grad /= rhs;
|
||||
t /= rhs;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator +=(S rhs)
|
||||
{
|
||||
t += rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator*=(S rhs)
|
||||
{
|
||||
grad *= rhs;
|
||||
t *= rhs;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall1d<T,V,S>& operator -=(S rhs)
|
||||
{
|
||||
t -= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator+=(S rhs)
|
||||
{
|
||||
t += rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall1d<T, V, S> &operator-=(S rhs)
|
||||
{
|
||||
t -= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// = operators
|
||||
/* gives warnings on cygwin
|
||||
// = operators
|
||||
/* gives warnings on cygwin
|
||||
|
||||
template <class T2,class V2,class S2>
|
||||
friend INLINE Rall1d<T2,V2,S2> operator /(const Rall1d<T2,V2,S2>& lhs,const Rall1d<T2,V2,S2>& rhs);
|
||||
|
||||
friend INLINE Rall1d<T,V,S> operator *(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs);
|
||||
friend INLINE Rall1d<T,V,S> operator +(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs);
|
||||
friend INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs);
|
||||
friend INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> operator *(S s,const Rall1d<T,V,S>& v);
|
||||
friend INLINE Rall1d<T,V,S> operator *(const Rall1d<T,V,S>& v,S s);
|
||||
friend INLINE Rall1d<T,V,S> operator +(S s,const Rall1d<T,V,S>& v);
|
||||
friend INLINE Rall1d<T,V,S> operator +(const Rall1d<T,V,S>& v,S s);
|
||||
friend INLINE Rall1d<T,V,S> operator -(S s,const Rall1d<T,V,S>& v);
|
||||
friend INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& v,S s);
|
||||
friend INLINE Rall1d<T,V,S> operator /(S s,const Rall1d<T,V,S>& v);
|
||||
friend INLINE Rall1d<T,V,S> operator /(const Rall1d<T,V,S>& v,S s);
|
||||
|
||||
template <class T2,class V2,class S2>
|
||||
friend INLINE Rall1d<T2,V2,S2> operator /(const Rall1d<T2,V2,S2>& lhs,const Rall1d<T2,V2,S2>&
|
||||
rhs);
|
||||
// = Mathematical functions that operate on Rall1d objects
|
||||
friend INLINE Rall1d<T,V,S> exp(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> log(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> sin(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> cos(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> tan(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> sinh(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> cosh(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> sqr(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> pow(const Rall1d<T,V,S>& arg,double m) ;
|
||||
friend INLINE Rall1d<T,V,S> sqrt(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> atan(const Rall1d<T,V,S>& x);
|
||||
friend INLINE Rall1d<T,V,S> hypot(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x);
|
||||
friend INLINE Rall1d<T,V,S> asin(const Rall1d<T,V,S>& x);
|
||||
friend INLINE Rall1d<T,V,S> acos(const Rall1d<T,V,S>& x);
|
||||
friend INLINE Rall1d<T,V,S> abs(const Rall1d<T,V,S>& x);
|
||||
friend INLINE S Norm(const Rall1d<T,V,S>& value) ;
|
||||
friend INLINE Rall1d<T,V,S> tanh(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> atan2(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x);
|
||||
|
||||
// = Utility functions to improve performance
|
||||
|
||||
friend INLINE Rall1d<T,V,S> operator *(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs);
|
||||
friend INLINE Rall1d<T,V,S> operator +(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs);
|
||||
friend INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs);
|
||||
friend INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> operator *(S s,const Rall1d<T,V,S>& v);
|
||||
friend INLINE Rall1d<T,V,S> operator *(const Rall1d<T,V,S>& v,S s);
|
||||
friend INLINE Rall1d<T,V,S> operator +(S s,const Rall1d<T,V,S>& v);
|
||||
friend INLINE Rall1d<T,V,S> operator +(const Rall1d<T,V,S>& v,S s);
|
||||
friend INLINE Rall1d<T,V,S> operator -(S s,const Rall1d<T,V,S>& v);
|
||||
friend INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& v,S s);
|
||||
friend INLINE Rall1d<T,V,S> operator /(S s,const Rall1d<T,V,S>& v);
|
||||
friend INLINE Rall1d<T,V,S> operator /(const Rall1d<T,V,S>& v,S s);
|
||||
friend INLINE Rall1d<T,V,S> LinComb(S alfa,const Rall1d<T,V,S>& a,
|
||||
const T& beta,const Rall1d<T,V,S>& b );
|
||||
|
||||
friend INLINE void LinCombR(S alfa,const Rall1d<T,V,S>& a,
|
||||
const T& beta,const Rall1d<T,V,S>& b,Rall1d<T,V,S>& result );
|
||||
|
||||
// = Setting value of a Rall1d object to 0 or 1
|
||||
|
||||
// = Mathematical functions that operate on Rall1d objects
|
||||
friend INLINE Rall1d<T,V,S> exp(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> log(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> sin(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> cos(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> tan(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> sinh(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> cosh(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> sqr(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> pow(const Rall1d<T,V,S>& arg,double m) ;
|
||||
friend INLINE Rall1d<T,V,S> sqrt(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> atan(const Rall1d<T,V,S>& x);
|
||||
friend INLINE Rall1d<T,V,S> hypot(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x);
|
||||
friend INLINE Rall1d<T,V,S> asin(const Rall1d<T,V,S>& x);
|
||||
friend INLINE Rall1d<T,V,S> acos(const Rall1d<T,V,S>& x);
|
||||
friend INLINE Rall1d<T,V,S> abs(const Rall1d<T,V,S>& x);
|
||||
friend INLINE S Norm(const Rall1d<T,V,S>& value) ;
|
||||
friend INLINE Rall1d<T,V,S> tanh(const Rall1d<T,V,S>& arg);
|
||||
friend INLINE Rall1d<T,V,S> atan2(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x);
|
||||
friend INLINE void SetToZero(Rall1d<T,V,S>& value);
|
||||
friend INLINE void SetToOne(Rall1d<T,V,S>& value);
|
||||
// = Equality in an eps-interval
|
||||
friend INLINE bool Equal(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x,double eps);
|
||||
*/
|
||||
};
|
||||
|
||||
// = Utility functions to improve performance
|
||||
|
||||
friend INLINE Rall1d<T,V,S> LinComb(S alfa,const Rall1d<T,V,S>& a,
|
||||
const T& beta,const Rall1d<T,V,S>& b );
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator /(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs)
|
||||
{
|
||||
return Rall1d<T,V,S>(lhs.t/rhs.t,(lhs.grad*rhs.t-lhs.t*rhs.grad)/(rhs.t*rhs.t));
|
||||
}
|
||||
|
||||
friend INLINE void LinCombR(S alfa,const Rall1d<T,V,S>& a,
|
||||
const T& beta,const Rall1d<T,V,S>& b,Rall1d<T,V,S>& result );
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator *(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs)
|
||||
{
|
||||
return Rall1d<T,V,S>(lhs.t*rhs.t,rhs.t*lhs.grad+lhs.t*rhs.grad);
|
||||
}
|
||||
|
||||
// = Setting value of a Rall1d object to 0 or 1
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator +(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs)
|
||||
{
|
||||
return Rall1d<T,V,S>(lhs.t+rhs.t,lhs.grad+rhs.grad);
|
||||
}
|
||||
|
||||
friend INLINE void SetToZero(Rall1d<T,V,S>& value);
|
||||
friend INLINE void SetToOne(Rall1d<T,V,S>& value);
|
||||
// = Equality in an eps-interval
|
||||
friend INLINE bool Equal(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x,double eps);
|
||||
*/
|
||||
};
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall1d<T, V, S> operator/(const Rall1d<T, V, S> &lhs, const Rall1d<T, V, S> &rhs)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& lhs,const Rall1d<T,V,S>& rhs)
|
||||
{
|
||||
return Rall1d<T,V,S>(lhs.t-rhs.t,lhs.grad-rhs.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
return Rall1d<T,V,S>(-arg.t,-arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator *(S s,const Rall1d<T,V,S>& v)
|
||||
{
|
||||
return Rall1d<T,V,S>(s*v.t,s*v.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator *(const Rall1d<T,V,S>& v,S s)
|
||||
{
|
||||
return Rall1d<T,V,S>(v.t*s,v.grad*s);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator +(S s,const Rall1d<T,V,S>& v)
|
||||
{
|
||||
return Rall1d<T,V,S>(s+v.t,v.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator +(const Rall1d<T,V,S>& v,S s)
|
||||
{
|
||||
return Rall1d<T,V,S>(v.t+s,v.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator -(S s,const Rall1d<T,V,S>& v)
|
||||
{
|
||||
return Rall1d<T,V,S>(s-v.t,-v.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator -(const Rall1d<T,V,S>& v,S s)
|
||||
{
|
||||
return Rall1d<T,V,S>(v.t-s,v.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator /(S s,const Rall1d<T,V,S>& v)
|
||||
{
|
||||
return Rall1d<T,V,S>(s/v.t,(-s*v.grad)/(v.t*v.t));
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> operator /(const Rall1d<T,V,S>& v,S s)
|
||||
{
|
||||
return Rall1d<T,V,S>(v.t/s,v.grad/s);
|
||||
}
|
||||
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> exp(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v= (exp(arg.t));
|
||||
return Rall1d<T,V,S>(v,v*arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> log(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v=(log(arg.t));
|
||||
return Rall1d<T,V,S>(v,arg.grad/arg.t);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> sin(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v=(sin(arg.t));
|
||||
return Rall1d<T,V,S>(v,cos(arg.t)*arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> cos(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v=(cos(arg.t));
|
||||
return Rall1d<T,V,S>(v,-sin(arg.t)*arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> tan(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v=(tan(arg.t));
|
||||
return Rall1d<T,V,S>(v,arg.grad/sqr(cos(arg.t)));
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> sinh(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v=(sinh(arg.t));
|
||||
return Rall1d<T,V,S>(v,cosh(arg.t)*arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> cosh(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v=(cosh(arg.t));
|
||||
return Rall1d<T,V,S>(v,sinh(arg.t)*arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> sqr(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v=(arg.t*arg.t);
|
||||
return Rall1d<T,V,S>(v,(2.0*arg.t)*arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> pow(const Rall1d<T,V,S>& arg,double m)
|
||||
{
|
||||
T v;
|
||||
v=(pow(arg.t,m));
|
||||
return Rall1d<T,V,S>(v,(m*v/arg.t)*arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> sqrt(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v;
|
||||
v=sqrt(arg.t);
|
||||
return Rall1d<T,V,S>(v, (0.5/v)*arg.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> atan(const Rall1d<T,V,S>& x)
|
||||
{
|
||||
return Rall1d<T, V, S>(lhs.t / rhs.t, (lhs.grad * rhs.t - lhs.t * rhs.grad) / (rhs.t * rhs.t));
|
||||
T v;
|
||||
v=(atan(x.t));
|
||||
return Rall1d<T,V,S>(v,x.grad/(1.0+sqr(x.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall1d<T, V, S> operator*(const Rall1d<T, V, S> &lhs, const Rall1d<T, V, S> &rhs)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> hypot(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x)
|
||||
{
|
||||
return Rall1d<T, V, S>(lhs.t * rhs.t, rhs.t * lhs.grad + lhs.t * rhs.grad);
|
||||
T v;
|
||||
v=(hypot(y.t,x.t));
|
||||
return Rall1d<T,V,S>(v,(x.t/v)*x.grad+(y.t/v)*y.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall1d<T, V, S> operator+(const Rall1d<T, V, S> &lhs, const Rall1d<T, V, S> &rhs)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> asin(const Rall1d<T,V,S>& x)
|
||||
{
|
||||
return Rall1d<T, V, S>(lhs.t + rhs.t, lhs.grad + rhs.grad);
|
||||
T v;
|
||||
v=(asin(x.t));
|
||||
return Rall1d<T,V,S>(v,x.grad/sqrt(1.0-sqr(x.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall1d<T, V, S> operator-(const Rall1d<T, V, S> &lhs, const Rall1d<T, V, S> &rhs)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> acos(const Rall1d<T,V,S>& x)
|
||||
{
|
||||
return Rall1d<T, V, S>(lhs.t - rhs.t, lhs.grad - rhs.grad);
|
||||
T v;
|
||||
v=(acos(x.t));
|
||||
return Rall1d<T,V,S>(v,-x.grad/sqrt(1.0-sqr(x.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator-(const Rall1d<T, V, S> &arg)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> abs(const Rall1d<T,V,S>& x)
|
||||
{
|
||||
return Rall1d<T, V, S>(-arg.t, -arg.grad);
|
||||
T v;
|
||||
v=(Sign(x));
|
||||
return Rall1d<T,V,S>(v*x,v*x.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator*(S s, const Rall1d<T, V, S> &v)
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE S Norm(const Rall1d<T,V,S>& value)
|
||||
{
|
||||
return Rall1d<T, V, S>(s * v.t, s * v.grad);
|
||||
return Norm(value.t);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator*(const Rall1d<T, V, S> &v, S s)
|
||||
{
|
||||
return Rall1d<T, V, S>(v.t * s, v.grad * s);
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> tanh(const Rall1d<T,V,S>& arg)
|
||||
{
|
||||
T v(tanh(arg.t));
|
||||
return Rall1d<T,V,S>(v,arg.grad/sqr(cosh(arg.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator+(S s, const Rall1d<T, V, S> &v)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> atan2(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x)
|
||||
{
|
||||
return Rall1d<T, V, S>(s + v.t, v.grad);
|
||||
T v(x.t*x.t+y.t*y.t);
|
||||
return Rall1d<T,V,S>(atan2(y.t,x.t),(x.t*y.grad-y.t*x.grad)/v);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator+(const Rall1d<T, V, S> &v, S s)
|
||||
{
|
||||
return Rall1d<T, V, S>(v.t + s, v.grad);
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall1d<T,V,S> LinComb(S alfa,const Rall1d<T,V,S>& a,
|
||||
const T& beta,const Rall1d<T,V,S>& b ) {
|
||||
return Rall1d<T,V,S>(
|
||||
LinComb(alfa,a.t,beta,b.t),
|
||||
LinComb(alfa,a.grad,beta,b.grad)
|
||||
);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator-(S s, const Rall1d<T, V, S> &v)
|
||||
{
|
||||
return Rall1d<T, V, S>(s - v.t, -v.grad);
|
||||
template <class T,class V,class S>
|
||||
INLINE void LinCombR(S alfa,const Rall1d<T,V,S>& a,
|
||||
const T& beta,const Rall1d<T,V,S>& b,Rall1d<T,V,S>& result ) {
|
||||
LinCombR(alfa, a.t, beta, b.t, result.t);
|
||||
LinCombR(alfa, a.grad, beta, b.grad, result.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator-(const Rall1d<T, V, S> &v, S s)
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE void SetToZero(Rall1d<T,V,S>& value)
|
||||
{
|
||||
SetToZero(value.grad);
|
||||
SetToZero(value.t);
|
||||
}
|
||||
template <class T,class V,class S>
|
||||
INLINE void SetToIdentity(Rall1d<T,V,S>& value)
|
||||
{
|
||||
SetToIdentity(value.t);
|
||||
SetToZero(value.grad);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE bool Equal(const Rall1d<T,V,S>& y,const Rall1d<T,V,S>& x,double eps=epsilon)
|
||||
{
|
||||
return Rall1d<T, V, S>(v.t - s, v.grad);
|
||||
return (Equal(x.t,y.t,eps)&&Equal(x.grad,y.grad,eps));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator/(S s, const Rall1d<T, V, S> &v)
|
||||
{
|
||||
return Rall1d<T, V, S>(s / v.t, (-s * v.grad) / (v.t * v.t));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> operator/(const Rall1d<T, V, S> &v, S s)
|
||||
{
|
||||
return Rall1d<T, V, S>(v.t / s, v.grad / s);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> exp(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = (exp(arg.t));
|
||||
return Rall1d<T, V, S>(v, v * arg.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> log(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = (log(arg.t));
|
||||
return Rall1d<T, V, S>(v, arg.grad / arg.t);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> sin(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = (sin(arg.t));
|
||||
return Rall1d<T, V, S>(v, cos(arg.t) * arg.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> cos(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = (cos(arg.t));
|
||||
return Rall1d<T, V, S>(v, -sin(arg.t) * arg.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> tan(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = (tan(arg.t));
|
||||
return Rall1d<T, V, S>(v, arg.grad / sqr(cos(arg.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> sinh(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = (sinh(arg.t));
|
||||
return Rall1d<T, V, S>(v, cosh(arg.t) * arg.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> cosh(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = (cosh(arg.t));
|
||||
return Rall1d<T, V, S>(v, sinh(arg.t) * arg.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> sqr(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = (arg.t * arg.t);
|
||||
return Rall1d<T, V, S>(v, (2.0 * arg.t) * arg.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall1d<T, V, S> pow(const Rall1d<T, V, S> &arg, double m)
|
||||
{
|
||||
T v;
|
||||
v = (pow(arg.t, m));
|
||||
return Rall1d<T, V, S>(v, (m * v / arg.t) * arg.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> sqrt(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v;
|
||||
v = sqrt(arg.t);
|
||||
return Rall1d<T, V, S>(v, (0.5 / v) * arg.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> atan(const Rall1d<T, V, S> &x)
|
||||
{
|
||||
T v;
|
||||
v = (atan(x.t));
|
||||
return Rall1d<T, V, S>(v, x.grad / (1.0 + sqr(x.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall1d<T, V, S> hypot(const Rall1d<T, V, S> &y, const Rall1d<T, V, S> &x)
|
||||
{
|
||||
T v;
|
||||
v = (hypot(y.t, x.t));
|
||||
return Rall1d<T, V, S>(v, (x.t / v) * x.grad + (y.t / v) * y.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> asin(const Rall1d<T, V, S> &x)
|
||||
{
|
||||
T v;
|
||||
v = (asin(x.t));
|
||||
return Rall1d<T, V, S>(v, x.grad / sqrt(1.0 - sqr(x.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> acos(const Rall1d<T, V, S> &x)
|
||||
{
|
||||
T v;
|
||||
v = (acos(x.t));
|
||||
return Rall1d<T, V, S>(v, -x.grad / sqrt(1.0 - sqr(x.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> abs(const Rall1d<T, V, S> &x)
|
||||
{
|
||||
T v;
|
||||
v = (Sign(x));
|
||||
return Rall1d<T, V, S>(v * x, v * x.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE S Norm(const Rall1d<T, V, S> &value)
|
||||
{
|
||||
return Norm(value.t);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall1d<T, V, S> tanh(const Rall1d<T, V, S> &arg)
|
||||
{
|
||||
T v(tanh(arg.t));
|
||||
return Rall1d<T, V, S>(v, arg.grad / sqr(cosh(arg.t)));
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall1d<T, V, S> atan2(const Rall1d<T, V, S> &y, const Rall1d<T, V, S> &x)
|
||||
{
|
||||
T v(x.t * x.t + y.t * y.t);
|
||||
return Rall1d<T, V, S>(atan2(y.t, x.t), (x.t * y.grad - y.t * x.grad) / v);
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall1d<T, V, S> LinComb(S alfa,
|
||||
const Rall1d<T, V, S> &a,
|
||||
const T &beta,
|
||||
const Rall1d<T, V, S> &b)
|
||||
{
|
||||
return Rall1d<T, V, S>(LinComb(alfa, a.t, beta, b.t), LinComb(alfa, a.grad, beta, b.grad));
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE void LinCombR(S alfa,
|
||||
const Rall1d<T, V, S> &a,
|
||||
const T &beta,
|
||||
const Rall1d<T, V, S> &b,
|
||||
Rall1d<T, V, S> &result)
|
||||
{
|
||||
LinCombR(alfa, a.t, beta, b.t, result.t);
|
||||
LinCombR(alfa, a.grad, beta, b.grad, result.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE void SetToZero(Rall1d<T, V, S> &value)
|
||||
{
|
||||
SetToZero(value.grad);
|
||||
SetToZero(value.t);
|
||||
}
|
||||
template<class T, class V, class S> INLINE void SetToIdentity(Rall1d<T, V, S> &value)
|
||||
{
|
||||
SetToIdentity(value.t);
|
||||
SetToZero(value.grad);
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE bool Equal(const Rall1d<T, V, S> &y, const Rall1d<T, V, S> &x, double eps = epsilon)
|
||||
{
|
||||
return (Equal(x.t, y.t, eps) && Equal(x.grad, y.grad, eps));
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,518 +1,536 @@
|
||||
|
||||
/*****************************************************************************
|
||||
* \file
|
||||
* class for automatic differentiation on scalar values and 1st
|
||||
* \file
|
||||
* class for automatic differentiation on scalar values and 1st
|
||||
* derivatives and 2nd derivative.
|
||||
*
|
||||
*
|
||||
* Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
*
|
||||
* \version
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
* \par Note
|
||||
* VC6++ contains a bug, concerning the use of inlined friend functions
|
||||
* in combination with namespaces. So, try to avoid inlined friend
|
||||
* functions !
|
||||
* VC6++ contains a bug, concerning the use of inlined friend functions
|
||||
* in combination with namespaces. So, try to avoid inlined friend
|
||||
* functions !
|
||||
*
|
||||
* \par History
|
||||
* - $log$
|
||||
* - $log$
|
||||
*
|
||||
* \par Release
|
||||
* $Name: $
|
||||
* $Name: $
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef Rall2D_H
|
||||
#define Rall2D_H
|
||||
|
||||
#include "utility.h"
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
namespace KDL {
|
||||
|
||||
/**
|
||||
* Rall2d contains a value, and its gradient and its 2nd derivative, and defines an algebraic
|
||||
* Rall2d contains a value, and its gradient and its 2nd derivative, and defines an algebraic
|
||||
* structure on this pair.
|
||||
* This template class has 3 template parameters :
|
||||
* - T contains the type of the value.
|
||||
* - V contains the type of the gradient (can be a vector-like type).
|
||||
* - S defines a scalar type that can operate on Rall1d. This is the type that
|
||||
* is used to give back values of Norm() etc.
|
||||
* - V contains the type of the gradient (can be a vector-like type).
|
||||
* - S defines a scalar type that can operate on Rall1d. This is the type that
|
||||
* is used to give back values of Norm() etc.
|
||||
*
|
||||
* S is usefull when you recurse a Rall1d object into itself to create a 2nd, 3th, 4th,..
|
||||
* S is usefull when you recurse a Rall1d object into itself to create a 2nd, 3th, 4th,..
|
||||
* derivatives. (e.g. Rall1d< Rall1d<double>, Rall1d<double>, double> ).
|
||||
*
|
||||
* S is always passed by value.
|
||||
* S is always passed by value.
|
||||
*
|
||||
* \par Class Type
|
||||
* Concrete implementation
|
||||
*/
|
||||
template<class T, class V = T, class S = T> class Rall2d {
|
||||
public:
|
||||
T t; //!< value
|
||||
V d; //!< 1st derivative
|
||||
V dd; //!< 2nd derivative
|
||||
public:
|
||||
// = Constructors
|
||||
INLINE Rall2d() {}
|
||||
template <class T,class V=T,class S=T>
|
||||
class Rall2d
|
||||
{
|
||||
public :
|
||||
T t; //!< value
|
||||
V d; //!< 1st derivative
|
||||
V dd; //!< 2nd derivative
|
||||
public :
|
||||
// = Constructors
|
||||
INLINE Rall2d() {}
|
||||
|
||||
explicit INLINE Rall2d(typename TI<T>::Arg c)
|
||||
{
|
||||
t = c;
|
||||
SetToZero(d);
|
||||
SetToZero(dd);
|
||||
}
|
||||
explicit INLINE Rall2d(typename TI<T>::Arg c)
|
||||
{t=c;SetToZero(d);SetToZero(dd);}
|
||||
|
||||
INLINE Rall2d(typename TI<T>::Arg tn, const V &afg) : t(tn), d(afg)
|
||||
{
|
||||
SetToZero(dd);
|
||||
}
|
||||
INLINE Rall2d(typename TI<T>::Arg tn,const V& afg):t(tn),d(afg) {SetToZero(dd);}
|
||||
|
||||
INLINE Rall2d(typename TI<T>::Arg tn, const V &afg, const V &afg2) : t(tn), d(afg), dd(afg2) {}
|
||||
INLINE Rall2d(typename TI<T>::Arg tn,const V& afg,const V& afg2):t(tn),d(afg),dd(afg2) {}
|
||||
|
||||
// = Copy Constructor
|
||||
INLINE Rall2d(const Rall2d<T, V, S> &r) : t(r.t), d(r.d), dd(r.dd) {}
|
||||
// if one defines this constructor, it's better optimized then the
|
||||
// automatically generated one ( that one set's up a loop to copy
|
||||
// word by word.
|
||||
// = Copy Constructor
|
||||
INLINE Rall2d(const Rall2d<T,V,S>& r):t(r.t),d(r.d),dd(r.dd) {}
|
||||
//if one defines this constructor, it's better optimized then the
|
||||
//automatically generated one ( that one set's up a loop to copy
|
||||
// word by word.
|
||||
|
||||
// = Member functions to access internal structures :
|
||||
INLINE T& Value() {
|
||||
return t;
|
||||
}
|
||||
|
||||
// = Member functions to access internal structures :
|
||||
INLINE T &Value()
|
||||
{
|
||||
return t;
|
||||
}
|
||||
INLINE V& D() {
|
||||
return d;
|
||||
}
|
||||
|
||||
INLINE V &D()
|
||||
{
|
||||
return d;
|
||||
}
|
||||
INLINE V& DD() {
|
||||
return dd;
|
||||
}
|
||||
INLINE static Rall2d<T,V,S> Zero() {
|
||||
Rall2d<T,V,S> tmp;
|
||||
SetToZero(tmp);
|
||||
return tmp;
|
||||
}
|
||||
INLINE static Rall2d<T,V,S> Identity() {
|
||||
Rall2d<T,V,S> tmp;
|
||||
SetToIdentity(tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
INLINE V &DD()
|
||||
{
|
||||
return dd;
|
||||
}
|
||||
INLINE static Rall2d<T, V, S> Zero()
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
SetToZero(tmp);
|
||||
return tmp;
|
||||
}
|
||||
INLINE static Rall2d<T, V, S> Identity()
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
SetToIdentity(tmp);
|
||||
return tmp;
|
||||
}
|
||||
// = assignment operators
|
||||
INLINE Rall2d<T,V,S>& operator =(S c)
|
||||
{t=c;SetToZero(d);SetToZero(dd);return *this;}
|
||||
|
||||
// = assignment operators
|
||||
INLINE Rall2d<T, V, S> &operator=(S c)
|
||||
{
|
||||
t = c;
|
||||
SetToZero(d);
|
||||
SetToZero(dd);
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator =(const Rall2d<T,V,S>& r)
|
||||
{t=r.t;d=r.d;dd=r.dd;return *this;}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator=(const Rall2d<T, V, S> &r)
|
||||
{
|
||||
t = r.t;
|
||||
d = r.d;
|
||||
dd = r.dd;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator /=(const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
t /= rhs.t;
|
||||
d = (d-t*rhs.d)/rhs.t;
|
||||
dd= (dd - S(2)*d*rhs.d-t*rhs.dd)/rhs.t;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator/=(const Rall2d<T, V, S> &rhs)
|
||||
{
|
||||
t /= rhs.t;
|
||||
d = (d - t * rhs.d) / rhs.t;
|
||||
dd = (dd - S(2) * d * rhs.d - t * rhs.dd) / rhs.t;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator *=(const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
t *= rhs.t;
|
||||
d = (d*rhs.t+t*rhs.d);
|
||||
dd = (dd*rhs.t+S(2)*d*rhs.d+t*rhs.dd);
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator*=(const Rall2d<T, V, S> &rhs)
|
||||
{
|
||||
t *= rhs.t;
|
||||
d = (d * rhs.t + t * rhs.d);
|
||||
dd = (dd * rhs.t + S(2) * d * rhs.d + t * rhs.dd);
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator +=(const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
t +=rhs.t;
|
||||
d +=rhs.d;
|
||||
dd+=rhs.dd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator+=(const Rall2d<T, V, S> &rhs)
|
||||
{
|
||||
t += rhs.t;
|
||||
d += rhs.d;
|
||||
dd += rhs.dd;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator -=(const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
t -= rhs.t;
|
||||
d -= rhs.d;
|
||||
dd -= rhs.dd;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator-=(const Rall2d<T, V, S> &rhs)
|
||||
{
|
||||
t -= rhs.t;
|
||||
d -= rhs.d;
|
||||
dd -= rhs.dd;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator /=(S rhs)
|
||||
{
|
||||
t /= rhs;
|
||||
d /= rhs;
|
||||
dd /= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator/=(S rhs)
|
||||
{
|
||||
t /= rhs;
|
||||
d /= rhs;
|
||||
dd /= rhs;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator *=(S rhs)
|
||||
{
|
||||
t *= rhs;
|
||||
d *= rhs;
|
||||
dd *= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator*=(S rhs)
|
||||
{
|
||||
t *= rhs;
|
||||
d *= rhs;
|
||||
dd *= rhs;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator -=(S rhs)
|
||||
{
|
||||
t -= rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator-=(S rhs)
|
||||
{
|
||||
t -= rhs;
|
||||
return *this;
|
||||
}
|
||||
INLINE Rall2d<T,V,S>& operator +=(S rhs)
|
||||
{
|
||||
t += rhs;
|
||||
return *this;
|
||||
}
|
||||
|
||||
INLINE Rall2d<T, V, S> &operator+=(S rhs)
|
||||
{
|
||||
t += rhs;
|
||||
return *this;
|
||||
}
|
||||
// = Operators between Rall2d objects
|
||||
/*
|
||||
friend INLINE Rall2d<T,V,S> operator /(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>& rhs);
|
||||
friend INLINE Rall2d<T,V,S> operator *(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>& rhs);
|
||||
friend INLINE Rall2d<T,V,S> operator +(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>& rhs);
|
||||
friend INLINE Rall2d<T,V,S> operator -(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>& rhs);
|
||||
friend INLINE Rall2d<T,V,S> operator -(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> operator *(S s,const Rall2d<T,V,S>& v);
|
||||
friend INLINE Rall2d<T,V,S> operator *(const Rall2d<T,V,S>& v,S s);
|
||||
friend INLINE Rall2d<T,V,S> operator +(S s,const Rall2d<T,V,S>& v);
|
||||
friend INLINE Rall2d<T,V,S> operator +(const Rall2d<T,V,S>& v,S s);
|
||||
friend INLINE Rall2d<T,V,S> operator -(S s,const Rall2d<T,V,S>& v);
|
||||
friend INLINE Rall2d<T,V,S> operator -(const Rall2d<T,V,S>& v,S s);
|
||||
friend INLINE Rall2d<T,V,S> operator /(S s,const Rall2d<T,V,S>& v);
|
||||
friend INLINE Rall2d<T,V,S> operator /(const Rall2d<T,V,S>& v,S s);
|
||||
|
||||
// = Mathematical functions that operate on Rall2d objects
|
||||
|
||||
friend INLINE Rall2d<T,V,S> exp(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> log(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> sin(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> cos(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> tan(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> sinh(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> cosh(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> tanh(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> sqr(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> pow(const Rall2d<T,V,S>& arg,double m) ;
|
||||
friend INLINE Rall2d<T,V,S> sqrt(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> asin(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> acos(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> atan(const Rall2d<T,V,S>& x);
|
||||
friend INLINE Rall2d<T,V,S> atan2(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x);
|
||||
friend INLINE Rall2d<T,V,S> abs(const Rall2d<T,V,S>& x);
|
||||
friend INLINE Rall2d<T,V,S> hypot(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x);
|
||||
// returns sqrt(y*y+x*x), but is optimized for accuracy and speed.
|
||||
friend INLINE S Norm(const Rall2d<T,V,S>& value) ;
|
||||
// returns Norm( value.Value() ).
|
||||
|
||||
// = Some utility functions to improve performance
|
||||
// (should also be declared on primitive types to improve uniformity
|
||||
friend INLINE Rall2d<T,V,S> LinComb(S alfa,const Rall2d<T,V,S>& a,
|
||||
TI<T>::Arg beta,const Rall2d<T,V,S>& b );
|
||||
friend INLINE void LinCombR(S alfa,const Rall2d<T,V,S>& a,
|
||||
TI<T>::Arg beta,const Rall2d<T,V,S>& b,Rall2d<T,V,S>& result );
|
||||
// = Setting value of a Rall2d object to 0 or 1
|
||||
friend INLINE void SetToZero(Rall2d<T,V,S>& value);
|
||||
friend INLINE void SetToOne(Rall2d<T,V,S>& value);
|
||||
// = Equality in an eps-interval
|
||||
friend INLINE bool Equal(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x,double eps);
|
||||
*/
|
||||
};
|
||||
|
||||
// = Operators between Rall2d objects
|
||||
/*
|
||||
friend INLINE Rall2d<T,V,S> operator /(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>&
|
||||
rhs); friend INLINE Rall2d<T,V,S> operator *(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>&
|
||||
rhs); friend INLINE Rall2d<T,V,S> operator +(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>&
|
||||
rhs); friend INLINE Rall2d<T,V,S> operator -(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>&
|
||||
rhs); friend INLINE Rall2d<T,V,S> operator -(const Rall2d<T,V,S>& arg); friend INLINE
|
||||
Rall2d<T,V,S> operator *(S s,const Rall2d<T,V,S>& v); friend INLINE Rall2d<T,V,S> operator
|
||||
*(const Rall2d<T,V,S>& v,S s); friend INLINE Rall2d<T,V,S> operator +(S s,const Rall2d<T,V,S>&
|
||||
v); friend INLINE Rall2d<T,V,S> operator +(const Rall2d<T,V,S>& v,S s); friend INLINE
|
||||
Rall2d<T,V,S> operator -(S s,const Rall2d<T,V,S>& v); friend INLINE Rall2d<T,V,S> operator
|
||||
-(const Rall2d<T,V,S>& v,S s); friend INLINE Rall2d<T,V,S> operator /(S s,const Rall2d<T,V,S>&
|
||||
v); friend INLINE Rall2d<T,V,S> operator /(const Rall2d<T,V,S>& v,S s);
|
||||
|
||||
// = Mathematical functions that operate on Rall2d objects
|
||||
|
||||
friend INLINE Rall2d<T,V,S> exp(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> log(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> sin(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> cos(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> tan(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> sinh(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> cosh(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> tanh(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> sqr(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> pow(const Rall2d<T,V,S>& arg,double m) ;
|
||||
friend INLINE Rall2d<T,V,S> sqrt(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> asin(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> acos(const Rall2d<T,V,S>& arg);
|
||||
friend INLINE Rall2d<T,V,S> atan(const Rall2d<T,V,S>& x);
|
||||
friend INLINE Rall2d<T,V,S> atan2(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x);
|
||||
friend INLINE Rall2d<T,V,S> abs(const Rall2d<T,V,S>& x);
|
||||
friend INLINE Rall2d<T,V,S> hypot(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x);
|
||||
// returns sqrt(y*y+x*x), but is optimized for accuracy and speed.
|
||||
friend INLINE S Norm(const Rall2d<T,V,S>& value) ;
|
||||
// returns Norm( value.Value() ).
|
||||
|
||||
// = Some utility functions to improve performance
|
||||
// (should also be declared on primitive types to improve uniformity
|
||||
friend INLINE Rall2d<T,V,S> LinComb(S alfa,const Rall2d<T,V,S>& a,
|
||||
TI<T>::Arg beta,const Rall2d<T,V,S>& b );
|
||||
friend INLINE void LinCombR(S alfa,const Rall2d<T,V,S>& a,
|
||||
TI<T>::Arg beta,const Rall2d<T,V,S>& b,Rall2d<T,V,S>& result );
|
||||
// = Setting value of a Rall2d object to 0 or 1
|
||||
friend INLINE void SetToZero(Rall2d<T,V,S>& value);
|
||||
friend INLINE void SetToOne(Rall2d<T,V,S>& value);
|
||||
// = Equality in an eps-interval
|
||||
friend INLINE bool Equal(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x,double eps);
|
||||
*/
|
||||
};
|
||||
|
||||
// = Operators between Rall2d objects
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> operator/(const Rall2d<T, V, S> &lhs, const Rall2d<T, V, S> &rhs)
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = lhs.t / rhs.t;
|
||||
tmp.d = (lhs.d - tmp.t * rhs.d) / rhs.t;
|
||||
tmp.dd = (lhs.dd - S(2) * tmp.d * rhs.d - tmp.t * rhs.dd) / rhs.t;
|
||||
return tmp;
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator /(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = lhs.t/rhs.t;
|
||||
tmp.d = (lhs.d-tmp.t*rhs.d)/rhs.t;
|
||||
tmp.dd= (lhs.dd-S(2)*tmp.d*rhs.d-tmp.t*rhs.dd)/rhs.t;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator *(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = lhs.t*rhs.t;
|
||||
tmp.d = (lhs.d*rhs.t+lhs.t*rhs.d);
|
||||
tmp.dd = (lhs.dd*rhs.t+S(2)*lhs.d*rhs.d+lhs.t*rhs.dd);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator +(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
return Rall2d<T,V,S>(lhs.t+rhs.t,lhs.d+rhs.d,lhs.dd+rhs.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator -(const Rall2d<T,V,S>& lhs,const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
return Rall2d<T,V,S>(lhs.t-rhs.t,lhs.d-rhs.d,lhs.dd-rhs.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator -(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
return Rall2d<T,V,S>(-arg.t,-arg.d,-arg.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator *(S s,const Rall2d<T,V,S>& v)
|
||||
{
|
||||
return Rall2d<T,V,S>(s*v.t,s*v.d,s*v.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator *(const Rall2d<T,V,S>& v,S s)
|
||||
{
|
||||
return Rall2d<T,V,S>(v.t*s,v.d*s,v.dd*s);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator +(S s,const Rall2d<T,V,S>& v)
|
||||
{
|
||||
return Rall2d<T,V,S>(s+v.t,v.d,v.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator +(const Rall2d<T,V,S>& v,S s)
|
||||
{
|
||||
return Rall2d<T,V,S>(v.t+s,v.d,v.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator -(S s,const Rall2d<T,V,S>& v)
|
||||
{
|
||||
return Rall2d<T,V,S>(s-v.t,-v.d,-v.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator -(const Rall2d<T,V,S>& v,S s)
|
||||
{
|
||||
return Rall2d<T,V,S>(v.t-s,v.d,v.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator /(S s,const Rall2d<T,V,S>& rhs)
|
||||
{
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = s/rhs.t;
|
||||
tmp.d = (-tmp.t*rhs.d)/rhs.t;
|
||||
tmp.dd= (-S(2)*tmp.d*rhs.d-tmp.t*rhs.dd)/rhs.t;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> operator*(const Rall2d<T, V, S> &lhs, const Rall2d<T, V, S> &rhs)
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> operator /(const Rall2d<T,V,S>& v,S s)
|
||||
{
|
||||
return Rall2d<T,V,S>(v.t/s,v.d/s,v.dd/s);
|
||||
}
|
||||
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> exp(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = exp(arg.t);
|
||||
tmp.d = tmp.t*arg.d;
|
||||
tmp.dd = tmp.d*arg.d+tmp.t*arg.dd;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> log(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = log(arg.t);
|
||||
tmp.d = arg.d/arg.t;
|
||||
tmp.dd = (arg.dd-tmp.d*arg.d)/arg.t;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> sin(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
T v1 = sin(arg.t);
|
||||
T v2 = cos(arg.t);
|
||||
return Rall2d<T,V,S>(v1,v2*arg.d,v2*arg.dd - (v1*arg.d)*arg.d );
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> cos(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
T v1 = cos(arg.t);
|
||||
T v2 = -sin(arg.t);
|
||||
return Rall2d<T,V,S>(v1,v2*arg.d, v2*arg.dd - (v1*arg.d)*arg.d);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> tan(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
T v1 = tan(arg.t);
|
||||
T v2 = S(1)+sqr(v1);
|
||||
return Rall2d<T,V,S>(v1,v2*arg.d, v2*(arg.dd+(S(2)*v1*sqr(arg.d))));
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> sinh(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
T v1 = sinh(arg.t);
|
||||
T v2 = cosh(arg.t);
|
||||
return Rall2d<T,V,S>(v1,v2*arg.d,v2*arg.dd + (v1*arg.d)*arg.d );
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> cosh(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
T v1 = cosh(arg.t);
|
||||
T v2 = sinh(arg.t);
|
||||
return Rall2d<T,V,S>(v1,v2*arg.d,v2*arg.dd + (v1*arg.d)*arg.d );
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> tanh(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
T v1 = tanh(arg.t);
|
||||
T v2 = S(1)-sqr(v1);
|
||||
return Rall2d<T,V,S>(v1,v2*arg.d, v2*(arg.dd-(S(2)*v1*sqr(arg.d))));
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> sqr(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
return Rall2d<T,V,S>(arg.t*arg.t,
|
||||
(S(2)*arg.t)*arg.d,
|
||||
S(2)*(sqr(arg.d)+arg.t*arg.dd)
|
||||
);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> pow(const Rall2d<T,V,S>& arg,double m)
|
||||
{
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = pow(arg.t,m);
|
||||
T v2 = (m/arg.t)*tmp.t;
|
||||
tmp.d = v2*arg.d;
|
||||
tmp.dd = (S((m-1))/arg.t)*tmp.d*arg.d + v2*arg.dd;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> sqrt(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
/* By inversion of sqr(x) :*/
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = sqrt(arg.t);
|
||||
tmp.d = (S(0.5)/tmp.t)*arg.d;
|
||||
tmp.dd = (S(0.5)*arg.dd-sqr(tmp.d))/tmp.t;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> asin(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = lhs.t * rhs.t;
|
||||
tmp.d = (lhs.d * rhs.t + lhs.t * rhs.d);
|
||||
tmp.dd = (lhs.dd * rhs.t + S(2) * lhs.d * rhs.d + lhs.t * rhs.dd);
|
||||
return tmp;
|
||||
/* By inversion of sin(x) */
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = asin(arg.t);
|
||||
T v = cos(tmp.t);
|
||||
tmp.d = arg.d/v;
|
||||
tmp.dd = (arg.dd+arg.t*sqr(tmp.d))/v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> operator+(const Rall2d<T, V, S> &lhs, const Rall2d<T, V, S> &rhs)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> acos(const Rall2d<T,V,S>& arg)
|
||||
{
|
||||
return Rall2d<T, V, S>(lhs.t + rhs.t, lhs.d + rhs.d, lhs.dd + rhs.dd);
|
||||
/* By inversion of cos(x) */
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = acos(arg.t);
|
||||
T v = -sin(tmp.t);
|
||||
tmp.d = arg.d/v;
|
||||
tmp.dd = (arg.dd+arg.t*sqr(tmp.d))/v;
|
||||
return tmp;
|
||||
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> operator-(const Rall2d<T, V, S> &lhs, const Rall2d<T, V, S> &rhs)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> atan(const Rall2d<T,V,S>& x)
|
||||
{
|
||||
return Rall2d<T, V, S>(lhs.t - rhs.t, lhs.d - rhs.d, lhs.dd - rhs.dd);
|
||||
/* By inversion of tan(x) */
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = atan(x.t);
|
||||
T v = S(1)+sqr(x.t);
|
||||
tmp.d = x.d/v;
|
||||
tmp.dd = x.dd/v-(S(2)*x.t)*sqr(tmp.d);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> operator-(const Rall2d<T, V, S> &arg)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> atan2(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x)
|
||||
{
|
||||
return Rall2d<T, V, S>(-arg.t, -arg.d, -arg.dd);
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = atan2(y.t,x.t);
|
||||
T v = sqr(y.t)+sqr(x.t);
|
||||
tmp.d = (x.t*y.d-x.d*y.t)/v;
|
||||
tmp.dd = ( x.t*y.dd-x.dd*y.t-S(2)*(x.t*x.d+y.t*y.d)*tmp.d ) / v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> operator*(S s, const Rall2d<T, V, S> &v)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> abs(const Rall2d<T,V,S>& x)
|
||||
{
|
||||
return Rall2d<T, V, S>(s * v.t, s * v.d, s * v.dd);
|
||||
T v(Sign(x));
|
||||
return Rall2d<T,V,S>(v*x,v*x.d,v*x.dd);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> operator*(const Rall2d<T, V, S> &v, S s)
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> hypot(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x)
|
||||
{
|
||||
return Rall2d<T, V, S>(v.t * s, v.d * s, v.dd * s);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> operator+(S s, const Rall2d<T, V, S> &v)
|
||||
{
|
||||
return Rall2d<T, V, S>(s + v.t, v.d, v.dd);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> operator+(const Rall2d<T, V, S> &v, S s)
|
||||
{
|
||||
return Rall2d<T, V, S>(v.t + s, v.d, v.dd);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> operator-(S s, const Rall2d<T, V, S> &v)
|
||||
{
|
||||
return Rall2d<T, V, S>(s - v.t, -v.d, -v.dd);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> operator-(const Rall2d<T, V, S> &v, S s)
|
||||
{
|
||||
return Rall2d<T, V, S>(v.t - s, v.d, v.dd);
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> operator/(S s, const Rall2d<T, V, S> &rhs)
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = s / rhs.t;
|
||||
tmp.d = (-tmp.t * rhs.d) / rhs.t;
|
||||
tmp.dd = (-S(2) * tmp.d * rhs.d - tmp.t * rhs.dd) / rhs.t;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> operator/(const Rall2d<T, V, S> &v, S s)
|
||||
{
|
||||
return Rall2d<T, V, S>(v.t / s, v.d / s, v.dd / s);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> exp(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = exp(arg.t);
|
||||
tmp.d = tmp.t * arg.d;
|
||||
tmp.dd = tmp.d * arg.d + tmp.t * arg.dd;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> log(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = log(arg.t);
|
||||
tmp.d = arg.d / arg.t;
|
||||
tmp.dd = (arg.dd - tmp.d * arg.d) / arg.t;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> sin(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
T v1 = sin(arg.t);
|
||||
T v2 = cos(arg.t);
|
||||
return Rall2d<T, V, S>(v1, v2 * arg.d, v2 * arg.dd - (v1 * arg.d) * arg.d);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> cos(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
T v1 = cos(arg.t);
|
||||
T v2 = -sin(arg.t);
|
||||
return Rall2d<T, V, S>(v1, v2 * arg.d, v2 * arg.dd - (v1 * arg.d) * arg.d);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> tan(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
T v1 = tan(arg.t);
|
||||
T v2 = S(1) + sqr(v1);
|
||||
return Rall2d<T, V, S>(v1, v2 * arg.d, v2 * (arg.dd + (S(2) * v1 * sqr(arg.d))));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> sinh(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
T v1 = sinh(arg.t);
|
||||
T v2 = cosh(arg.t);
|
||||
return Rall2d<T, V, S>(v1, v2 * arg.d, v2 * arg.dd + (v1 * arg.d) * arg.d);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> cosh(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
T v1 = cosh(arg.t);
|
||||
T v2 = sinh(arg.t);
|
||||
return Rall2d<T, V, S>(v1, v2 * arg.d, v2 * arg.dd + (v1 * arg.d) * arg.d);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> tanh(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
T v1 = tanh(arg.t);
|
||||
T v2 = S(1) - sqr(v1);
|
||||
return Rall2d<T, V, S>(v1, v2 * arg.d, v2 * (arg.dd - (S(2) * v1 * sqr(arg.d))));
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> sqr(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
return Rall2d<T, V, S>(
|
||||
arg.t * arg.t, (S(2) * arg.t) * arg.d, S(2) * (sqr(arg.d) + arg.t * arg.dd));
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> pow(const Rall2d<T, V, S> &arg, double m)
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = pow(arg.t, m);
|
||||
T v2 = (m / arg.t) * tmp.t;
|
||||
tmp.d = v2 * arg.d;
|
||||
tmp.dd = (S((m - 1)) / arg.t) * tmp.d * arg.d + v2 * arg.dd;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> sqrt(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
/* By inversion of sqr(x) :*/
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = sqrt(arg.t);
|
||||
tmp.d = (S(0.5) / tmp.t) * arg.d;
|
||||
tmp.dd = (S(0.5) * arg.dd - sqr(tmp.d)) / tmp.t;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> asin(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
/* By inversion of sin(x) */
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = asin(arg.t);
|
||||
T v = cos(tmp.t);
|
||||
tmp.d = arg.d / v;
|
||||
tmp.dd = (arg.dd + arg.t * sqr(tmp.d)) / v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> acos(const Rall2d<T, V, S> &arg)
|
||||
{
|
||||
/* By inversion of cos(x) */
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = acos(arg.t);
|
||||
T v = -sin(tmp.t);
|
||||
tmp.d = arg.d / v;
|
||||
tmp.dd = (arg.dd + arg.t * sqr(tmp.d)) / v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> atan(const Rall2d<T, V, S> &x)
|
||||
{
|
||||
/* By inversion of tan(x) */
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = atan(x.t);
|
||||
T v = S(1) + sqr(x.t);
|
||||
tmp.d = x.d / v;
|
||||
tmp.dd = x.dd / v - (S(2) * x.t) * sqr(tmp.d);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> atan2(const Rall2d<T, V, S> &y, const Rall2d<T, V, S> &x)
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = atan2(y.t, x.t);
|
||||
T v = sqr(y.t) + sqr(x.t);
|
||||
tmp.d = (x.t * y.d - x.d * y.t) / v;
|
||||
tmp.dd = (x.t * y.dd - x.dd * y.t - S(2) * (x.t * x.d + y.t * y.d) * tmp.d) / v;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE Rall2d<T, V, S> abs(const Rall2d<T, V, S> &x)
|
||||
{
|
||||
T v(Sign(x));
|
||||
return Rall2d<T, V, S>(v * x, v * x.d, v * x.dd);
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> hypot(const Rall2d<T, V, S> &y, const Rall2d<T, V, S> &x)
|
||||
{
|
||||
Rall2d<T, V, S> tmp;
|
||||
tmp.t = hypot(y.t, x.t);
|
||||
tmp.d = (x.t * x.d + y.t * y.d) / tmp.t;
|
||||
tmp.dd = (sqr(x.d) + x.t * x.dd + sqr(y.d) + y.t * y.dd - sqr(tmp.d)) / tmp.t;
|
||||
return tmp;
|
||||
Rall2d<T,V,S> tmp;
|
||||
tmp.t = hypot(y.t,x.t);
|
||||
tmp.d = (x.t*x.d+y.t*y.d)/tmp.t;
|
||||
tmp.dd = (sqr(x.d)+x.t*x.dd+sqr(y.d)+y.t*y.dd-sqr(tmp.d))/tmp.t;
|
||||
return tmp;
|
||||
}
|
||||
// returns sqrt(y*y+x*x), but is optimized for accuracy and speed.
|
||||
|
||||
template<class T, class V, class S> INLINE S Norm(const Rall2d<T, V, S> &value)
|
||||
template <class T,class V,class S>
|
||||
INLINE S Norm(const Rall2d<T,V,S>& value)
|
||||
{
|
||||
return Norm(value.t);
|
||||
return Norm(value.t);
|
||||
}
|
||||
// returns Norm( value.Value() ).
|
||||
|
||||
|
||||
// (should also be declared on primitive types to improve uniformity
|
||||
template<class T, class V, class S>
|
||||
INLINE Rall2d<T, V, S> LinComb(S alfa,
|
||||
const Rall2d<T, V, S> &a,
|
||||
const T &beta,
|
||||
const Rall2d<T, V, S> &b)
|
||||
{
|
||||
return Rall2d<T, V, S>(LinComb(alfa, a.t, beta, b.t),
|
||||
LinComb(alfa, a.d, beta, b.d),
|
||||
LinComb(alfa, a.dd, beta, b.dd));
|
||||
template <class T,class V,class S>
|
||||
INLINE Rall2d<T,V,S> LinComb(S alfa,const Rall2d<T,V,S>& a,
|
||||
const T& beta,const Rall2d<T,V,S>& b ) {
|
||||
return Rall2d<T,V,S>(
|
||||
LinComb(alfa,a.t,beta,b.t),
|
||||
LinComb(alfa,a.d,beta,b.d),
|
||||
LinComb(alfa,a.dd,beta,b.dd)
|
||||
);
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE void LinCombR(S alfa,
|
||||
const Rall2d<T, V, S> &a,
|
||||
const T &beta,
|
||||
const Rall2d<T, V, S> &b,
|
||||
Rall2d<T, V, S> &result)
|
||||
{
|
||||
LinCombR(alfa, a.t, beta, b.t, result.t);
|
||||
LinCombR(alfa, a.d, beta, b.d, result.d);
|
||||
LinCombR(alfa, a.dd, beta, b.dd, result.dd);
|
||||
template <class T,class V,class S>
|
||||
INLINE void LinCombR(S alfa,const Rall2d<T,V,S>& a,
|
||||
const T& beta,const Rall2d<T,V,S>& b,Rall2d<T,V,S>& result ) {
|
||||
LinCombR(alfa, a.t, beta, b.t, result.t);
|
||||
LinCombR(alfa, a.d, beta, b.d, result.d);
|
||||
LinCombR(alfa, a.dd, beta, b.dd, result.dd);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE void SetToZero(Rall2d<T, V, S> &value)
|
||||
template <class T,class V,class S>
|
||||
INLINE void SetToZero(Rall2d<T,V,S>& value)
|
||||
{
|
||||
SetToZero(value.t);
|
||||
SetToZero(value.d);
|
||||
SetToZero(value.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE void SetToIdentity(Rall2d<T,V,S>& value)
|
||||
{
|
||||
SetToZero(value.d);
|
||||
SetToIdentity(value.t);
|
||||
SetToZero(value.dd);
|
||||
}
|
||||
|
||||
template <class T,class V,class S>
|
||||
INLINE bool Equal(const Rall2d<T,V,S>& y,const Rall2d<T,V,S>& x,double eps=epsilon)
|
||||
{
|
||||
SetToZero(value.t);
|
||||
SetToZero(value.d);
|
||||
SetToZero(value.dd);
|
||||
return (Equal(x.t,y.t,eps)&&
|
||||
Equal(x.d,y.d,eps)&&
|
||||
Equal(x.dd,y.dd,eps)
|
||||
);
|
||||
}
|
||||
|
||||
template<class T, class V, class S> INLINE void SetToIdentity(Rall2d<T, V, S> &value)
|
||||
{
|
||||
SetToZero(value.d);
|
||||
SetToIdentity(value.t);
|
||||
SetToZero(value.dd);
|
||||
|
||||
}
|
||||
|
||||
template<class T, class V, class S>
|
||||
INLINE bool Equal(const Rall2d<T, V, S> &y, const Rall2d<T, V, S> &x, double eps = epsilon)
|
||||
{
|
||||
return (Equal(x.t, y.t, eps) && Equal(x.d, y.d, eps) && Equal(x.dd, y.dd, eps));
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -19,310 +19,291 @@
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
// Based on the svd of the KDL-0.2 library by Erwin Aertbelien
|
||||
|
||||
//Based on the svd of the KDL-0.2 library by Erwin Aertbelien
|
||||
#ifndef SVD_EIGEN_HH_HPP
|
||||
#define SVD_EIGEN_HH_HPP
|
||||
|
||||
|
||||
#include <Eigen/Core>
|
||||
#include <algorithm>
|
||||
|
||||
namespace KDL {
|
||||
template<typename Scalar> inline Scalar PYTHAG(Scalar a, Scalar b)
|
||||
namespace KDL
|
||||
{
|
||||
double at, bt, ct;
|
||||
at = fabs(a);
|
||||
bt = fabs(b);
|
||||
if (at > bt) {
|
||||
ct = bt / at;
|
||||
return Scalar(at * sqrt(1.0 + ct * ct));
|
||||
}
|
||||
else {
|
||||
if (bt == 0)
|
||||
return Scalar(0.0);
|
||||
else {
|
||||
ct = at / bt;
|
||||
return Scalar(bt * sqrt(1.0 + ct * ct));
|
||||
template<typename Scalar> inline Scalar PYTHAG(Scalar a,Scalar b) {
|
||||
double at,bt,ct;
|
||||
at = fabs(a);
|
||||
bt = fabs(b);
|
||||
if (at > bt ) {
|
||||
ct=bt/at;
|
||||
return Scalar(at*sqrt(1.0+ct*ct));
|
||||
} else {
|
||||
if (bt==0)
|
||||
return Scalar(0.0);
|
||||
else {
|
||||
ct=at/bt;
|
||||
return Scalar(bt*sqrt(1.0+ct*ct));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<typename Scalar> inline Scalar SIGN(Scalar a,Scalar b) {
|
||||
return ((b) >= Scalar(0.0) ? fabs(a) : -fabs(a));
|
||||
}
|
||||
|
||||
/**
|
||||
* svd calculation of boost ublas matrices
|
||||
*
|
||||
* @param A matrix<double>(mxn)
|
||||
* @param U matrix<double>(mxn)
|
||||
* @param S vector<double> n
|
||||
* @param V matrix<double>(nxn)
|
||||
* @param tmp vector<double> n
|
||||
* @param maxiter defaults to 150
|
||||
*
|
||||
* @return -2 if maxiter exceeded, 0 otherwise
|
||||
*/
|
||||
template<typename MatrixA, typename MatrixUV, typename VectorS>
|
||||
int svd_eigen_HH(
|
||||
const Eigen::MatrixBase<MatrixA>& A,
|
||||
Eigen::MatrixBase<MatrixUV>& U,
|
||||
Eigen::MatrixBase<VectorS>& S,
|
||||
Eigen::MatrixBase<MatrixUV>& V,
|
||||
Eigen::MatrixBase<VectorS>& tmp,
|
||||
int maxiter=150)
|
||||
{
|
||||
//get the rows/columns of the matrix
|
||||
const int rows = A.rows();
|
||||
const int cols = A.cols();
|
||||
|
||||
U = A;
|
||||
|
||||
int i(-1),its(-1),j(-1),jj(-1),k(-1),nm=0;
|
||||
int ppi(0);
|
||||
bool flag;
|
||||
e_scalar maxarg1,maxarg2,anorm(0),c(0),f(0),h(0),s(0),scale(0),x(0),y(0),z(0),g(0);
|
||||
|
||||
g=scale=anorm=e_scalar(0.0);
|
||||
|
||||
/* Householder reduction to bidiagonal form. */
|
||||
for (i=0;i<cols;i++) {
|
||||
ppi=i+1;
|
||||
tmp(i)=scale*g;
|
||||
g=s=scale=e_scalar(0.0);
|
||||
if (i<rows) {
|
||||
// compute the sum of the i-th column, starting from the i-th row
|
||||
for (k=i;k<rows;k++) scale += fabs(U(k,i));
|
||||
if (scale!=0) {
|
||||
// multiply the i-th column by 1.0/scale, start from the i-th element
|
||||
// sum of squares of column i, start from the i-th element
|
||||
for (k=i;k<rows;k++) {
|
||||
U(k,i) /= scale;
|
||||
s += U(k,i)*U(k,i);
|
||||
}
|
||||
f=U(i,i); // f is the diag elem
|
||||
g = -SIGN(e_scalar(sqrt(s)),f);
|
||||
h=f*g-s;
|
||||
U(i,i)=f-g;
|
||||
for (j=ppi;j<cols;j++) {
|
||||
// dot product of columns i and j, starting from the i-th row
|
||||
for (s=0.0,k=i;k<rows;k++) s += U(k,i)*U(k,j);
|
||||
f=s/h;
|
||||
// copy the scaled i-th column into the j-th column
|
||||
for (k=i;k<rows;k++) U(k,j) += f*U(k,i);
|
||||
}
|
||||
for (k=i;k<rows;k++) U(k,i) *= scale;
|
||||
}
|
||||
}
|
||||
// save singular value
|
||||
S(i)=scale*g;
|
||||
g=s=scale=e_scalar(0.0);
|
||||
if ((i <rows) && (i+1 != cols)) {
|
||||
// sum of row i, start from columns i+1
|
||||
for (k=ppi;k<cols;k++) scale += fabs(U(i,k));
|
||||
if (scale!=0) {
|
||||
for (k=ppi;k<cols;k++) {
|
||||
U(i,k) /= scale;
|
||||
s += U(i,k)*U(i,k);
|
||||
}
|
||||
f=U(i,ppi);
|
||||
g = -SIGN(e_scalar(sqrt(s)),f);
|
||||
h=f*g-s;
|
||||
U(i,ppi)=f-g;
|
||||
for (k=ppi;k<cols;k++) tmp(k)=U(i,k)/h;
|
||||
for (j=ppi;j<rows;j++) {
|
||||
for (s=0.0,k=ppi;k<cols;k++) s += U(j,k)*U(i,k);
|
||||
for (k=ppi;k<cols;k++) U(j,k) += s*tmp(k);
|
||||
}
|
||||
for (k=ppi;k<cols;k++) U(i,k) *= scale;
|
||||
}
|
||||
}
|
||||
maxarg1=anorm;
|
||||
maxarg2=(fabs(S(i))+fabs(tmp(i)));
|
||||
anorm = maxarg1 > maxarg2 ? maxarg1 : maxarg2;
|
||||
}
|
||||
/* Accumulation of right-hand transformations. */
|
||||
for (i=cols-1;i>=0;i--) {
|
||||
if (i<cols-1) {
|
||||
if (g) {
|
||||
for (j=ppi;j<cols;j++) V(j,i)=(U(i,j)/U(i,ppi))/g;
|
||||
for (j=ppi;j<cols;j++) {
|
||||
for (s=0.0,k=ppi;k<cols;k++) s += U(i,k)*V(k,j);
|
||||
for (k=ppi;k<cols;k++) V(k,j) += s*V(k,i);
|
||||
}
|
||||
}
|
||||
for (j=ppi;j<cols;j++) V(i,j)=V(j,i)=0.0;
|
||||
}
|
||||
V(i,i)=1.0;
|
||||
g=tmp(i);
|
||||
ppi=i;
|
||||
}
|
||||
/* Accumulation of left-hand transformations. */
|
||||
for (i=cols-1<rows-1 ? cols-1:rows-1;i>=0;i--) {
|
||||
ppi=i+1;
|
||||
g=S(i);
|
||||
for (j=ppi;j<cols;j++) U(i,j)=0.0;
|
||||
if (g) {
|
||||
g=e_scalar(1.0)/g;
|
||||
for (j=ppi;j<cols;j++) {
|
||||
for (s=0.0,k=ppi;k<rows;k++) s += U(k,i)*U(k,j);
|
||||
f=(s/U(i,i))*g;
|
||||
for (k=i;k<rows;k++) U(k,j) += f*U(k,i);
|
||||
}
|
||||
for (j=i;j<rows;j++) U(j,i) *= g;
|
||||
} else {
|
||||
for (j=i;j<rows;j++) U(j,i)=0.0;
|
||||
}
|
||||
++U(i,i);
|
||||
}
|
||||
|
||||
/* Diagonalization of the bidiagonal form. */
|
||||
for (k=cols-1;k>=0;k--) { /* Loop over singular values. */
|
||||
for (its=1;its<=maxiter;its++) { /* Loop over allowed iterations. */
|
||||
flag=true;
|
||||
for (ppi=k;ppi>=0;ppi--) { /* Test for splitting. */
|
||||
nm=ppi-1; /* Note that tmp(1) is always zero. */
|
||||
if ((fabs(tmp(ppi))+anorm) == anorm) {
|
||||
flag=false;
|
||||
break;
|
||||
}
|
||||
if ((fabs(S(nm)+anorm) == anorm)) break;
|
||||
}
|
||||
if (flag) {
|
||||
c=e_scalar(0.0); /* Cancellation of tmp(l), if l>1: */
|
||||
s=e_scalar(1.);
|
||||
for (i=ppi;i<=k;i++) {
|
||||
f=s*tmp(i);
|
||||
tmp(i)=c*tmp(i);
|
||||
if ((fabs(f)+anorm) == anorm) break;
|
||||
g=S(i);
|
||||
h=PYTHAG(f,g);
|
||||
S(i)=h;
|
||||
h=e_scalar(1.0)/h;
|
||||
c=g*h;
|
||||
s=(-f*h);
|
||||
for (j=0;j<rows;j++) {
|
||||
y=U(j,nm);
|
||||
z=U(j,i);
|
||||
U(j,nm)=y*c+z*s;
|
||||
U(j,i)=z*c-y*s;
|
||||
}
|
||||
}
|
||||
}
|
||||
z=S(k);
|
||||
|
||||
if (ppi == k) { /* Convergence. */
|
||||
if (z < e_scalar(0.0)) { /* Singular value is made nonnegative. */
|
||||
S(k) = -z;
|
||||
for (j=0;j<cols;j++) V(j,k)=-V(j,k);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
x=S(ppi); /* Shift from bottom 2-by-2 minor: */
|
||||
nm=k-1;
|
||||
y=S(nm);
|
||||
g=tmp(nm);
|
||||
h=tmp(k);
|
||||
f=((y-z)*(y+z)+(g-h)*(g+h))/(e_scalar(2.0)*h*y);
|
||||
|
||||
g=PYTHAG(f,e_scalar(1.0));
|
||||
f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
|
||||
|
||||
/* Next QR transformation: */
|
||||
c=s=1.0;
|
||||
for (j=ppi;j<=nm;j++) {
|
||||
i=j+1;
|
||||
g=tmp(i);
|
||||
y=S(i);
|
||||
h=s*g;
|
||||
g=c*g;
|
||||
z=PYTHAG(f,h);
|
||||
tmp(j)=z;
|
||||
c=f/z;
|
||||
s=h/z;
|
||||
f=x*c+g*s;
|
||||
g=g*c-x*s;
|
||||
h=y*s;
|
||||
y=y*c;
|
||||
for (jj=0;jj<cols;jj++) {
|
||||
x=V(jj,j);
|
||||
z=V(jj,i);
|
||||
V(jj,j)=x*c+z*s;
|
||||
V(jj,i)=z*c-x*s;
|
||||
}
|
||||
z=PYTHAG(f,h);
|
||||
S(j)=z;
|
||||
if (z) {
|
||||
z=e_scalar(1.0)/z;
|
||||
c=f*z;
|
||||
s=h*z;
|
||||
}
|
||||
f=(c*g)+(s*y);
|
||||
x=(c*y)-(s*g);
|
||||
for (jj=0;jj<rows;jj++) {
|
||||
y=U(jj,j);
|
||||
z=U(jj,i);
|
||||
U(jj,j)=y*c+z*s;
|
||||
U(jj,i)=z*c-y*s;
|
||||
}
|
||||
}
|
||||
tmp(ppi)=0.0;
|
||||
tmp(k)=f;
|
||||
S(k)=x;
|
||||
}
|
||||
}
|
||||
|
||||
//Sort eigen values:
|
||||
for (i=0; i<cols; i++){
|
||||
|
||||
double S_max = S(i);
|
||||
int i_max = i;
|
||||
for (j=i+1; j<cols; j++){
|
||||
double Sj = S(j);
|
||||
if (Sj > S_max){
|
||||
S_max = Sj;
|
||||
i_max = j;
|
||||
}
|
||||
}
|
||||
if (i_max != i){
|
||||
/* swap eigenvalues */
|
||||
e_scalar tmp = S(i);
|
||||
S(i)=S(i_max);
|
||||
S(i_max)=tmp;
|
||||
|
||||
/* swap eigenvectors */
|
||||
U.col(i).swap(U.col(i_max));
|
||||
V.col(i).swap(V.col(i_max));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (its == maxiter)
|
||||
return (-2);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename Scalar> inline Scalar SIGN(Scalar a, Scalar b)
|
||||
{
|
||||
return ((b) >= Scalar(0.0) ? fabs(a) : -fabs(a));
|
||||
}
|
||||
|
||||
/**
|
||||
* svd calculation of boost ublas matrices
|
||||
*
|
||||
* @param A matrix<double>(mxn)
|
||||
* @param U matrix<double>(mxn)
|
||||
* @param S vector<double> n
|
||||
* @param V matrix<double>(nxn)
|
||||
* @param tmp vector<double> n
|
||||
* @param maxiter defaults to 150
|
||||
*
|
||||
* @return -2 if maxiter exceeded, 0 otherwise
|
||||
*/
|
||||
template<typename MatrixA, typename MatrixUV, typename VectorS>
|
||||
int svd_eigen_HH(const Eigen::MatrixBase<MatrixA> &A,
|
||||
Eigen::MatrixBase<MatrixUV> &U,
|
||||
Eigen::MatrixBase<VectorS> &S,
|
||||
Eigen::MatrixBase<MatrixUV> &V,
|
||||
Eigen::MatrixBase<VectorS> &tmp,
|
||||
int maxiter = 150)
|
||||
{
|
||||
// get the rows/columns of the matrix
|
||||
const int rows = A.rows();
|
||||
const int cols = A.cols();
|
||||
|
||||
U = A;
|
||||
|
||||
int i(-1), its(-1), j(-1), jj(-1), k(-1), nm = 0;
|
||||
int ppi(0);
|
||||
bool flag;
|
||||
e_scalar maxarg1, maxarg2, anorm(0), c(0), f(0), h(0), s(0), scale(0), x(0), y(0), z(0), g(0);
|
||||
|
||||
g = scale = anorm = e_scalar(0.0);
|
||||
|
||||
/* Householder reduction to bidiagonal form. */
|
||||
for (i = 0; i < cols; i++) {
|
||||
ppi = i + 1;
|
||||
tmp(i) = scale * g;
|
||||
g = s = scale = e_scalar(0.0);
|
||||
if (i < rows) {
|
||||
// compute the sum of the i-th column, starting from the i-th row
|
||||
for (k = i; k < rows; k++)
|
||||
scale += fabs(U(k, i));
|
||||
if (scale != 0) {
|
||||
// multiply the i-th column by 1.0/scale, start from the i-th element
|
||||
// sum of squares of column i, start from the i-th element
|
||||
for (k = i; k < rows; k++) {
|
||||
U(k, i) /= scale;
|
||||
s += U(k, i) * U(k, i);
|
||||
}
|
||||
f = U(i, i); // f is the diag elem
|
||||
g = -SIGN(e_scalar(sqrt(s)), f);
|
||||
h = f * g - s;
|
||||
U(i, i) = f - g;
|
||||
for (j = ppi; j < cols; j++) {
|
||||
// dot product of columns i and j, starting from the i-th row
|
||||
for (s = 0.0, k = i; k < rows; k++)
|
||||
s += U(k, i) * U(k, j);
|
||||
f = s / h;
|
||||
// copy the scaled i-th column into the j-th column
|
||||
for (k = i; k < rows; k++)
|
||||
U(k, j) += f * U(k, i);
|
||||
}
|
||||
for (k = i; k < rows; k++)
|
||||
U(k, i) *= scale;
|
||||
}
|
||||
}
|
||||
// save singular value
|
||||
S(i) = scale * g;
|
||||
g = s = scale = e_scalar(0.0);
|
||||
if ((i < rows) && (i + 1 != cols)) {
|
||||
// sum of row i, start from columns i+1
|
||||
for (k = ppi; k < cols; k++)
|
||||
scale += fabs(U(i, k));
|
||||
if (scale != 0) {
|
||||
for (k = ppi; k < cols; k++) {
|
||||
U(i, k) /= scale;
|
||||
s += U(i, k) * U(i, k);
|
||||
}
|
||||
f = U(i, ppi);
|
||||
g = -SIGN(e_scalar(sqrt(s)), f);
|
||||
h = f * g - s;
|
||||
U(i, ppi) = f - g;
|
||||
for (k = ppi; k < cols; k++)
|
||||
tmp(k) = U(i, k) / h;
|
||||
for (j = ppi; j < rows; j++) {
|
||||
for (s = 0.0, k = ppi; k < cols; k++)
|
||||
s += U(j, k) * U(i, k);
|
||||
for (k = ppi; k < cols; k++)
|
||||
U(j, k) += s * tmp(k);
|
||||
}
|
||||
for (k = ppi; k < cols; k++)
|
||||
U(i, k) *= scale;
|
||||
}
|
||||
}
|
||||
maxarg1 = anorm;
|
||||
maxarg2 = (fabs(S(i)) + fabs(tmp(i)));
|
||||
anorm = maxarg1 > maxarg2 ? maxarg1 : maxarg2;
|
||||
}
|
||||
/* Accumulation of right-hand transformations. */
|
||||
for (i = cols - 1; i >= 0; i--) {
|
||||
if (i < cols - 1) {
|
||||
if (g) {
|
||||
for (j = ppi; j < cols; j++)
|
||||
V(j, i) = (U(i, j) / U(i, ppi)) / g;
|
||||
for (j = ppi; j < cols; j++) {
|
||||
for (s = 0.0, k = ppi; k < cols; k++)
|
||||
s += U(i, k) * V(k, j);
|
||||
for (k = ppi; k < cols; k++)
|
||||
V(k, j) += s * V(k, i);
|
||||
}
|
||||
}
|
||||
for (j = ppi; j < cols; j++)
|
||||
V(i, j) = V(j, i) = 0.0;
|
||||
}
|
||||
V(i, i) = 1.0;
|
||||
g = tmp(i);
|
||||
ppi = i;
|
||||
}
|
||||
/* Accumulation of left-hand transformations. */
|
||||
for (i = cols - 1 < rows - 1 ? cols - 1 : rows - 1; i >= 0; i--) {
|
||||
ppi = i + 1;
|
||||
g = S(i);
|
||||
for (j = ppi; j < cols; j++)
|
||||
U(i, j) = 0.0;
|
||||
if (g) {
|
||||
g = e_scalar(1.0) / g;
|
||||
for (j = ppi; j < cols; j++) {
|
||||
for (s = 0.0, k = ppi; k < rows; k++)
|
||||
s += U(k, i) * U(k, j);
|
||||
f = (s / U(i, i)) * g;
|
||||
for (k = i; k < rows; k++)
|
||||
U(k, j) += f * U(k, i);
|
||||
}
|
||||
for (j = i; j < rows; j++)
|
||||
U(j, i) *= g;
|
||||
}
|
||||
else {
|
||||
for (j = i; j < rows; j++)
|
||||
U(j, i) = 0.0;
|
||||
}
|
||||
++U(i, i);
|
||||
}
|
||||
|
||||
/* Diagonalization of the bidiagonal form. */
|
||||
for (k = cols - 1; k >= 0; k--) { /* Loop over singular values. */
|
||||
for (its = 1; its <= maxiter; its++) { /* Loop over allowed iterations. */
|
||||
flag = true;
|
||||
for (ppi = k; ppi >= 0; ppi--) { /* Test for splitting. */
|
||||
nm = ppi - 1; /* Note that tmp(1) is always zero. */
|
||||
if ((fabs(tmp(ppi)) + anorm) == anorm) {
|
||||
flag = false;
|
||||
break;
|
||||
}
|
||||
if ((fabs(S(nm) + anorm) == anorm))
|
||||
break;
|
||||
}
|
||||
if (flag) {
|
||||
c = e_scalar(0.0); /* Cancellation of tmp(l), if l>1: */
|
||||
s = e_scalar(1.);
|
||||
for (i = ppi; i <= k; i++) {
|
||||
f = s * tmp(i);
|
||||
tmp(i) = c * tmp(i);
|
||||
if ((fabs(f) + anorm) == anorm)
|
||||
break;
|
||||
g = S(i);
|
||||
h = PYTHAG(f, g);
|
||||
S(i) = h;
|
||||
h = e_scalar(1.0) / h;
|
||||
c = g * h;
|
||||
s = (-f * h);
|
||||
for (j = 0; j < rows; j++) {
|
||||
y = U(j, nm);
|
||||
z = U(j, i);
|
||||
U(j, nm) = y * c + z * s;
|
||||
U(j, i) = z * c - y * s;
|
||||
}
|
||||
}
|
||||
}
|
||||
z = S(k);
|
||||
|
||||
if (ppi == k) { /* Convergence. */
|
||||
if (z < e_scalar(0.0)) { /* Singular value is made nonnegative. */
|
||||
S(k) = -z;
|
||||
for (j = 0; j < cols; j++)
|
||||
V(j, k) = -V(j, k);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
x = S(ppi); /* Shift from bottom 2-by-2 minor: */
|
||||
nm = k - 1;
|
||||
y = S(nm);
|
||||
g = tmp(nm);
|
||||
h = tmp(k);
|
||||
f = ((y - z) * (y + z) + (g - h) * (g + h)) / (e_scalar(2.0) * h * y);
|
||||
|
||||
g = PYTHAG(f, e_scalar(1.0));
|
||||
f = ((x - z) * (x + z) + h * ((y / (f + SIGN(g, f))) - h)) / x;
|
||||
|
||||
/* Next QR transformation: */
|
||||
c = s = 1.0;
|
||||
for (j = ppi; j <= nm; j++) {
|
||||
i = j + 1;
|
||||
g = tmp(i);
|
||||
y = S(i);
|
||||
h = s * g;
|
||||
g = c * g;
|
||||
z = PYTHAG(f, h);
|
||||
tmp(j) = z;
|
||||
c = f / z;
|
||||
s = h / z;
|
||||
f = x * c + g * s;
|
||||
g = g * c - x * s;
|
||||
h = y * s;
|
||||
y = y * c;
|
||||
for (jj = 0; jj < cols; jj++) {
|
||||
x = V(jj, j);
|
||||
z = V(jj, i);
|
||||
V(jj, j) = x * c + z * s;
|
||||
V(jj, i) = z * c - x * s;
|
||||
}
|
||||
z = PYTHAG(f, h);
|
||||
S(j) = z;
|
||||
if (z) {
|
||||
z = e_scalar(1.0) / z;
|
||||
c = f * z;
|
||||
s = h * z;
|
||||
}
|
||||
f = (c * g) + (s * y);
|
||||
x = (c * y) - (s * g);
|
||||
for (jj = 0; jj < rows; jj++) {
|
||||
y = U(jj, j);
|
||||
z = U(jj, i);
|
||||
U(jj, j) = y * c + z * s;
|
||||
U(jj, i) = z * c - y * s;
|
||||
}
|
||||
}
|
||||
tmp(ppi) = 0.0;
|
||||
tmp(k) = f;
|
||||
S(k) = x;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort eigen values:
|
||||
for (i = 0; i < cols; i++) {
|
||||
|
||||
double S_max = S(i);
|
||||
int i_max = i;
|
||||
for (j = i + 1; j < cols; j++) {
|
||||
double Sj = S(j);
|
||||
if (Sj > S_max) {
|
||||
S_max = Sj;
|
||||
i_max = j;
|
||||
}
|
||||
}
|
||||
if (i_max != i) {
|
||||
/* swap eigenvalues */
|
||||
e_scalar tmp = S(i);
|
||||
S(i) = S(i_max);
|
||||
S(i_max) = tmp;
|
||||
|
||||
/* swap eigenvectors */
|
||||
U.col(i).swap(U.col(i_max));
|
||||
V.col(i).swap(V.col(i_max));
|
||||
}
|
||||
}
|
||||
|
||||
if (its == maxiter)
|
||||
return (-2);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
#endif
|
||||
|
||||
@@ -1,98 +1,114 @@
|
||||
/** \file itasc/kdl/utilities/traits.h
|
||||
* \ingroup intern_itasc
|
||||
*/
|
||||
#ifndef KDLPV_TRAITS_H
|
||||
#define KDLPV_TRAITS_H
|
||||
#ifndef KDLPV_TRAITS_H
|
||||
#define KDLPV_TRAITS_H
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
|
||||
// forwards declarations :
|
||||
namespace KDL {
|
||||
class Frame;
|
||||
class Rotation;
|
||||
class Vector;
|
||||
class Twist;
|
||||
class Wrench;
|
||||
class FrameVel;
|
||||
class RotationVel;
|
||||
class VectorVel;
|
||||
class TwistVel;
|
||||
} // namespace KDL
|
||||
class Frame;
|
||||
class Rotation;
|
||||
class Vector;
|
||||
class Twist;
|
||||
class Wrench;
|
||||
class FrameVel;
|
||||
class RotationVel;
|
||||
class VectorVel;
|
||||
class TwistVel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Traits are traits classes to determine the type of a derivative of another type.
|
||||
*
|
||||
* For geometric objects the "geometric" derivative is chosen. For example the derivative of a
|
||||
Rotation
|
||||
* matrix is NOT a 3x3 matrix containing the derivative of the elements of a rotation matrix. The
|
||||
derivative
|
||||
* of the rotation matrix is a Vector corresponding the rotational velocity. Mostly used in
|
||||
template classes
|
||||
* For geometric objects the "geometric" derivative is chosen. For example the derivative of a Rotation
|
||||
* matrix is NOT a 3x3 matrix containing the derivative of the elements of a rotation matrix. The derivative
|
||||
* of the rotation matrix is a Vector corresponding the rotational velocity. Mostly used in template classes
|
||||
* and routines to derive a correct type when needed.
|
||||
*
|
||||
*
|
||||
* You can see this as a compile-time lookuptable to find the type of the derivative.
|
||||
*
|
||||
* Example
|
||||
* \verbatim
|
||||
Rotation R;
|
||||
Rotation R;
|
||||
Traits<Rotation> dR;
|
||||
\endverbatim
|
||||
*/
|
||||
template<typename T> struct Traits {
|
||||
typedef T valueType;
|
||||
typedef T derivType;
|
||||
template <typename T>
|
||||
struct Traits {
|
||||
typedef T valueType;
|
||||
typedef T derivType;
|
||||
};
|
||||
|
||||
template<> struct Traits<KDL::Frame> {
|
||||
typedef KDL::Frame valueType;
|
||||
typedef KDL::Twist derivType;
|
||||
template <>
|
||||
struct Traits<KDL::Frame> {
|
||||
typedef KDL::Frame valueType;
|
||||
typedef KDL::Twist derivType;
|
||||
};
|
||||
template<> struct Traits<KDL::Twist> {
|
||||
typedef KDL::Twist valueType;
|
||||
typedef KDL::Twist derivType;
|
||||
template <>
|
||||
struct Traits<KDL::Twist> {
|
||||
typedef KDL::Twist valueType;
|
||||
typedef KDL::Twist derivType;
|
||||
};
|
||||
template<> struct Traits<KDL::Wrench> {
|
||||
typedef KDL::Wrench valueType;
|
||||
typedef KDL::Wrench derivType;
|
||||
template <>
|
||||
struct Traits<KDL::Wrench> {
|
||||
typedef KDL::Wrench valueType;
|
||||
typedef KDL::Wrench derivType;
|
||||
};
|
||||
|
||||
template<> struct Traits<KDL::Rotation> {
|
||||
typedef KDL::Rotation valueType;
|
||||
typedef KDL::Vector derivType;
|
||||
template <>
|
||||
struct Traits<KDL::Rotation> {
|
||||
typedef KDL::Rotation valueType;
|
||||
typedef KDL::Vector derivType;
|
||||
};
|
||||
|
||||
template<> struct Traits<KDL::Vector> {
|
||||
typedef KDL::Vector valueType;
|
||||
typedef KDL::Vector derivType;
|
||||
template <>
|
||||
struct Traits<KDL::Vector> {
|
||||
typedef KDL::Vector valueType;
|
||||
typedef KDL::Vector derivType;
|
||||
};
|
||||
|
||||
template<> struct Traits<double> {
|
||||
typedef double valueType;
|
||||
typedef double derivType;
|
||||
template <>
|
||||
struct Traits<double> {
|
||||
typedef double valueType;
|
||||
typedef double derivType;
|
||||
};
|
||||
|
||||
template<> struct Traits<float> {
|
||||
typedef float valueType;
|
||||
typedef float derivType;
|
||||
template <>
|
||||
struct Traits<float> {
|
||||
typedef float valueType;
|
||||
typedef float derivType;
|
||||
};
|
||||
|
||||
template<> struct Traits<KDL::FrameVel> {
|
||||
typedef KDL::Frame valueType;
|
||||
typedef KDL::TwistVel derivType;
|
||||
template <>
|
||||
struct Traits<KDL::FrameVel> {
|
||||
typedef KDL::Frame valueType;
|
||||
typedef KDL::TwistVel derivType;
|
||||
};
|
||||
template<> struct Traits<KDL::TwistVel> {
|
||||
typedef KDL::Twist valueType;
|
||||
typedef KDL::TwistVel derivType;
|
||||
template <>
|
||||
struct Traits<KDL::TwistVel> {
|
||||
typedef KDL::Twist valueType;
|
||||
typedef KDL::TwistVel derivType;
|
||||
};
|
||||
|
||||
template<> struct Traits<KDL::RotationVel> {
|
||||
typedef KDL::Rotation valueType;
|
||||
typedef KDL::VectorVel derivType;
|
||||
template <>
|
||||
struct Traits<KDL::RotationVel> {
|
||||
typedef KDL::Rotation valueType;
|
||||
typedef KDL::VectorVel derivType;
|
||||
};
|
||||
|
||||
template<> struct Traits<KDL::VectorVel> {
|
||||
typedef KDL::Vector valueType;
|
||||
typedef KDL::VectorVel derivType;
|
||||
template <>
|
||||
struct Traits<KDL::VectorVel> {
|
||||
typedef KDL::Vector valueType;
|
||||
typedef KDL::VectorVel derivType;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -3,22 +3,22 @@
|
||||
*/
|
||||
/** @file utility.cpp
|
||||
* @author Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
* @version
|
||||
* @version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
*
|
||||
* @par history
|
||||
* - changed layout of the comments to accommodate doxygen
|
||||
*/
|
||||
|
||||
|
||||
#include "utility.h"
|
||||
|
||||
namespace KDL {
|
||||
|
||||
int STREAMBUFFERSIZE = 10000;
|
||||
int STREAMBUFFERSIZE=10000;
|
||||
int MAXLENFILENAME = 255;
|
||||
const double PI = 3.1415926535897932384626433832795;
|
||||
const double PI= 3.1415926535897932384626433832795;
|
||||
const double deg2rad = 0.01745329251994329576923690768488;
|
||||
const double rad2deg = 57.2957795130823208767981548141052;
|
||||
double epsilon = 0.000001;
|
||||
double epsilon2 = 0.000001 * 0.000001;
|
||||
} // namespace KDL
|
||||
double epsilon2 = 0.000001*0.000001;
|
||||
}
|
||||
|
||||
@@ -1,166 +1,170 @@
|
||||
/*****************************************************************************
|
||||
/*****************************************************************************
|
||||
* Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
*
|
||||
* \version
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
* \par History
|
||||
* - $log$
|
||||
*
|
||||
* \par Release
|
||||
* $Name: $
|
||||
* $Name: $
|
||||
* \file
|
||||
* Included by most lrl-files to provide some general
|
||||
* functions and macro definitions.
|
||||
*
|
||||
*
|
||||
* \par history
|
||||
* - changed layout of the comments to accommodate doxygen
|
||||
*/
|
||||
|
||||
|
||||
#ifndef KDL_UTILITY_H
|
||||
#define KDL_UTILITY_H
|
||||
|
||||
#include "kdl-config.h"
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
|
||||
#ifdef NDEBUG
|
||||
# undef assert
|
||||
# define assert(e) ((void)0)
|
||||
#undef assert
|
||||
#define assert(e) ((void)0)
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// configurable options for the frames library.
|
||||
|
||||
#ifdef KDL_INLINE
|
||||
# ifdef _MSC_VER
|
||||
// Microsoft Visual C
|
||||
# define IMETHOD __forceinline
|
||||
# else
|
||||
// Some other compiler, e.g. gcc
|
||||
# define IMETHOD inline
|
||||
# endif
|
||||
#ifdef _MSC_VER
|
||||
// Microsoft Visual C
|
||||
#define IMETHOD __forceinline
|
||||
#else
|
||||
// Some other compiler, e.g. gcc
|
||||
#define IMETHOD inline
|
||||
#endif
|
||||
#else
|
||||
# define IMETHOD
|
||||
#define IMETHOD
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
//! turn on or off frames bounds checking. If turned on, assert() can still
|
||||
//! be turned off with -DNDEBUG.
|
||||
#ifdef KDL_INDEX_CHECK
|
||||
# define FRAMES_CHECKI(a) assert(a)
|
||||
#define FRAMES_CHECKI(a) assert(a)
|
||||
#else
|
||||
# define FRAMES_CHECKI(a)
|
||||
#define FRAMES_CHECKI(a)
|
||||
#endif
|
||||
|
||||
|
||||
namespace KDL {
|
||||
|
||||
#ifdef __GNUC__
|
||||
// so that sin,cos can be overloaded and complete
|
||||
// resolution of overloaded functions work.
|
||||
using ::acos;
|
||||
using ::asin;
|
||||
using ::atan;
|
||||
using ::atan2;
|
||||
using ::cos;
|
||||
using ::cosh;
|
||||
using ::exp;
|
||||
using ::hypot;
|
||||
using ::log;
|
||||
using ::pow;
|
||||
using ::sin;
|
||||
using ::sinh;
|
||||
using ::sqrt;
|
||||
using ::tan;
|
||||
using ::tanh;
|
||||
// so that sin,cos can be overloaded and complete
|
||||
// resolution of overloaded functions work.
|
||||
using ::sin;
|
||||
using ::cos;
|
||||
using ::exp;
|
||||
using ::log;
|
||||
using ::sin;
|
||||
using ::cos;
|
||||
using ::tan;
|
||||
using ::sinh;
|
||||
using ::cosh;
|
||||
using ::pow;
|
||||
using ::sqrt;
|
||||
using ::atan;
|
||||
using ::hypot;
|
||||
using ::asin;
|
||||
using ::acos;
|
||||
using ::tanh;
|
||||
using ::atan2;
|
||||
#endif
|
||||
#ifndef __GNUC__
|
||||
// only real solution : get Rall1d and varia out of namespaces.
|
||||
# pragma warning(disable : 4786)
|
||||
//only real solution : get Rall1d and varia out of namespaces.
|
||||
#pragma warning (disable:4786)
|
||||
|
||||
inline double sin(double a)
|
||||
{
|
||||
return ::sin(a);
|
||||
}
|
||||
inline double sin(double a) {
|
||||
return ::sin(a);
|
||||
}
|
||||
|
||||
inline double cos(double a) {
|
||||
return ::cos(a);
|
||||
}
|
||||
inline double exp(double a) {
|
||||
return ::exp(a);
|
||||
}
|
||||
inline double log(double a) {
|
||||
return ::log(a);
|
||||
}
|
||||
inline double tan(double a) {
|
||||
return ::tan(a);
|
||||
}
|
||||
inline double cosh(double a) {
|
||||
return ::cosh(a);
|
||||
}
|
||||
inline double sinh(double a) {
|
||||
return ::sinh(a);
|
||||
}
|
||||
inline double sqrt(double a) {
|
||||
return ::sqrt(a);
|
||||
}
|
||||
inline double atan(double a) {
|
||||
return ::atan(a);
|
||||
}
|
||||
inline double acos(double a) {
|
||||
return ::acos(a);
|
||||
}
|
||||
inline double asin(double a) {
|
||||
return ::asin(a);
|
||||
}
|
||||
inline double tanh(double a) {
|
||||
return ::tanh(a);
|
||||
}
|
||||
inline double pow(double a,double b) {
|
||||
return ::pow(a,b);
|
||||
}
|
||||
inline double atan2(double a,double b) {
|
||||
return ::atan2(a,b);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline double cos(double a)
|
||||
{
|
||||
return ::cos(a);
|
||||
}
|
||||
inline double exp(double a)
|
||||
{
|
||||
return ::exp(a);
|
||||
}
|
||||
inline double log(double a)
|
||||
{
|
||||
return ::log(a);
|
||||
}
|
||||
inline double tan(double a)
|
||||
{
|
||||
return ::tan(a);
|
||||
}
|
||||
inline double cosh(double a)
|
||||
{
|
||||
return ::cosh(a);
|
||||
}
|
||||
inline double sinh(double a)
|
||||
{
|
||||
return ::sinh(a);
|
||||
}
|
||||
inline double sqrt(double a)
|
||||
{
|
||||
return ::sqrt(a);
|
||||
}
|
||||
inline double atan(double a)
|
||||
{
|
||||
return ::atan(a);
|
||||
}
|
||||
inline double acos(double a)
|
||||
{
|
||||
return ::acos(a);
|
||||
}
|
||||
inline double asin(double a)
|
||||
{
|
||||
return ::asin(a);
|
||||
}
|
||||
inline double tanh(double a)
|
||||
{
|
||||
return ::tanh(a);
|
||||
}
|
||||
inline double pow(double a, double b)
|
||||
{
|
||||
return ::pow(a, b);
|
||||
}
|
||||
inline double atan2(double a, double b)
|
||||
{
|
||||
return ::atan2(a, b);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Auxiliary class for argument types (Trait-template class )
|
||||
*
|
||||
*
|
||||
* Is used to pass doubles by value, and arbitrary objects by const reference.
|
||||
* This is TWICE as fast (2 x less memory access) and avoids bugs in VC6++ concerning
|
||||
* the assignment of the result of intrinsic functions to const double&-typed variables,
|
||||
* and optimization on.
|
||||
*/
|
||||
template<class T> class TI {
|
||||
public:
|
||||
typedef const T &Arg; //!< Arg is used for passing the element to a function.
|
||||
template <class T>
|
||||
class TI
|
||||
{
|
||||
public:
|
||||
typedef const T& Arg; //!< Arg is used for passing the element to a function.
|
||||
};
|
||||
|
||||
template<> class TI<double> {
|
||||
public:
|
||||
typedef double Arg;
|
||||
template <>
|
||||
class TI<double> {
|
||||
public:
|
||||
typedef double Arg;
|
||||
};
|
||||
|
||||
template<> class TI<int> {
|
||||
public:
|
||||
typedef int Arg;
|
||||
template <>
|
||||
class TI<int> {
|
||||
public:
|
||||
typedef int Arg;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* /note linkage
|
||||
* Something fishy about the difference between C++ and C
|
||||
* in C++ const values default to INTERNAL linkage, in C they default
|
||||
@@ -168,11 +172,11 @@ template<> class TI<int> {
|
||||
* because they, for at least some of them, can be changed by the user.
|
||||
* If you want to explicitly declare internal linkage, use "static".
|
||||
*/
|
||||
//!
|
||||
extern int STREAMBUFFERSIZE;
|
||||
//!
|
||||
extern int STREAMBUFFERSIZE;
|
||||
|
||||
//! maximal length of a file name
|
||||
extern int MAXLENFILENAME;
|
||||
extern int MAXLENFILENAME;
|
||||
|
||||
//! the value of pi
|
||||
extern const double PI;
|
||||
@@ -184,126 +188,114 @@ extern const double deg2rad;
|
||||
extern const double rad2deg;
|
||||
|
||||
//! default precision while comparing with Equal(..,..) functions. Initialized at 0.0000001.
|
||||
extern double epsilon;
|
||||
extern double epsilon;
|
||||
|
||||
//! power or 2 of epsilon
|
||||
extern double epsilon2;
|
||||
extern double epsilon2;
|
||||
|
||||
//! the number of derivatives used in the RN-... objects.
|
||||
extern int VSIZE;
|
||||
extern int VSIZE;
|
||||
|
||||
|
||||
|
||||
#ifndef _MFC_VER
|
||||
# undef max
|
||||
inline double max(double a, double b)
|
||||
{
|
||||
if (b < a)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
#undef max
|
||||
inline double max(double a,double b) {
|
||||
if (b<a)
|
||||
return a;
|
||||
else
|
||||
return b;
|
||||
}
|
||||
|
||||
# undef min
|
||||
inline double min(double a, double b)
|
||||
{
|
||||
if (b < a)
|
||||
return b;
|
||||
else
|
||||
return a;
|
||||
#undef min
|
||||
inline double min(double a,double b) {
|
||||
if (b<a)
|
||||
return b;
|
||||
else
|
||||
return a;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// #pragma inline_depth( 255 )
|
||||
// #pragma inline_recursion( on )
|
||||
# define INLINE __forceinline
|
||||
// #define INLINE inline
|
||||
//#pragma inline_depth( 255 )
|
||||
//#pragma inline_recursion( on )
|
||||
#define INLINE __forceinline
|
||||
//#define INLINE inline
|
||||
#else
|
||||
# define INLINE inline
|
||||
#define INLINE inline
|
||||
#endif
|
||||
|
||||
inline double LinComb(double alfa, double a, double beta, double b)
|
||||
{
|
||||
return alfa * a + beta * b;
|
||||
|
||||
inline double LinComb(double alfa,double a,
|
||||
double beta,double b ) {
|
||||
return alfa*a+beta*b;
|
||||
}
|
||||
|
||||
inline void LinCombR(double alfa, double a, double beta, double b, double &result)
|
||||
{
|
||||
result = alfa * a + beta * b;
|
||||
}
|
||||
inline void LinCombR(double alfa,double a,
|
||||
double beta,double b,double& result ) {
|
||||
result=alfa*a+beta*b;
|
||||
}
|
||||
|
||||
//! to uniformly set double, RNDouble,Vector,... objects to zero in template-classes
|
||||
inline void SetToZero(double &arg)
|
||||
{
|
||||
arg = 0;
|
||||
inline void SetToZero(double& arg) {
|
||||
arg=0;
|
||||
}
|
||||
|
||||
//! to uniformly set double, RNDouble,Vector,... objects to the identity element in
|
||||
//! template-classes
|
||||
inline void SetToIdentity(double &arg)
|
||||
{
|
||||
arg = 1;
|
||||
//! to uniformly set double, RNDouble,Vector,... objects to the identity element in template-classes
|
||||
inline void SetToIdentity(double& arg) {
|
||||
arg=1;
|
||||
}
|
||||
|
||||
inline double sign(double arg)
|
||||
{
|
||||
return (arg < 0) ? (-1) : (1);
|
||||
inline double sign(double arg) {
|
||||
return (arg<0)?(-1):(1);
|
||||
}
|
||||
|
||||
inline double sqr(double arg)
|
||||
{
|
||||
return arg * arg;
|
||||
}
|
||||
inline double Norm(double arg)
|
||||
{
|
||||
return fabs((double)arg);
|
||||
inline double sqr(double arg) { return arg*arg;}
|
||||
inline double Norm(double arg) {
|
||||
return fabs( (double)arg );
|
||||
}
|
||||
|
||||
|
||||
#if defined(__WIN32__) && !defined(__GNUC__)
|
||||
inline double hypot(double y, double x)
|
||||
{
|
||||
return ::_hypot(y, x);
|
||||
}
|
||||
inline double abs(double x)
|
||||
{
|
||||
return ::fabs(x);
|
||||
}
|
||||
inline double hypot(double y,double x) { return ::_hypot(y,x);}
|
||||
inline double abs(double x) { return ::fabs(x);}
|
||||
#endif
|
||||
|
||||
// compares whether 2 doubles are equal in an eps-interval.
|
||||
// Does not check whether a or b represents numbers
|
||||
// On VC6, if a/b is -INF, it returns false;
|
||||
inline bool Equal(double a, double b, double eps = epsilon)
|
||||
inline bool Equal(double a,double b,double eps=epsilon)
|
||||
{
|
||||
double tmp = (a - b);
|
||||
return ((eps > tmp) && (tmp > -eps));
|
||||
double tmp=(a-b);
|
||||
return ((eps>tmp)&& (tmp>-eps) );
|
||||
}
|
||||
|
||||
inline void random(double &a)
|
||||
{
|
||||
a = 1.98 * rand() / (double)RAND_MAX - 0.99;
|
||||
inline void random(double& a) {
|
||||
a = 1.98*rand()/(double)RAND_MAX -0.99;
|
||||
}
|
||||
|
||||
inline void posrandom(double &a)
|
||||
{
|
||||
a = 0.001 + 0.99 * rand() / (double)RAND_MAX;
|
||||
inline void posrandom(double& a) {
|
||||
a = 0.001+0.99*rand()/(double)RAND_MAX;
|
||||
}
|
||||
|
||||
inline double diff(double a, double b, double dt)
|
||||
{
|
||||
return (b - a) / dt;
|
||||
inline double diff(double a,double b,double dt) {
|
||||
return (b-a)/dt;
|
||||
}
|
||||
// inline float diff(float a,float b,double dt) {
|
||||
// return (b-a)/dt;
|
||||
// }
|
||||
inline double addDelta(double a, double da, double dt)
|
||||
{
|
||||
return a + da * dt;
|
||||
//inline float diff(float a,float b,double dt) {
|
||||
//return (b-a)/dt;
|
||||
//}
|
||||
inline double addDelta(double a,double da,double dt) {
|
||||
return a+da*dt;
|
||||
}
|
||||
|
||||
// inline float addDelta(float a,float da,double dt) {
|
||||
//inline float addDelta(float a,float da,double dt) {
|
||||
// return a+da*dt;
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,204 +4,206 @@
|
||||
/*****************************************************************************
|
||||
* Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
*
|
||||
* \version
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
* \par History
|
||||
* - $log$
|
||||
*
|
||||
* \par Release
|
||||
* $Name: $
|
||||
* $Name: $
|
||||
* \todo
|
||||
* make IO routines more robust against the differences between DOS/UNIX end-of-line style.
|
||||
****************************************************************************/
|
||||
|
||||
|
||||
#include "utility_io.h"
|
||||
#include "error.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace KDL {
|
||||
|
||||
//
|
||||
// _functions are private functions
|
||||
// _functions are private functions
|
||||
//
|
||||
|
||||
void _check_istream(std::istream &is)
|
||||
{
|
||||
if ((!is.good()) && (is.eof())) {
|
||||
throw Error_BasicIO_File();
|
||||
}
|
||||
}
|
||||
void _check_istream(std::istream& is)
|
||||
{
|
||||
if ((!is.good())&&(is.eof()) )
|
||||
{
|
||||
throw Error_BasicIO_File();
|
||||
}
|
||||
}
|
||||
// Eats until the end of the line
|
||||
static int _EatUntilEndOfLine(std::istream &is, int *countp = NULL)
|
||||
{
|
||||
int ch;
|
||||
int count;
|
||||
count = 0;
|
||||
do {
|
||||
ch = is.get();
|
||||
count++;
|
||||
_check_istream(is);
|
||||
} while (ch != '\n');
|
||||
if (countp != NULL)
|
||||
*countp = count;
|
||||
return ch;
|
||||
static int _EatUntilEndOfLine( std::istream& is, int* countp=NULL) {
|
||||
int ch;
|
||||
int count;
|
||||
count = 0;
|
||||
do {
|
||||
ch = is.get();
|
||||
count++;
|
||||
_check_istream(is);
|
||||
} while (ch!='\n');
|
||||
if (countp!=NULL) *countp = count;
|
||||
return ch;
|
||||
}
|
||||
|
||||
// Eats until the end of the comment
|
||||
static int _EatUntilEndOfComment(std::istream &is, int *countp = NULL)
|
||||
{
|
||||
int ch;
|
||||
int count;
|
||||
count = 0;
|
||||
int prevch;
|
||||
ch = 0;
|
||||
do {
|
||||
prevch = ch;
|
||||
static int _EatUntilEndOfComment( std::istream& is, int* countp=NULL) {
|
||||
int ch;
|
||||
int count;
|
||||
count = 0;
|
||||
int prevch;
|
||||
ch = 0;
|
||||
do {
|
||||
prevch = ch;
|
||||
ch = is.get();
|
||||
count++;
|
||||
_check_istream(is);
|
||||
if ((prevch=='*')&&(ch=='/')) {
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
if (countp!=NULL) *countp = count;
|
||||
ch = is.get();
|
||||
count++;
|
||||
_check_istream(is);
|
||||
if ((prevch == '*') && (ch == '/')) {
|
||||
break;
|
||||
}
|
||||
} while (true);
|
||||
if (countp != NULL)
|
||||
*countp = count;
|
||||
ch = is.get();
|
||||
return ch;
|
||||
return ch;
|
||||
}
|
||||
|
||||
// Eats space-like characters and comments
|
||||
// possibly returns the number of space-like characters eaten.
|
||||
static int _EatSpace(std::istream &is, int *countp = NULL)
|
||||
{
|
||||
int ch;
|
||||
int count;
|
||||
count = -1;
|
||||
do {
|
||||
_check_istream(is);
|
||||
static int _EatSpace( std::istream& is,int* countp=NULL) {
|
||||
int ch;
|
||||
int count;
|
||||
count=-1;
|
||||
do {
|
||||
_check_istream(is);
|
||||
|
||||
ch = is.get();
|
||||
count++;
|
||||
if (ch == '#') {
|
||||
ch = _EatUntilEndOfLine(is, &count);
|
||||
}
|
||||
if (ch == '/') {
|
||||
ch = is.get();
|
||||
if (ch == '/') {
|
||||
ch = _EatUntilEndOfLine(is, &count);
|
||||
}
|
||||
else if (ch == '*') {
|
||||
ch = _EatUntilEndOfComment(is, &count);
|
||||
}
|
||||
else {
|
||||
is.putback(ch);
|
||||
ch = '/';
|
||||
}
|
||||
}
|
||||
} while ((ch == ' ') || (ch == '\n') || (ch == '\t'));
|
||||
if (countp != NULL)
|
||||
*countp = count;
|
||||
return ch;
|
||||
ch = is.get();
|
||||
count++;
|
||||
if (ch == '#') {
|
||||
ch = _EatUntilEndOfLine(is,&count);
|
||||
}
|
||||
if (ch == '/') {
|
||||
ch = is.get();
|
||||
if (ch == '/') {
|
||||
ch = _EatUntilEndOfLine(is,&count);
|
||||
} else if (ch == '*') {
|
||||
ch = _EatUntilEndOfComment(is,&count);
|
||||
} else {
|
||||
is.putback(ch);
|
||||
ch = '/';
|
||||
}
|
||||
}
|
||||
} while ((ch==' ')||(ch=='\n')||(ch=='\t'));
|
||||
if (countp!=NULL) *countp = count;
|
||||
return ch;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Eats whites, returns, tabs and the delim character
|
||||
// Checks whether delim char. is encountered.
|
||||
void Eat(std::istream &is, int delim)
|
||||
{
|
||||
int ch;
|
||||
ch = _EatSpace(is);
|
||||
if (ch != delim) {
|
||||
throw Error_BasicIO_Exp_Delim();
|
||||
}
|
||||
ch = _EatSpace(is);
|
||||
is.putback(ch);
|
||||
void Eat( std::istream& is, int delim )
|
||||
{
|
||||
int ch;
|
||||
ch=_EatSpace(is);
|
||||
if (ch != delim) {
|
||||
throw Error_BasicIO_Exp_Delim();
|
||||
}
|
||||
ch=_EatSpace(is);
|
||||
is.putback(ch);
|
||||
}
|
||||
|
||||
// Eats whites, returns, tabs and the delim character
|
||||
// Checks whether delim char. is encountered.
|
||||
// EatEnd does not eat all space-like char's at the end.
|
||||
void EatEnd(std::istream &is, int delim)
|
||||
{
|
||||
int ch;
|
||||
ch = _EatSpace(is);
|
||||
if (ch != delim) {
|
||||
throw Error_BasicIO_Exp_Delim();
|
||||
}
|
||||
void EatEnd( std::istream& is, int delim )
|
||||
{
|
||||
int ch;
|
||||
ch=_EatSpace(is);
|
||||
if (ch != delim) {
|
||||
throw Error_BasicIO_Exp_Delim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// For each space in descript, this routine eats whites,tabs, and newlines (at least one)
|
||||
// There should be no consecutive spaces in the description.
|
||||
// for each letter in descript, its reads the corresponding letter in the output
|
||||
// the routine is case insensitive.
|
||||
|
||||
|
||||
// Simple routine, enough for our purposes.
|
||||
// works with ASCII chars
|
||||
inline char Upper(char ch)
|
||||
inline char Upper(char ch)
|
||||
{
|
||||
/*if (('a'<=ch)&&(ch<='z'))
|
||||
return (ch-'a'+'A');
|
||||
else
|
||||
return ch;
|
||||
*/
|
||||
return toupper(ch);
|
||||
/*if (('a'<=ch)&&(ch<='z'))
|
||||
return (ch-'a'+'A');
|
||||
else
|
||||
return ch;
|
||||
*/
|
||||
return toupper(ch);
|
||||
}
|
||||
|
||||
void Eat(std::istream &is, const char *descript)
|
||||
void Eat(std::istream& is,const char* descript)
|
||||
{
|
||||
// eats whites before word
|
||||
char ch;
|
||||
char chdescr;
|
||||
ch = _EatSpace(is);
|
||||
is.putback(ch);
|
||||
const char *p;
|
||||
p = descript;
|
||||
while ((*p) != 0) {
|
||||
chdescr = (char)Upper(*p);
|
||||
if (chdescr == ' ') {
|
||||
int count = 0;
|
||||
ch = _EatSpace(is, &count);
|
||||
is.putback(ch);
|
||||
if (count == 0) {
|
||||
throw Error_BasicIO_Not_A_Space();
|
||||
}
|
||||
// eats whites before word
|
||||
char ch;
|
||||
char chdescr;
|
||||
ch=_EatSpace(is);
|
||||
is.putback(ch);
|
||||
const char* p;
|
||||
p = descript;
|
||||
while ((*p)!=0) {
|
||||
chdescr = (char)Upper(*p);
|
||||
if (chdescr==' ') {
|
||||
int count=0;
|
||||
ch=_EatSpace(is,&count);
|
||||
is.putback(ch);
|
||||
if (count==0) {
|
||||
throw Error_BasicIO_Not_A_Space();
|
||||
}
|
||||
} else {
|
||||
ch=(char)is.get();
|
||||
if (chdescr!=Upper(ch)) {
|
||||
throw Error_BasicIO_Unexpected();
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
else {
|
||||
ch = (char)is.get();
|
||||
if (chdescr != Upper(ch)) {
|
||||
throw Error_BasicIO_Unexpected();
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void EatWord(std::istream &is, const char *delim, char *storage, int maxsize)
|
||||
|
||||
|
||||
void EatWord(std::istream& is,const char* delim,char* storage,int maxsize)
|
||||
{
|
||||
int ch;
|
||||
char *p;
|
||||
int size;
|
||||
// eat white before word
|
||||
ch = _EatSpace(is);
|
||||
p = storage;
|
||||
size = 0;
|
||||
int count = 0;
|
||||
while ((count == 0) && (strchr(delim, ch) == NULL)) {
|
||||
*p = (char)toupper(ch);
|
||||
++p;
|
||||
if (size == maxsize) {
|
||||
throw Error_BasicIO_ToBig();
|
||||
int ch;
|
||||
char* p;
|
||||
int size;
|
||||
// eat white before word
|
||||
ch=_EatSpace(is);
|
||||
p = storage;
|
||||
size=0;
|
||||
int count = 0;
|
||||
while ((count==0)&&(strchr(delim,ch)==NULL)) {
|
||||
*p = (char) toupper(ch);
|
||||
++p;
|
||||
if (size==maxsize) {
|
||||
throw Error_BasicIO_ToBig();
|
||||
}
|
||||
_check_istream(is);
|
||||
++size;
|
||||
//ch = is.get();
|
||||
ch =_EatSpace(is,&count);
|
||||
}
|
||||
_check_istream(is);
|
||||
++size;
|
||||
// ch = is.get();
|
||||
ch = _EatSpace(is, &count);
|
||||
}
|
||||
*p = 0;
|
||||
is.putback(ch);
|
||||
*p=0;
|
||||
is.putback(ch);
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/*****************************************************************************
|
||||
/*****************************************************************************
|
||||
* Erwin Aertbelien, Div. PMA, Dep. of Mech. Eng., K.U.Leuven
|
||||
*
|
||||
* \version
|
||||
* \version
|
||||
* ORO_Geometry V0.2
|
||||
*
|
||||
* \par History
|
||||
* - $log$
|
||||
*
|
||||
* \par Release
|
||||
* $Name: $
|
||||
* $Name: $
|
||||
*
|
||||
* \file utility_io.h
|
||||
* Included by most lrl-files to provide some general
|
||||
@@ -18,34 +18,38 @@
|
||||
#ifndef KDL_UTILITY_IO_H_84822
|
||||
#define KDL_UTILITY_IO_H_84822
|
||||
|
||||
// #include <kdl/kdl-config.h>
|
||||
//#include <kdl/kdl-config.h>
|
||||
|
||||
|
||||
// Standard includes
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
namespace KDL {
|
||||
|
||||
|
||||
/**
|
||||
* checks validity of basic io of is
|
||||
*/
|
||||
void _check_istream(std::istream &is);
|
||||
void _check_istream(std::istream& is);
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Eats characters of the stream until the character delim is encountered
|
||||
* @param is a stream
|
||||
* @param delim eat until this character is encountered
|
||||
*/
|
||||
void Eat(std::istream &is, int delim);
|
||||
void Eat(std::istream& is, int delim );
|
||||
|
||||
/**
|
||||
/**
|
||||
* Eats characters of the stream as long as they satisfy the description in descript
|
||||
* @param is a stream
|
||||
* @param descript description string. A sequence of spaces, tabs,
|
||||
* @param descript description string. A sequence of spaces, tabs,
|
||||
* new-lines and comments is regarded as 1 space in the description string.
|
||||
*/
|
||||
void Eat(std::istream &is, const char *descript);
|
||||
void Eat(std::istream& is,const char* descript);
|
||||
|
||||
/**
|
||||
* Eats a word of the stream delimited by the letters in delim or space(tabs...)
|
||||
@@ -54,16 +58,20 @@ void Eat(std::istream &is, const char *descript);
|
||||
* @param storage for returning the word
|
||||
* @param maxsize a word can be maximally maxsize-1 long.
|
||||
*/
|
||||
void EatWord(std::istream &is, const char *delim, char *storage, int maxsize);
|
||||
void EatWord(std::istream& is,const char* delim,char* storage,int maxsize);
|
||||
|
||||
/**
|
||||
/**
|
||||
* Eats characters of the stream until the character delim is encountered
|
||||
* similar to Eat(is,delim) but spaces at the end are not read.
|
||||
* @param is a stream
|
||||
* @param delim eat until this character is encountered
|
||||
*/
|
||||
void EatEnd(std::istream &is, int delim);
|
||||
void EatEnd( std::istream& is, int delim );
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
} // namespace KDL
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,78 +9,75 @@
|
||||
#ifndef UBLAS_TYPES_HPP_
|
||||
#define UBLAS_TYPES_HPP_
|
||||
|
||||
#include "kdl/chain.hpp"
|
||||
#include <boost/numeric/ublas/matrix.hpp>
|
||||
#include <boost/numeric/ublas/vector.hpp>
|
||||
#include <boost/numeric/ublas/matrix_proxy.hpp>
|
||||
#include <boost/numeric/ublas/vector_proxy.hpp>
|
||||
#include "kdl/frames.hpp"
|
||||
#include "kdl/tree.hpp"
|
||||
#include "kdl/chain.hpp"
|
||||
#include "kdl/jacobian.hpp"
|
||||
#include "kdl/jntarray.hpp"
|
||||
#include "kdl/tree.hpp"
|
||||
#include <boost/numeric/ublas/matrix.hpp>
|
||||
#include <boost/numeric/ublas/matrix_proxy.hpp>
|
||||
#include <boost/numeric/ublas/vector.hpp>
|
||||
#include <boost/numeric/ublas/vector_proxy.hpp>
|
||||
|
||||
namespace iTaSC {
|
||||
|
||||
namespace iTaSC{
|
||||
|
||||
namespace ublas = boost::numeric::ublas;
|
||||
using KDL::Chain;
|
||||
using KDL::Twist;
|
||||
using KDL::Frame;
|
||||
using KDL::Inertia;
|
||||
using KDL::Jacobian;
|
||||
using KDL::JntArray;
|
||||
using KDL::Joint;
|
||||
using KDL::Rotation;
|
||||
using KDL::Segment;
|
||||
using KDL::Inertia;
|
||||
using KDL::SegmentMap;
|
||||
using KDL::Tree;
|
||||
using KDL::Twist;
|
||||
using KDL::JntArray;
|
||||
using KDL::Jacobian;
|
||||
using KDL::Segment;
|
||||
using KDL::Rotation;
|
||||
using KDL::Vector;
|
||||
using KDL::Chain;
|
||||
|
||||
#define u_scalar double
|
||||
#define u_vector ublas::vector<u_scalar>
|
||||
#define u_zero_vector ublas::zero_vector<u_scalar>
|
||||
#define u_matrix ublas::matrix<u_scalar>
|
||||
#define u_matrix6 ublas::matrix<u_scalar, 6, 6>
|
||||
#define u_matrix6 ublas::matrix<u_scalar,6,6>
|
||||
#define u_identity_matrix ublas::identity_matrix<u_scalar>
|
||||
#define u_scalar_vector ublas::scalar_vector<u_scalar>
|
||||
#define u_zero_matrix ublas::zero_matrix<u_scalar>
|
||||
#define u_vector6 ublas::bounded_vector<u_scalar, 6>
|
||||
#define u_vector6 ublas::bounded_vector<u_scalar,6>
|
||||
|
||||
inline static int changeBase(const u_matrix &J_in, const Frame &T, u_matrix &J_out)
|
||||
{
|
||||
inline static int changeBase(const u_matrix& J_in, const Frame& T, u_matrix& J_out) {
|
||||
|
||||
if (J_out.size1() != 6 || J_in.size1() != 6 || J_in.size2() != J_out.size2())
|
||||
return -1;
|
||||
for (unsigned int j = 0; j < J_in.size2(); ++j) {
|
||||
ublas::matrix_column<const u_matrix> Jj_in = column(J_in, j);
|
||||
ublas::matrix_column<u_matrix> Jj_out = column(J_out, j);
|
||||
Twist arg;
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
arg(i) = Jj_in(i);
|
||||
Twist tmp(T * arg);
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
Jj_out(i) = tmp(i);
|
||||
}
|
||||
return 0;
|
||||
if (J_out.size1() != 6 || J_in.size1() != 6 || J_in.size2() != J_out.size2())
|
||||
return -1;
|
||||
for (unsigned int j = 0; j < J_in.size2(); ++j) {
|
||||
ublas::matrix_column<const u_matrix > Jj_in = column(J_in,j);
|
||||
ublas::matrix_column<u_matrix > Jj_out = column(J_out,j);
|
||||
Twist arg;
|
||||
for(unsigned int i=0;i<6;++i)
|
||||
arg(i)=Jj_in(i);
|
||||
Twist tmp(T*arg);
|
||||
for(unsigned int i=0;i<6;++i)
|
||||
Jj_out(i)=tmp(i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
inline static int changeBase(const ublas::matrix_range<u_matrix> &J_in,
|
||||
const Frame &T,
|
||||
ublas::matrix_range<u_matrix> &J_out)
|
||||
{
|
||||
inline static int changeBase(const ublas::matrix_range<u_matrix >& J_in, const Frame& T, ublas::matrix_range<u_matrix >& J_out) {
|
||||
|
||||
if (J_out.size1() != 6 || J_in.size1() != 6 || J_in.size2() != J_out.size2())
|
||||
return -1;
|
||||
for (unsigned int j = 0; j < J_in.size2(); ++j) {
|
||||
ublas::matrix_column<const ublas::matrix_range<u_matrix>> Jj_in = column(J_in, j);
|
||||
ublas::matrix_column<ublas::matrix_range<u_matrix>> Jj_out = column(J_out, j);
|
||||
Twist arg;
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
arg(i) = Jj_in(i);
|
||||
Twist tmp(T * arg);
|
||||
for (unsigned int i = 0; i < 6; ++i)
|
||||
Jj_out(i) = tmp(i);
|
||||
}
|
||||
return 0;
|
||||
if (J_out.size1() != 6 || J_in.size1() != 6 || J_in.size2() != J_out.size2())
|
||||
return -1;
|
||||
for (unsigned int j = 0; j < J_in.size2(); ++j) {
|
||||
ublas::matrix_column<const ublas::matrix_range<u_matrix > > Jj_in = column(J_in,j);
|
||||
ublas::matrix_column<ublas::matrix_range<u_matrix > > Jj_out = column(J_out,j);
|
||||
Twist arg;
|
||||
for(unsigned int i=0;i<6;++i)
|
||||
arg(i)=Jj_in(i);
|
||||
Twist tmp(T*arg);
|
||||
for(unsigned int i=0;i<6;++i)
|
||||
Jj_out(i)=tmp(i);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace iTaSC
|
||||
}
|
||||
#endif /* UBLAS_TYPES_HPP_ */
|
||||
|
||||
Reference in New Issue
Block a user