/* * 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. * */ #ifndef _GAZEBO_SKELETON_HH_ #define _GAZEBO_SKELETON_HH_ #include #include #include #include #include #include "gazebo/math/Matrix4.hh" #include "gazebo/common/CommonTypes.hh" #include "gazebo/util/system.hh" namespace gazebo { namespace common { class SkeletonNode; class NodeTransform; class SkeletonAnimation; typedef std::map NodeMap; typedef std::map::iterator NodeMapIter; typedef std::map > RawNodeAnim; typedef std::map RawSkeletonAnim; typedef std::vector > > RawNodeWeights; /// \addtogroup gazebo_common Common Animation /// \{ /// \class Skeleton Skeleton.hh common/common.hh /// \brief A skeleton class GZ_COMMON_VISIBLE Skeleton { /// \brief Constructor public: Skeleton(); /// \brief Constructor /// \param[in] _root node public: Skeleton(SkeletonNode *_root); /// \brief Destructor public: virtual ~Skeleton(); /// \brief Change the root node /// \param[in] _node the new node public: void SetRootNode(SkeletonNode* _node); /// \brief Return the root /// \return the root public: SkeletonNode* GetRootNode(); /// \brief Find a node /// \param[in] _name the name of the node to look for /// \return the node, or NULL if not found public: SkeletonNode* GetNodeByName(std::string _name); /// \brief Find node by index /// \param[in] _id the index /// \return the node, or NULL if not found public: SkeletonNode* GetNodeById(std::string _id); /// \brief Find or create node with handle /// \param[in] _handle /// \return the node. A new node is created if it didn't exist public: SkeletonNode* GetNodeByHandle(unsigned int _handle); /// \brief Returns the node count /// \return the count public: unsigned int GetNumNodes(); /// \brief Returns the number of joints /// \return the count public: unsigned int GetNumJoints(); /// \brief Scale all nodes, transforms and animation data /// \param[in] the scaling factor public: void Scale(double _scale); /// \brief Set the bind pose skeletal transform /// \param[in] _trans the transform public: void SetBindShapeTransform( const ignition::math::Matrix4d &_trans); /// \brief Return bind pose skeletal transform /// \return a matrix public: ignition::math::Matrix4d BindShapeTransform(); /// \brief Outputs the transforms to std::err stream public: void PrintTransforms(); /// \brief Get a copy or the node dictionary public: NodeMap GetNodes(); /// \brief Resizes the raw node weight array /// \param[in] _vertices the new size public: void SetNumVertAttached(unsigned int _vertices); /// \brief Add a new weight to a node (bone) /// \param[in] _vertex index of the vertex /// \param[in] _node name of the bone /// \param[in] _weight the new weight (range 0 to 1) public: void AddVertNodeWeight(unsigned int _vertex, std::string _node, double _weight); /// \brief Returns the number of bone weights for a vertex /// \param[in] _vertex the index of the vertex /// \return the count public: unsigned int GetNumVertNodeWeights(unsigned int _vertex); /// \brief Weight of a bone for a vertex /// \param[in] _v the index of the vertex /// \param[in] _i the index of the weight for that vertex /// \return a pair containing the name of the node and the weight public: std::pair GetVertNodeWeight(unsigned int _v, unsigned int _i); /// \brief Returns the number of animations /// \return the count public: unsigned int GetNumAnimations(); /// \brief Find animation /// \param[in] _i the animation index /// \return the animation, or NULL if _i is out of bounds public: SkeletonAnimation* GetAnimation(const unsigned int _i); /// \brief Add an animation. The skeleton does not take ownership of the /// animation /// \param[in] _anim the animation to add public: void AddAnimation(SkeletonAnimation *_anim); /// \brief Initializes the hande numbers for each node in the map /// using breadth first traversal protected: void BuildNodeMap(); /// \brief the root node protected: SkeletonNode *root; /// \brief The dictionary of nodes, indexed by name protected: NodeMap nodes; /// \brief the bind pose skeletal transform protected: ignition::math::Matrix4d bindShapeTransform; /// \brief the node weight table protected: RawNodeWeights rawNW; /// \brief the array of animations protected: std::vector anims; }; /// \class SkeletonNode Skeleton.hh common/common.hh /// \brief A skeleton node class GZ_COMMON_VISIBLE SkeletonNode { /// \brief enumeration of node types public: enum SkeletonNodeType {NODE, JOINT}; /// \brief Constructor /// \param[in] _parent The parent node public: SkeletonNode(SkeletonNode* _parent); /// \brief Constructor /// \param[in] _parent the parent node /// \param[in] _name name of node /// \param[in] _id Id of node /// \param[in] _type The type of this node public: SkeletonNode(SkeletonNode* _parent, std::string _name, std::string _id, SkeletonNodeType _type = JOINT); /// \brief Destructor public: virtual ~SkeletonNode(); /// \brief Change the name /// \param[in] _name the new name public: void SetName(std::string _name); /// \brief Returns the name /// \return the name public: std::string GetName(); /// \brief Change the id string /// \param[in] _id the new id string public: void SetId(std::string _id); /// \brief Returns the index /// \return the id string public: std::string GetId(); /// \brief Change the skeleton node type /// \param[in] _type the new type public: void SetType(SkeletonNodeType _type); /// \brief Is a joint query /// \return true if the skeleton type is a joint, false otherwise public: bool IsJoint(); /// \brief Set a transformation /// \param[in] _trans the transformation /// \param[in] _updateChildren when true the UpdateChildrenTransforms /// operation is performed public: void SetTransform(const ignition::math::Matrix4d &_trans, bool _updateChildren = true); /// \brief Set the model transformation /// \param[in] _trans the transformation /// \param[in] _updateChildren when true the UpdateChildrenTransforms /// operation is performed public: void SetModelTransform(const ignition::math::Matrix4d &_trans, bool _updateChildren = true); /// \brief Apply model transformations in order for each node in the tree public: void UpdateChildrenTransforms(); /// \brief Sets the initial transformation /// \param[in] _tras the transfromation matrix public: void SetInitialTransform(const ignition::math::Matrix4d &_tras); /// \brief Reset the transformation to the initial transformation /// \param[in] _resetChildren when true, performs the operation for every /// node in the tree public: void Reset(bool _resetChildren); /// \brief Get transform relative to parent /// \return Transform relative to parent public: ignition::math::Matrix4d Transform(); /// \brief Set the parent node /// \param[in] _parent the new parent public: void SetParent(SkeletonNode* _parent); /// \brief Returns the parent node /// \return the parent public: SkeletonNode* GetParent(); /// \brief Queries wether a node has no parent parent /// \return true if the node has no parent, fasle otherwise public: bool IsRootNode(); /// \brief Add a new child /// \param[in] _child a child public: void AddChild(SkeletonNode* _child); /// \brief Returns the children count /// \return the count public: unsigned int GetChildCount(); /// \brief Find a child by index /// \param[in] _index the index /// \return the child skeleton. NO BOUNDS CHECKING public: SkeletonNode* GetChild(unsigned int _index); /// \brief Get child by name /// \param[in] _name the name of the child skeleton /// \return the skeleton, or NULL if not found public: SkeletonNode* GetChildByName(std::string _name); /// \brief Get child by string id /// \param[in] _id the string id /// \return the child skeleton or NULL if not found public: SkeletonNode* GetChildById(std::string _id); /// \brief Assign a handle number /// \param[in] _h the handle public: void SetHandle(unsigned int _h); /// \brief Get the handle index /// \return the handle index public: unsigned int GetHandle(); /// \brief Assign the inverse of the bind pose skeletal transform /// \param[in] _invBM the transform public: void SetInverseBindTransform( const ignition::math::Matrix4d &_invBM); /// \brief Retrieve the inverse of the bind pose skeletal transform /// \return the transform public: ignition::math::Matrix4d InverseBindTransform(); /// \brief Retrieve the model transform /// \return the transform public: ignition::math::Matrix4d ModelTransform() const; /// \brief Retrieve the raw transformations /// \return an array of transformations public: std::vector GetRawTransforms(); /// \brief Return the raw transformations count /// \return the count public: unsigned int GetNumRawTrans(); /// \brief Find a raw transformation /// \param[in] _i the index of the transformation /// \return the node transform. NO BOUNDS CHECKING PERFORMED public: NodeTransform GetRawTransform(unsigned int _i); /// \brief Add a raw transform /// \param[in] _t the transform public: void AddRawTransform(NodeTransform _t); /// \brief Returns a copy of the array of transformations. /// \return the array of transform (These are the same as the raw trans) public: std::vector GetTransforms(); /// \brief the name of the skeletal node protected: std::string name; /// \brief a string identifier protected: std::string id; /// \brief the type fo node protected: SkeletonNodeType type; /// \brief the transform protected: ignition::math::Matrix4d transform; /// \brief the initial transformation protected: ignition::math::Matrix4d initialTransform; /// \brief the model transformation protected: ignition::math::Matrix4d modelTransform; /// \brief the inverse of the bind pose skeletal transform protected: ignition::math::Matrix4d invBindTransform; /// \brief the parent node protected: SkeletonNode *parent; /// \brief the children nodes protected: std::vector children; /// \brief handle index number protected: unsigned int handle; /// \brief the raw transformation protected: std::vector rawTransforms; }; /// \clas NodeTransform Skeleton.hh common/common.hh /// \brief A transformation node class GZ_COMMON_VISIBLE NodeTransform { /// \brief Enumeration of the transform types public: enum TransformType {TRANSLATE, ROTATE, SCALE, MATRIX}; /// \brief Constructor /// \param[in] _type the type of transform public: NodeTransform(TransformType _type = MATRIX); /// \brief Constructor /// \param[in] _mat the matrix /// \param[in] _sid identifier /// \param[in] _type the type of transform public: NodeTransform(const ignition::math::Matrix4d &_mat, const std::string &_sid = "_default_", TransformType _type = MATRIX); /// \brief Destructor. It does nothing. public: ~NodeTransform(); /// \brief Assign a transformation /// \param[in] _mat the transform public: void Set(const ignition::math::Matrix4d &_mat); /// \brief Set transform type /// \param[in] _type the type public: void SetType(TransformType _type); /// \brief Set the SID /// \param[in] _sid the sid public: void SetSID(std::string _sid); /// \brief Returns the transformation matrix /// \return The transform matrix public: ignition::math::Matrix4d GetTransform() const; /// \brief Returns the transformation type /// \return the type public: TransformType GetType(); /// \brief Returns thr SID /// \return the SID public: std::string GetSID(); /// \brief Set a transformation matrix component value /// \param[in] _idx the component index /// \param[in] _value the value public: void SetComponent(unsigned int _idx, double _value); /// \brief Set source data values /// param[in] _mat the values public: void SetSourceValues(const ignition::math::Matrix4d &_mat); /// \brief Set source data values /// \param[in] _vec Vector to set source data values from. public: void SetSourceValues(const ignition::math::Vector3d &_vec); /// \brief Sets source matrix values from roation /// \param[in] _axis of rotation /// \param[in] _angle of rotation public: void SetSourceValues(const ignition::math::Vector3d &_axis, const double _angle); /// \brief Sets the transform matrix from the source according to the type public: void RecalculateMatrix(); /// \brief Prints the transform matrix to std::err stream public: void PrintSource(); /// \brief Matrix cast operator /// \return the transform public: ignition::math::Matrix4d operator()(); /// \brief Node transform multiplication operator /// \param[in] _t a transform /// \return transform matrix multiplied by _t's transform public: ignition::math::Matrix4d operator*(NodeTransform _t); /// \brief Matrix multiplication operator /// \param[in] _m a matrix /// \return transform matrix multiplied by _m public: ignition::math::Matrix4d operator*( const ignition::math::Matrix4d &_m); /// \brief the sid protected: std::string sid; /// \brief transform type protected: TransformType type; /// \brief transform protected: ignition::math::Matrix4d transform; /// \brief source data values (can be a matrix, a position or rotation) protected: std::vector source; }; /// \} } } #endif