Program Listing for File model.hxx
↰ Return to documentation for file (include/pinocchio/algorithm/model.hxx
)
//
// Copyright (c) 2019-2022 CNRS INRIA
//
#ifndef __pinocchio_algorithm_model_hxx__
#define __pinocchio_algorithm_model_hxx__
#include <algorithm>
namespace pinocchio
{
namespace details
{
// Retrieve the joint id in model_out, given the info of model_in.
// If the user change all the joint names, the universe name won't correspond to the first joint in the tree when searching by name.
// We thus need to retrieve it with other means, e.g. checking the index of the joints.
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
JointIndex getJointId(const ModelTpl<Scalar,Options,JointCollectionTpl> & model_in,
const ModelTpl<Scalar,Options,JointCollectionTpl> & model_out,
const std::string & joint_name_in_model_in)
{
const JointIndex joint_id = model_in.getJointId(joint_name_in_model_in);
assert(joint_id < model_in.joints.size());
if(joint_id == 0 && model_in.parents[0] == 0) // This is the universe, maybe renamed.
return model_out.getJointId(model_out.names[0]);
else
return model_out.getJointId(joint_name_in_model_in);
}
// Retrieve the frame id in model_out, given the info of model_in.
// If the user change all the frame names, the universe name won't correspond to the first frame in the tree when searching by name.
// We thus need to retrieve it with other means, e.g. checking the fields of the frames.
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
FrameIndex getFrameId(const ModelTpl<Scalar,Options,JointCollectionTpl> & model_in,
const ModelTpl<Scalar,Options,JointCollectionTpl> & model_out,
const std::string & frame_name_in_model_in,
const FrameType & type)
{
const FrameIndex frame_id = model_in.getFrameId(frame_name_in_model_in);
assert(frame_id < model_in.frames.size());
if(frame_id == 0 && model_in.frames[0].previousFrame == 0 && model_in.frames[0].parent == 0) // This is the universe, maybe renamed.
return model_out.getFrameId(model_out.frames[0].name,type);
else
return model_out.getFrameId(frame_name_in_model_in,type);
}
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
void appendUniverseToModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & modelAB,
const GeometryModel & geomModelAB,
FrameIndex parentFrame,
const SE3Tpl<Scalar, Options> & pfMAB,
ModelTpl<Scalar,Options,JointCollectionTpl> & model,
GeometryModel & geomModel)
{
typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
typedef typename Model::Frame Frame;
PINOCCHIO_THROW(parentFrame < model.frames.size(),
std::invalid_argument,
"parentFrame is greater than the size of the frames vector.");
const Frame & pframe = model.frames[parentFrame];
JointIndex jid = pframe.parent;
assert(jid < model.joints.size());
// If inertia is not NaN, add it.
if (modelAB.inertias[0] == modelAB.inertias[0])
model.appendBodyToJoint (jid, modelAB.inertias[0], pframe.placement * pfMAB);
// Add all frames whose parent is this joint.
for (FrameIndex fid = 1; fid < modelAB.frames.size(); ++fid)
{
Frame frame = modelAB.frames[fid];
if (frame.parent == 0)
{
PINOCCHIO_CHECK_INPUT_ARGUMENT(!model.existFrame(frame.name, frame.type),
"The two models have conflicting frame names.");
frame.parent = jid;
if (frame.previousFrame != 0)
{
frame.previousFrame = getFrameId(modelAB,model,modelAB.frames[frame.previousFrame].name,
modelAB.frames[frame.previousFrame].type);
}
else
{
frame.previousFrame = parentFrame;
}
// Modify frame placement
frame.placement = pframe.placement * pfMAB * frame.placement;
model.addFrame (frame);
}
}
// Add all geometries whose parent is this joint.
for (GeomIndex gid = 0; gid < geomModelAB.geometryObjects.size(); ++gid)
{
GeometryObject go = geomModelAB.geometryObjects[gid];
if (go.parentJoint == 0)
{
go.parentJoint = jid;
if (go.parentFrame != 0)
{
go.parentFrame = getFrameId(modelAB,model,modelAB.frames[go.parentFrame].name,
modelAB.frames[go.parentFrame].type);
}
else
{
go.parentFrame = parentFrame;
}
go.placement = pframe.placement * pfMAB * go.placement;
geomModel.addGeometryObject (go);
}
}
}
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
struct AppendJointOfModelAlgoTpl
: public fusion::JointUnaryVisitorBase< AppendJointOfModelAlgoTpl<Scalar,Options,JointCollectionTpl> >
{
typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
typedef typename Model::Frame Frame;
typedef boost::fusion::vector<
const Model &,
const GeometryModel&,
JointIndex,
const typename Model::SE3 &,
Model &,
GeometryModel& > ArgsType;
template <typename JointModel>
static void algo (const JointModelBase<JointModel> & jmodel_in,
const Model & modelAB,
const GeometryModel & geomModelAB,
JointIndex parent_id,
const typename Model::SE3 & pMi,
Model & model,
GeometryModel & geomModel)
{
// If old parent is universe, use what's provided in the input.
// otherwise, get the parent from modelAB.
const JointIndex joint_id_in = jmodel_in.id();
if (modelAB.parents[joint_id_in] > 0)
parent_id = getJointId(modelAB,model,modelAB.names[modelAB.parents[joint_id_in]]);
PINOCCHIO_CHECK_INPUT_ARGUMENT(!model.existJointName(modelAB.names[joint_id_in]),
"The two models have conflicting joint names.");
JointIndex joint_id_out = model.addJoint(parent_id,
jmodel_in,
pMi * modelAB.jointPlacements[joint_id_in],
modelAB.names[joint_id_in],
jmodel_in.jointVelocitySelector(modelAB.effortLimit),
jmodel_in.jointVelocitySelector(modelAB.velocityLimit),
jmodel_in.jointConfigSelector(modelAB.lowerPositionLimit),
jmodel_in.jointConfigSelector(modelAB.upperPositionLimit),
jmodel_in.jointVelocitySelector(modelAB.friction),
jmodel_in.jointVelocitySelector(modelAB.damping));
assert(joint_id_out < model.joints.size());
model.appendBodyToJoint(joint_id_out, modelAB.inertias[joint_id_in]);
const typename Model::JointModel & jmodel_out = model.joints[joint_id_out];
jmodel_out.jointVelocitySelector(model.rotorInertia) = jmodel_in.jointVelocitySelector(modelAB.rotorInertia);
jmodel_out.jointVelocitySelector(model.rotorGearRatio) = jmodel_in.jointVelocitySelector(modelAB.rotorGearRatio);
// Add all frames whose parent is this joint.
for (FrameIndex fid = 1; fid < modelAB.frames.size(); ++fid)
{
Frame frame = modelAB.frames[fid];
if (frame.parent == jmodel_in.id())
{
PINOCCHIO_CHECK_INPUT_ARGUMENT(!model.existFrame(frame.name, frame.type),
"The two models have conflicting frame names.");
frame.parent = joint_id_out;
assert (frame.previousFrame > 0 || frame.type == JOINT);
if (frame.previousFrame != 0)
{
frame.previousFrame = getFrameId(modelAB,model,modelAB.frames[frame.previousFrame].name,modelAB.frames[frame.previousFrame].type);
}
model.addFrame(frame);
}
}
// Add all geometries whose parent is this joint.
for(GeomIndex gid = 0; gid < geomModelAB.geometryObjects.size(); ++gid)
{
GeometryObject go = geomModelAB.geometryObjects[gid];
if(go.parentJoint == joint_id_in)
{
go.parentJoint = joint_id_out;
assert(go.parentFrame > 0);
if(go.parentFrame != 0 && go.parentFrame < modelAB.frames.size())
{
go.parentFrame = getFrameId(modelAB,model,modelAB.frames[go.parentFrame].name,modelAB.frames[go.parentFrame].type);
}
geomModel.addGeometryObject(go);
}
}
}
};
} // namespace details
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
void
appendModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & modelA,
const ModelTpl<Scalar,Options,JointCollectionTpl> & modelB,
const FrameIndex frameInModelA,
const SE3Tpl<Scalar, Options> & aMb,
ModelTpl<Scalar,Options,JointCollectionTpl> & model)
{
GeometryModel geomModelA, geomModelB, geomModel;
appendModel(modelA, modelB, geomModelA, geomModelB, frameInModelA, aMb,
model, geomModel);
}
// Compute whether Joint child is a descendent of parent in a given model
// Joints are represented by their id in the model
template <typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
static bool hasAncestor(const ModelTpl<Scalar,Options,JointCollectionTpl> & model,
JointIndex child, JointIndex parent)
{
typedef typename ModelTpl<Scalar,Options,JointCollectionTpl>::IndexVector IndexVector_t;
// Any joints has universe as an acenstor
assert(model.supports[child][0] == 0);
for (typename IndexVector_t::const_iterator it=model.supports[child].begin();
it!=model.supports[child].end(); ++it)
{
if (*it == parent) return true;
}
return false;
}
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl>
void
appendModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & modelA,
const ModelTpl<Scalar,Options,JointCollectionTpl> & modelB,
const GeometryModel& geomModelA,
const GeometryModel& geomModelB,
const FrameIndex frameInModelA,
const SE3Tpl<Scalar, Options>& aMb,
ModelTpl<Scalar,Options,JointCollectionTpl>& model,
GeometryModel& geomModel)
{
typedef details::AppendJointOfModelAlgoTpl<Scalar, Options, JointCollectionTpl> AppendJointOfModelAlgo;
typedef typename AppendJointOfModelAlgo::ArgsType ArgsType;
PINOCCHIO_CHECK_INPUT_ARGUMENT((bool)(frameInModelA < (FrameIndex) modelA.nframes),
"frameInModelA is an invalid Frame index, greater than the number of frames contained in modelA.");
typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
typedef typename Model::SE3 SE3;
typedef typename Model::Frame Frame;
const Frame & frame = modelA.frames[frameInModelA];
static const SE3 id = SE3::Identity();
int njoints = modelA.njoints + modelB.njoints - 1;
model.names .reserve ((size_t)njoints);
model.joints .reserve ((size_t)njoints);
model.jointPlacements .reserve ((size_t)njoints);
model.parents .reserve ((size_t)njoints);
model.inertias .reserve ((size_t)njoints);
int nframes = modelA.nframes + modelB.nframes - 1;
model.frames .reserve ((size_t)nframes);
geomModel.geometryObjects.reserve (geomModelA.ngeoms + geomModelB.ngeoms);
details::appendUniverseToModel (modelA, geomModelA, 0, id, model, geomModel);
// Compute joints of A that should be added before and after joints of B
std::vector<JointIndex> AJointsBeforeB;
std::vector<JointIndex> AJointsAfterB;
// All joints until the parent of frameInModelA come first
for (JointIndex jid = 1; jid <= frame.parent; ++jid)
{
AJointsBeforeB.push_back(jid);
}
// descendants of the parent of frameInModelA come also before model B
// TODO(jcarpent): enhancement by taking into account the compactness of the joint ordering.
for (JointIndex jid = frame.parent+1; jid < modelA.joints.size(); ++jid)
{
if (hasAncestor(modelA, jid, frame.parent))
{
AJointsBeforeB.push_back(jid);
} else
{
AJointsAfterB.push_back(jid);
}
}
// Copy modelA joints that should come before model B
for (std::vector<JointIndex>::const_iterator jid = AJointsBeforeB.begin();
jid !=AJointsBeforeB.end(); ++jid)
{
ArgsType args (modelA, geomModelA, 0, id, model, geomModel);
AppendJointOfModelAlgo::run (modelA.joints[*jid], args);
}
// Copy modelB joints
details::appendUniverseToModel (modelB, geomModelB,
details::getFrameId(modelA,model,frame.name,frame.type), aMb, model, geomModel);
for (JointIndex jid = 1; jid < modelB.joints.size(); ++jid)
{
SE3 pMi = (jid == 1 ? frame.placement * aMb : id);
ArgsType args (modelB, geomModelB, frame.parent, pMi, model, geomModel);
AppendJointOfModelAlgo::run (modelB.joints[jid], args);
}
// Copy remaining joints of modelA
// Copy modelA joints that should come before model B
for (std::vector<JointIndex>::const_iterator jid = AJointsAfterB.begin();
jid!=AJointsAfterB.end(); ++jid)
{
ArgsType args (modelA, geomModelA, 0, id, model, geomModel);
AppendJointOfModelAlgo::run (modelA.joints[*jid], args);
}
#ifdef PINOCCHIO_WITH_HPP_FCL
// Add collision pairs of geomModelA and geomModelB
geomModel.collisionPairs.reserve(geomModelA.collisionPairs.size()
+ geomModelB.collisionPairs.size()
+ geomModelA.geometryObjects.size() * geomModelB.geometryObjects.size());
for (std::size_t icp = 0; icp < geomModelA.collisionPairs.size(); ++icp)
{
const CollisionPair& cp = geomModelA.collisionPairs[icp];
GeomIndex go1 = geomModel.getGeometryId(geomModelA.geometryObjects[cp.first ].name);
GeomIndex go2 = geomModel.getGeometryId(geomModelA.geometryObjects[cp.second].name);
geomModel.addCollisionPair (CollisionPair (go1, go2));
}
for (std::size_t icp = 0; icp < geomModelB.collisionPairs.size(); ++icp)
{
const CollisionPair & cp = geomModelB.collisionPairs[icp];
GeomIndex go1 = geomModel.getGeometryId(geomModelB.geometryObjects[cp.first ].name);
GeomIndex go2 = geomModel.getGeometryId(geomModelB.geometryObjects[cp.second].name);
geomModel.addCollisionPair (CollisionPair (go1, go2));
}
// add the collision pairs between geomModelA and geomModelB.
for (Index i = 0; i < geomModelA.geometryObjects.size(); ++i)
{
GeomIndex go1 = geomModel.getGeometryId(geomModelA.geometryObjects[i].name);
for (Index j = 0; j < geomModelB.geometryObjects.size(); ++j)
{
GeomIndex go2 = geomModel.getGeometryId(geomModelB.geometryObjects[j].name);
if ( geomModel.geometryObjects[go1].parentJoint
!= geomModel.geometryObjects[go2].parentJoint)
geomModel.addCollisionPair(CollisionPair(go1, go2));
}
}
#endif
}
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
void
buildReducedModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & input_model,
std::vector<JointIndex> list_of_joints_to_lock,
const Eigen::MatrixBase<ConfigVectorType> & reference_configuration,
ModelTpl<Scalar,Options,JointCollectionTpl> & reduced_model)
{
PINOCCHIO_CHECK_ARGUMENT_SIZE(reference_configuration.size(), input_model.nq,
"The configuration vector is not of right size");
PINOCCHIO_CHECK_INPUT_ARGUMENT(list_of_joints_to_lock.size() <= (size_t)input_model.njoints,
"The number of joints to lock is greater than the total of joints in the reduced_model");
typedef ModelTpl<Scalar,Options,JointCollectionTpl> Model;
typedef typename Model::JointModel JointModel;
typedef typename Model::JointData JointData;
typedef typename Model::Frame Frame;
typedef typename Model::SE3 SE3;
// Sort indexes
std::sort(list_of_joints_to_lock.begin(),list_of_joints_to_lock.end());
typename Model::FrameVector::const_iterator frame_it = input_model.frames.begin();
// Check that they are not two identical elements
for(size_t id = 1; id < list_of_joints_to_lock.size(); ++id)
{
PINOCCHIO_CHECK_INPUT_ARGUMENT(list_of_joints_to_lock[id-1] < list_of_joints_to_lock[id],
"The input list_of_joints_to_lock contains two identical indexes.");
}
// Reserve memory
const Eigen::DenseIndex njoints = input_model.njoints - (Eigen::DenseIndex)list_of_joints_to_lock.size();
reduced_model.names .reserve((size_t)njoints);
reduced_model.joints .reserve((size_t)njoints);
reduced_model.jointPlacements .reserve((size_t)njoints);
reduced_model.parents .reserve((size_t)njoints);
reduced_model.names[0] = input_model.names[0];
reduced_model.joints[0] = input_model.joints[0];
reduced_model.jointPlacements[0] = input_model.jointPlacements[0];
reduced_model.parents[0] = input_model.parents[0];
reduced_model.inertias[0] = input_model.inertias[0];
reduced_model.name = input_model.name;
reduced_model.gravity = input_model.gravity;
size_t current_index_to_lock = 0;
for(JointIndex joint_id = 1; joint_id < (JointIndex)input_model.njoints; ++joint_id)
{
const JointIndex joint_id_to_lock = (current_index_to_lock < list_of_joints_to_lock.size()) ? list_of_joints_to_lock[current_index_to_lock] : 0;
const JointIndex input_parent_joint_index = input_model.parents[joint_id];
const std::string & joint_name = input_model.names[joint_id];
const JointModel & joint_input_model = input_model.joints[joint_id];
// retrieve the closest joint parent in the new kinematic tree
const std::string & parent_joint_name = input_model.names[input_parent_joint_index];
const bool exist_parent_joint = reduced_model.existJointName(parent_joint_name);
const JointIndex reduced_parent_joint_index
= exist_parent_joint
? reduced_model.getJointId(parent_joint_name)
: reduced_model.frames[reduced_model.getFrameId(parent_joint_name)].parent;
const SE3 parent_frame_placement
= exist_parent_joint
? SE3::Identity()
: reduced_model.frames[reduced_model.getFrameId(parent_joint_name)].placement;
const FrameIndex reduced_previous_frame_index
= exist_parent_joint
? 0
: reduced_model.getFrameId(parent_joint_name);
if(joint_id == joint_id_to_lock)
{
// the joint should not be added to the Model but aggragated to its parent joint
//Add frames up to the joint to lock
while((*frame_it).name != joint_name)
{
++frame_it;
const Frame & input_frame = *frame_it;
if(input_frame.name == joint_name)
break;
const std::string & support_joint_name = input_model.names[input_frame.parent];
std::vector<JointIndex>::const_iterator support_joint_it = std::find(list_of_joints_to_lock.begin(),
list_of_joints_to_lock.end(),
input_frame.parent);
if(support_joint_it != list_of_joints_to_lock.end())
{
if( input_frame.type == JOINT
&& reduced_model.existFrame(input_frame.name)
&& support_joint_name == input_frame.name)
continue; // this means that the Joint is now fixed and has been replaced by a Frame. No need to add a new one.
// The joint has been removed and replaced by a Frame
const FrameIndex joint_frame_id = reduced_model.getFrameId(support_joint_name);
const Frame & joint_frame = reduced_model.frames[joint_frame_id];
Frame reduced_frame = input_frame;
reduced_frame.placement = joint_frame.placement * input_frame.placement;
reduced_frame.parent = joint_frame.parent;
reduced_frame.previousFrame = reduced_model.getFrameId(input_model.frames[input_frame.previousFrame].name);
reduced_model.addFrame(reduced_frame, false);
}
else
{
Frame reduced_frame = input_frame;
reduced_frame.parent = reduced_model.getJointId(input_model.names[input_frame.parent]);
reduced_frame.previousFrame = reduced_model.getFrameId(input_model.frames[input_frame.previousFrame].name);
reduced_model.addFrame(reduced_frame, false);
}
}
// Compute the new placement of the joint with respect to its parent joint in the new kinematic tree.
JointData joint_data = joint_input_model.createData();
joint_input_model.calc(joint_data,reference_configuration);
const SE3 liMi = parent_frame_placement * input_model.jointPlacements[joint_id] * joint_data.M();
Frame frame = Frame(joint_name,
reduced_parent_joint_index, reduced_previous_frame_index,
liMi,
FIXED_JOINT,
input_model.inertias[joint_id]);
FrameIndex frame_id = reduced_model.addFrame(frame);
reduced_model.frames[frame_id].previousFrame = frame_id; // a bit weird, but this is a solution for missing parent frame
current_index_to_lock++;
}
else
{
// the joint should be added to the Model as it is
JointIndex reduced_joint_id = reduced_model.addJoint(reduced_parent_joint_index,
joint_input_model,
parent_frame_placement * input_model.jointPlacements[joint_id],
joint_name,
joint_input_model.jointVelocitySelector(input_model.effortLimit),
joint_input_model.jointVelocitySelector(input_model.velocityLimit),
joint_input_model.jointConfigSelector(input_model.lowerPositionLimit),
joint_input_model.jointConfigSelector(input_model.upperPositionLimit),
joint_input_model.jointVelocitySelector(input_model.friction),
joint_input_model.jointVelocitySelector(input_model.damping));
// Append inertia
reduced_model.appendBodyToJoint(reduced_joint_id,
input_model.inertias[joint_id],
SE3::Identity());
// Copy other kinematics and dynamics properties
const typename Model::JointModel & jmodel_out = reduced_model.joints[reduced_joint_id];
jmodel_out.jointVelocitySelector(reduced_model.rotorInertia)
= joint_input_model.jointVelocitySelector(input_model.rotorInertia);
jmodel_out.jointVelocitySelector(reduced_model.rotorGearRatio)
= joint_input_model.jointVelocitySelector(input_model.rotorGearRatio);
}
}
// Retrieve and extend the reference configurations
typedef typename Model::ConfigVectorMap ConfigVectorMap;
for(typename ConfigVectorMap::const_iterator config_it = input_model.referenceConfigurations.begin();
config_it != input_model.referenceConfigurations.end(); ++config_it)
{
const std::string & config_name = config_it->first;
const typename Model::ConfigVectorType & input_config_vector = config_it->second;
typename Model::ConfigVectorType reduced_config_vector(reduced_model.nq);
for(JointIndex reduced_joint_id = 1;
reduced_joint_id < reduced_model.joints.size();
++reduced_joint_id)
{
const JointIndex input_joint_id = input_model.getJointId(reduced_model.names[reduced_joint_id]);
const JointModel & input_joint_model = input_model.joints[input_joint_id];
const JointModel & reduced_joint_model = reduced_model.joints[reduced_joint_id];
reduced_joint_model.jointConfigSelector(reduced_config_vector) = input_joint_model.jointConfigSelector(input_config_vector);
}
reduced_model.referenceConfigurations.insert(std::make_pair(config_name, reduced_config_vector));
}
// Add all the missing frames
for(;frame_it != input_model.frames.end(); ++frame_it)
{
const Frame & input_frame = *frame_it;
const std::string & support_joint_name = input_model.names[input_frame.parent];
std::vector<JointIndex>::const_iterator support_joint_it = std::find(list_of_joints_to_lock.begin(),
list_of_joints_to_lock.end(),
input_frame.parent);
if(support_joint_it != list_of_joints_to_lock.end())
{
if( input_frame.type == JOINT
&& reduced_model.existFrame(input_frame.name)
&& support_joint_name == input_frame.name)
continue; // this means that the Joint is now fixed and has been replaced by a Frame. No need to add a new one.
// The joint has been removed and replaced by a Frame
const FrameIndex joint_frame_id = reduced_model.getFrameId(support_joint_name);
const Frame & joint_frame = reduced_model.frames[joint_frame_id];
Frame reduced_frame = input_frame;
reduced_frame.placement = joint_frame.placement * input_frame.placement;
reduced_frame.parent = joint_frame.parent;
reduced_frame.previousFrame = reduced_model.getFrameId(input_model.frames[input_frame.previousFrame].name);
reduced_model.addFrame(reduced_frame, false);
}
else
{
Frame reduced_frame = input_frame;
reduced_frame.parent = reduced_model.getJointId(input_model.names[input_frame.parent]);
reduced_frame.previousFrame = reduced_model.getFrameId(input_model.frames[input_frame.previousFrame].name);
reduced_model.addFrame(reduced_frame, false);
}
}
}
template<typename Scalar, int Options, template<typename,int> class JointCollectionTpl, typename ConfigVectorType>
void
buildReducedModel(const ModelTpl<Scalar,Options,JointCollectionTpl> & input_model,
const GeometryModel & input_geom_model,
const std::vector<JointIndex> & list_of_joints_to_lock,
const Eigen::MatrixBase<ConfigVectorType> & reference_configuration,
ModelTpl<Scalar,Options,JointCollectionTpl> & reduced_model,
GeometryModel & reduced_geom_model)
{
const std::vector<GeometryModel> temp_input_geoms(1,input_geom_model);
std::vector<GeometryModel> temp_reduced_geom_models;
buildReducedModel(input_model, temp_input_geoms, list_of_joints_to_lock,
reference_configuration, reduced_model,
temp_reduced_geom_models);
reduced_geom_model = temp_reduced_geom_models.front();
}
template <typename Scalar, int Options,
template <typename, int> class JointCollectionTpl,
typename GeometryModelAllocator,
typename ConfigVectorType>
void buildReducedModel(
const ModelTpl<Scalar, Options, JointCollectionTpl> &input_model,
const std::vector<GeometryModel,GeometryModelAllocator> &list_of_geom_models,
const std::vector<JointIndex> &list_of_joints_to_lock,
const Eigen::MatrixBase<ConfigVectorType> &reference_configuration,
ModelTpl<Scalar, Options, JointCollectionTpl> &reduced_model,
std::vector<GeometryModel,GeometryModelAllocator> &list_of_reduced_geom_models) {
typedef ModelTpl<Scalar, Options, JointCollectionTpl> Model;
buildReducedModel(input_model, list_of_joints_to_lock, reference_configuration, reduced_model);
// for all GeometryModels
for (size_t gmi = 0; gmi < list_of_geom_models.size(); ++gmi) {
const GeometryModel &input_geom_model = list_of_geom_models[gmi];
GeometryModel reduced_geom_model;
// Add all the geometries
typedef GeometryModel::GeometryObject GeometryObject;
typedef GeometryModel::GeometryObjectVector GeometryObjectVector;
for(GeometryObjectVector::const_iterator it = input_geom_model.geometryObjects.begin();
it != input_geom_model.geometryObjects.end(); ++it)
{
const GeometryModel::GeometryObject & geom = *it;
const JointIndex joint_id_in_input_model = geom.parentJoint;
_PINOCCHIO_CHECK_INPUT_ARGUMENT_2((joint_id_in_input_model < (JointIndex)input_model.njoints),
"Invalid joint parent index for the geometry with name " + geom.name);
const std::string & parent_joint_name = input_model.names[joint_id_in_input_model];
JointIndex reduced_joint_id = (JointIndex)-1;
typedef typename Model::SE3 SE3;
SE3 relative_placement = SE3::Identity();
if(reduced_model.existJointName(parent_joint_name))
{
reduced_joint_id = reduced_model.getJointId(parent_joint_name);
}
else // The joint is now a frame
{
const FrameIndex reduced_frame_id = reduced_model.getFrameId(parent_joint_name);
reduced_joint_id = reduced_model.frames[reduced_frame_id].parent;
relative_placement = reduced_model.frames[reduced_frame_id].placement;
}
GeometryObject reduced_geom(geom);
reduced_geom.parentJoint = reduced_joint_id;
reduced_geom.parentFrame = reduced_model.getBodyId(
input_model.frames[geom.parentFrame].name);
reduced_geom.placement = relative_placement * geom.placement;
reduced_geom_model.addGeometryObject(reduced_geom);
}
#ifdef PINOCCHIO_WITH_HPP_FCL
// Add all the collision pairs - the index of the geometry objects should have not changed
typedef GeometryModel::CollisionPairVector CollisionPairVector;
for(CollisionPairVector::const_iterator it = input_geom_model.collisionPairs.begin();
it != input_geom_model.collisionPairs.end(); ++it)
{
const CollisionPair & cp = *it;
reduced_geom_model.addCollisionPair(cp);
}
#endif
list_of_reduced_geom_models.push_back(reduced_geom_model);
}
}
} // namespace pinocchio
#endif // ifndef __pinocchio_algorithm_model_hxx__