/** * @file * * @author Max Lammers * @author Mamadou Babaei * * @section LICENSE * * Copyright (c) 2020 - 2025 SenseGlove * * @section DESCRIPTION * * A data class containing the minimum required data for a hand's forward * kinematics. * Used in both kinematics and calibration. */ #pragma once #include #include #include #include "Fingers.hpp" #include "Platform.hpp" namespace SGCore { namespace Kinematics { /// Represents data of a user's hand required for forward kinematics. class SGCORE_API BasicHandModel; class Quat; class Vect3D; }// namespace Kinematics }// namespace SGCore /// Represents data of a user's hand required for forward kinematics. class SGCORE_API SGCore::Kinematics::BasicHandModel { public: /// Retrieve a default left or right hand model. SG_NODISCARD static BasicHandModel Default(bool bRightHanded); /// Convert a serialized HandModel back into its class representation. SG_NODISCARD static BasicHandModel Deserialize(const std::string& serializedString); public: /// Default finger lengths (based on right hand). /// Any missing fingers are replaced with their respective value. SG_NODISCARD static const std::vector>& GetBaseFingerLengths(); /// Default joint positions (based on right hand). /// Any missing positions are replaced with their respective value. SG_NODISCARD static const std::vector& GetBaseJointPositions(); /// Default joint angles (based on right hand). /// Any missing angles are replaced with their respective value. SG_NODISCARD static const std::vector& GetBaseJointAngles(); private: struct Impl; std::unique_ptr Pimpl; public: /// The basic class constructor. BasicHandModel(); /// Create a new BasicHandModel with no starting rotations. BasicHandModel(bool bRightHanded, const std::vector>& lengths, const std::vector& startPositions); /// Create a new BasicHandModel. BasicHandModel(bool bRightHanded, const std::vector>& lengths, const std::vector& startPositions, const std::vector& startRotations); /** * The copy constructor. */ BasicHandModel(const BasicHandModel& rhs); /** * The move constructor. */ BasicHandModel(BasicHandModel&& rhs) noexcept; /// The basic class destructor. virtual ~BasicHandModel(); public: /** * The copy assignment operator. */ BasicHandModel& operator=(const BasicHandModel& rhs); /** * The move assignment operator. */ BasicHandModel& operator=(BasicHandModel&& rhs) noexcept; public: /// Whether or not this BasicHandModel was created for a left- or right hand. Used for validation. /// SG_NODISCARD bool IsRight() const; public: /// The length of individual finger phalangers in mm, sorted per finger. Generally 5x3. SG_NODISCARD const std::vector>& GetFingerLengths() const; /// Retrieve the finger lengths of a specific finger in mm. SG_NODISCARD const std::vector& GetFingerLengths(EFinger finger) const; /// Set the finger lengths of a specific finger in mm. void SetFingerLengths(EFinger finger, const std::vector& lengths); /// Set the finger lengths of a specific finger in mm. void SetFingerLengths(uint8_t finger, const std::vector& lengths); /// Get the finger ratios of all fingers. SG_NODISCARD const std::vector>& GetFingerRatios() const; protected: /// Calculated Finger ratios [0..1]. void SetFingerRatios(const std::vector>& ratios); public: /// Get the finger ratios of a specific finger. SG_NODISCARD const std::vector& GetFingerRatios(EFinger finger) const; /// Starting joint positions relative to the device Origin. SG_NODISCARD const std::vector& GetStartJointPositions() const; void SetStartJointPosition(EFinger finger, const Vect3D& position); void SetStartJointPosition(uint8_t finger, const Vect3D& position); /// Starting joint rotations relative to the device Origin. SG_NODISCARD const std::vector& GetStartJointRotations() const; /// Retrieve the start position of a specific finger. SG_NODISCARD const Vect3D& GetJointPosition(EFinger finger) const; /// Set the start position of a specific finger. void SetJointPosition(const Vect3D& newPosition, EFinger finger); /// Retrieve the start rotation of a specific finger. SG_NODISCARD const Quat& GetJointRotation(EFinger finger) const; /// Set the start rotation of a specific finger. void SetJointRotation(const Quat& newRotation, EFinger finger); /// Get the total lengths of fingers, in mm. SG_NODISCARD const std::vector& GetTotalLengths() const; /// Get the total length of a specific finger, in mm. SG_NODISCARD float GetTotalLength(EFinger finger) const; protected: /// Calculated Total finger lengths. void SetTotalLengths(const std::vector& lengths); public: /// Retrieve the lengths of a specific finger, as BasicHandModel representation (L, 0, 0). /// Used for forwards kinematics. SG_NODISCARD std::vector Get3DLengths(EFinger finger) const; public: /// Check if this BasicHandModel has the same values as another BasicHandModel. /// /// SG_NODISCARD bool Equals(const BasicHandModel& basicHandModel) const; protected: /// Test if the input has enough values. if not, add the appropriate values to compensate. virtual void Validate(); /// Calculate hand variables (finger lengths, ratios) based on current values. void CalculateVariables(); public: /// Convert this handModel into a string notation, readable for humans. Does not include starting /// positions / rotations. /// SG_NODISCARD std::string ToString() const; /// Convert this handModel into a string notation, readable for humans. Optionally includes starting /// positions / rotations. /// /// SG_NODISCARD std::string ToString(bool bLengthsOnly) const; /// Serialize this HandModel into a string representation. /// SG_NODISCARD std::string Serialize() const; };