pxmlw6n2f/Gazebo_Distributed_MPI/gazebo/common/Skeleton.cc

694 lines
17 KiB
C++

/*
* Copyright (C) 2012 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <list>
#include "gazebo/common/Skeleton.hh"
#include "gazebo/common/SkeletonAnimation.hh"
#include "gazebo/math/Angle.hh"
using namespace gazebo;
using namespace common;
//////////////////////////////////////////////////
Skeleton::Skeleton()
{
}
//////////////////////////////////////////////////
Skeleton::Skeleton(SkeletonNode *_root)
{
this->root = _root;
this->BuildNodeMap();
}
//////////////////////////////////////////////////
Skeleton::~Skeleton()
{
delete this->root;
}
//////////////////////////////////////////////////
void Skeleton::SetRootNode(SkeletonNode* _node)
{
this->root = _node;
this->BuildNodeMap();
}
//////////////////////////////////////////////////
SkeletonNode* Skeleton::GetRootNode()
{
return this->root;
}
//////////////////////////////////////////////////
SkeletonNode* Skeleton::GetNodeByName(std::string _name)
{
for (std::map<unsigned int, SkeletonNode*>::iterator iter =
this->nodes.begin(); iter != this->nodes.end(); ++iter)
if (iter->second->GetName() == _name)
return iter->second;
return NULL;
}
//////////////////////////////////////////////////
SkeletonNode* Skeleton::GetNodeById(std::string _id)
{
for (std::map<unsigned int, SkeletonNode*>::iterator iter =
this->nodes.begin(); iter != this->nodes.end(); ++iter)
if (iter->second->GetId() == _id)
return iter->second;
return NULL;
}
//////////////////////////////////////////////////
SkeletonNode* Skeleton::GetNodeByHandle(unsigned int _handle)
{
return this->nodes[_handle];
}
//////////////////////////////////////////////////
unsigned int Skeleton::GetNumNodes()
{
return this->nodes.size();
}
//////////////////////////////////////////////////
unsigned int Skeleton::GetNumJoints()
{
unsigned int c = 0;
for (std::map<unsigned int, SkeletonNode*>::iterator iter =
this->nodes.begin(); iter != this->nodes.end(); ++iter)
if (iter->second->IsJoint())
c++;
return c;
}
//////////////////////////////////////////////////
void Skeleton::Scale(double _scale)
{
// scale skeleton structure
for (NodeMap::iterator iter = this->nodes.begin();
iter != this->nodes.end(); ++iter)
{
SkeletonNode *node = iter->second;
ignition::math::Matrix4d trans(node->Transform());
ignition::math::Vector3d pos(trans.Translation());
trans.Translate(pos * _scale);
node->SetTransform(trans, false);
}
// update the nodes' model transforms
this->root->UpdateChildrenTransforms();
// scale the animation data
for (unsigned int i = 0; i < this->anims.size(); ++i)
this->anims[i]->Scale(_scale);
}
//////////////////////////////////////////////////
void Skeleton::BuildNodeMap()
{
std::list<SkeletonNode*> toVisit;
toVisit.push_front(this->root);
unsigned int handle = 0;
while (!toVisit.empty())
{
SkeletonNode *node = toVisit.front();
toVisit.pop_front();
for (int i = (node->GetChildCount() - 1); i >= 0; i--)
toVisit.push_front(node->GetChild(i));
node->SetHandle(handle);
this->nodes[handle] = node;
handle++;
}
}
//////////////////////////////////////////////////
void Skeleton::SetBindShapeTransform(const ignition::math::Matrix4d &_trans)
{
this->bindShapeTransform = _trans;
}
//////////////////////////////////////////////////
ignition::math::Matrix4d Skeleton::BindShapeTransform()
{
return this->bindShapeTransform;
}
//////////////////////////////////////////////////
void Skeleton::PrintTransforms()
{
for (std::map<unsigned int, SkeletonNode*>::iterator iter =
this->nodes.begin(); iter != this->nodes.end(); ++iter)
{
SkeletonNode *node = iter->second;
std::cerr << "---------------\n" << node->GetName() << "\n";
for (unsigned int i = 0; i < node->GetNumRawTrans(); ++i)
{
NodeTransform nt = node->GetRawTransform(i);
std::cerr << "\t" << nt.GetSID();
if (nt.GetType() == NodeTransform::MATRIX)
std::cerr << " MATRIX\n";
else
if (nt.GetType() == NodeTransform::TRANSLATE)
std::cerr << " TRANSLATE\n";
else
if (nt.GetType() == NodeTransform::ROTATE)
std::cerr << " ROTATE\n";
else
std::cerr << " SCALE\n";
std::cerr << nt() << "\n+++++++++++\n";
}
std::cerr << node->ModelTransform() << "\n";
if (node->IsJoint())
std::cerr << node->InverseBindTransform() << "\n";
}
}
//////////////////////////////////////////////////
NodeMap Skeleton::GetNodes()
{
return this->nodes;
}
//////////////////////////////////////////////////
void Skeleton::SetNumVertAttached(unsigned int _vertices)
{
this->rawNW.resize(_vertices);
}
//////////////////////////////////////////////////
void Skeleton::AddVertNodeWeight(unsigned int _vertex, std::string _node,
double _weight)
{
this->rawNW[_vertex].push_back(std::make_pair(_node, _weight));
}
//////////////////////////////////////////////////
unsigned int Skeleton::GetNumVertNodeWeights(unsigned int _vertex)
{
return this->rawNW[_vertex].size();
}
//////////////////////////////////////////////////
std::pair<std::string, double> Skeleton::GetVertNodeWeight(unsigned int _v,
unsigned int _i)
{
return this->rawNW[_v][_i];
}
//////////////////////////////////////////////////
unsigned int Skeleton::GetNumAnimations()
{
return this->anims.size();
}
SkeletonAnimation *Skeleton::GetAnimation(const unsigned int _i)
{
if (_i >= this->anims.size())
return NULL;
return this->anims[_i];
}
//////////////////////////////////////////////////
void Skeleton::AddAnimation(SkeletonAnimation *_anim)
{
this->anims.push_back(_anim);
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
SkeletonNode::SkeletonNode(SkeletonNode* _parent)
{
this->parent = _parent;
if (this->parent)
this->parent->AddChild(this);
}
//////////////////////////////////////////////////
SkeletonNode::SkeletonNode(SkeletonNode* _parent, std::string _name,
std::string _id, SkeletonNodeType _type)
{
this->parent = _parent;
if (this->parent)
this->parent->AddChild(this);
this->name = _name;
this->id = _id;
this->type = _type;
}
//////////////////////////////////////////////////
SkeletonNode::~SkeletonNode()
{
this->children.clear();
}
//////////////////////////////////////////////////
void SkeletonNode::SetName(std::string _name)
{
this->name = _name;
}
//////////////////////////////////////////////////
std::string SkeletonNode::GetName()
{
return this->name;
}
//////////////////////////////////////////////////
void SkeletonNode::SetId(std::string _id)
{
this->id = _id;
}
//////////////////////////////////////////////////
std::string SkeletonNode::GetId()
{
return this->id;
}
//////////////////////////////////////////////////
void SkeletonNode::SetType(SkeletonNodeType _type)
{
this->type = _type;
}
//////////////////////////////////////////////////
bool SkeletonNode::IsJoint()
{
if (this->type == JOINT)
return true;
else
return false;
}
//////////////////////////////////////////////////
void SkeletonNode::SetTransform(const ignition::math::Matrix4d &_trans,
bool _updateChildren)
{
this->transform = _trans;
if (this->parent == NULL)
this->modelTransform = _trans;
else
this->modelTransform = this->parent->ModelTransform() * _trans;
/// propagate the change to the children nodes
if (_updateChildren)
this->UpdateChildrenTransforms();
}
//////////////////////////////////////////////////
void SkeletonNode::SetInitialTransform(const ignition::math::Matrix4d &_trans)
{
this->initialTransform = _trans;
this->SetTransform(_trans);
}
//////////////////////////////////////////////////
void SkeletonNode::Reset(bool resetChildren)
{
this->SetTransform(this->initialTransform);
if (resetChildren)
for (unsigned int i = 0; i < this->GetChildCount(); ++i)
this->GetChild(i)->Reset(true);
}
//////////////////////////////////////////////////
void SkeletonNode::UpdateChildrenTransforms()
{
std::list<SkeletonNode*> toVisit;
for (unsigned int i = 0; i < this->children.size(); ++i)
toVisit.push_back(this->children[i]);
while (!toVisit.empty())
{
SkeletonNode *node = toVisit.front();
toVisit.pop_front();
for (int i = (node->GetChildCount() - 1); i >= 0; i--)
toVisit.push_front(node->GetChild(i));
node->modelTransform = node->GetParent()->modelTransform * node->transform;
}
}
//////////////////////////////////////////////////
ignition::math::Matrix4d SkeletonNode::Transform()
{
return this->transform;
}
//////////////////////////////////////////////////
void SkeletonNode::SetModelTransform(
const ignition::math::Matrix4d &_trans, const bool _updateChildren)
{
this->modelTransform = _trans;
if (this->parent == NULL)
{
this->transform = _trans;
}
else
{
ignition::math::Matrix4d invParentTrans =
this->parent->ModelTransform().Inverse();
this->transform = invParentTrans * this->modelTransform;
}
if (_updateChildren)
this->UpdateChildrenTransforms();
}
//////////////////////////////////////////////////
ignition::math::Matrix4d SkeletonNode::ModelTransform() const
{
return this->modelTransform;
}
//////////////////////////////////////////////////
void SkeletonNode::SetParent(SkeletonNode* _parent)
{
this->parent = _parent;
}
//////////////////////////////////////////////////
SkeletonNode* SkeletonNode::GetParent()
{
return this->parent;
}
//////////////////////////////////////////////////
bool SkeletonNode::IsRootNode()
{
if (!this->parent)
return true;
else
return false;
}
//////////////////////////////////////////////////
void SkeletonNode::AddChild(SkeletonNode* _child)
{
this->children.push_back(_child);
}
//////////////////////////////////////////////////
unsigned int SkeletonNode::GetChildCount()
{
return this->children.size();
}
//////////////////////////////////////////////////
SkeletonNode* SkeletonNode::GetChild(unsigned int _index)
{
return this->children[_index];
}
//////////////////////////////////////////////////
SkeletonNode* SkeletonNode::GetChildByName(std::string _name)
{
for (unsigned int i = 0; i < this->children.size(); ++i)
if (this->children[i]->GetName() == _name)
return this->children[i];
return NULL;
}
//////////////////////////////////////////////////
SkeletonNode* SkeletonNode::GetChildById(std::string _id)
{
for (unsigned int i = 0; i < this->children.size(); ++i)
if (this->children[i]->GetId() == _id)
return this->children[i];
return NULL;
}
//////////////////////////////////////////////////
void SkeletonNode::SetHandle(unsigned int _handle)
{
this->handle = _handle;
}
//////////////////////////////////////////////////
unsigned int SkeletonNode::GetHandle()
{
return this->handle;
}
//////////////////////////////////////////////////
void SkeletonNode::SetInverseBindTransform(
const ignition::math::Matrix4d &_invBM)
{
this->invBindTransform = _invBM;
}
//////////////////////////////////////////////////
ignition::math::Matrix4d SkeletonNode::InverseBindTransform()
{
return this->invBindTransform;
}
//////////////////////////////////////////////////
std::vector<NodeTransform> SkeletonNode::GetRawTransforms()
{
return this->rawTransforms;
}
//////////////////////////////////////////////////
unsigned int SkeletonNode::GetNumRawTrans()
{
return this->rawTransforms.size();
}
//////////////////////////////////////////////////
NodeTransform SkeletonNode::GetRawTransform(unsigned int _i)
{
return this->rawTransforms[_i];
}
//////////////////////////////////////////////////
void SkeletonNode::AddRawTransform(NodeTransform _t)
{
this->rawTransforms.push_back(_t);
}
//////////////////////////////////////////////////
std::vector<NodeTransform> SkeletonNode::GetTransforms()
{
return this->rawTransforms;
}
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
//////////////////////////////////////////////////
NodeTransform::NodeTransform(TransformType _type)
{
this->sid = "_default_";
this->type = _type;
this->transform =
ignition::math::Matrix4d(ignition::math::Matrix4d::Identity);
}
//////////////////////////////////////////////////
NodeTransform::NodeTransform(const ignition::math::Matrix4d &_mat,
const std::string &_sid, TransformType _type)
{
this->sid = _sid;
this->type = _type;
this->transform = _mat;
}
//////////////////////////////////////////////////
NodeTransform::~NodeTransform()
{
}
//////////////////////////////////////////////////
void NodeTransform::Set(const ignition::math::Matrix4d &_mat)
{
this->transform = _mat;
}
//////////////////////////////////////////////////
void NodeTransform::SetType(TransformType _type)
{
this->type = _type;
}
//////////////////////////////////////////////////
void NodeTransform::SetSID(std::string _sid)
{
this->sid = _sid;
}
//////////////////////////////////////////////////
ignition::math::Matrix4d NodeTransform::GetTransform() const
{
return this->transform;
}
//////////////////////////////////////////////////
NodeTransform::TransformType NodeTransform::GetType()
{
return this->type;
}
//////////////////////////////////////////////////
std::string NodeTransform::GetSID()
{
return this->sid;
}
//////////////////////////////////////////////////
void NodeTransform::SetComponent(unsigned int _idx, double _value)
{
this->source[_idx] = _value;
}
//////////////////////////////////////////////////
void NodeTransform::SetSourceValues(const ignition::math::Matrix4d &_mat)
{
this->source.resize(16);
unsigned int idx = 0;
for (unsigned int i = 0; i < 4; ++i)
{
for (unsigned int j = 0; j < 4; ++j)
{
this->source[idx] = _mat(i, j);
idx++;
}
}
}
//////////////////////////////////////////////////
void NodeTransform::SetSourceValues(const ignition::math::Vector3d &_vec)
{
this->source.resize(3);
this->source[0] = _vec.X();
this->source[1] = _vec.Y();
this->source[2] = _vec.Z();
}
//////////////////////////////////////////////////
void NodeTransform::SetSourceValues(
const ignition::math::Vector3d &_axis, const double _angle)
{
this->source.resize(4);
this->source[0] = _axis.X();
this->source[1] = _axis.Y();
this->source[2] = _axis.Z();
this->source[3] = _angle;
}
//////////////////////////////////////////////////
void NodeTransform::RecalculateMatrix()
{
if (this->type == MATRIX)
{
this->transform.Set(this->source[0], this->source[1], this->source[2],
this->source[3], this->source[4], this->source[5],
this->source[6], this->source[7], this->source[8],
this->source[9], this->source[10], this->source[11],
this->source[12], this->source[13], this->source[14],
this->source[15]);
}
else
if (this->type == TRANSLATE)
{
this->transform.Translate(
ignition::math::Vector3d(this->source[0],
this->source[1], this->source[2]));
}
else
if (this->type == ROTATE)
{
ignition::math::Matrix3d mat;
mat.Axis(ignition::math::Vector3d(
this->source[0], this->source[1], this->source[2]),
IGN_DTOR(this->source[3]));
this->transform = mat;
}
else
{
this->transform.Scale(ignition::math::Vector3d(
this->source[0], this->source[1], this->source[2]));
}
}
//////////////////////////////////////////////////
ignition::math::Matrix4d NodeTransform::operator()()
{
return this->transform;
}
//////////////////////////////////////////////////
ignition::math::Matrix4d NodeTransform::operator*(NodeTransform _t)
{
ignition::math::Matrix4d m;
m = this->transform * _t();
return m;
}
//////////////////////////////////////////////////
ignition::math::Matrix4d NodeTransform::operator*(
const ignition::math::Matrix4d &_m)
{
ignition::math::Matrix4d m;
m = this->transform * _m;
return m;
}
//////////////////////////////////////////////////
void NodeTransform::PrintSource()
{
std::cerr << this->sid;
for (unsigned int i = 0; i < this->source.size(); ++i)
std::cerr << " " << this->source[i];
std::cerr << "\n";
}