From 614e7ccb64e34366872a05e6921badf1d32f6c7e Mon Sep 17 00:00:00 2001 From: fabians Date: Fri, 29 Oct 2021 14:29:46 +0200 Subject: [PATCH] init commit transmission --- .../include/jiminy/core/robot/AbstractMotor.h | 141 +++--- .../jiminy/core/robot/AbstractTransmission.h | 255 +++++++++++ core/include/jiminy/core/robot/BasicMotors.h | 7 +- .../jiminy/core/robot/BasicTransmissions.h | 67 +++ core/include/jiminy/core/robot/Robot.h | 3 + core/src/robot/AbstractMotor.cc | 124 ++---- core/src/robot/AbstractTransmission.cc | 405 ++++++++++++++++++ core/src/robot/BasicMotors.cc | 32 +- core/src/robot/BasicTransmissions.cc | 102 +++++ core/src/robot/Robot.cc | 11 + 10 files changed, 940 insertions(+), 207 deletions(-) create mode 100644 core/include/jiminy/core/robot/AbstractTransmission.h create mode 100644 core/include/jiminy/core/robot/BasicTransmissions.h create mode 100644 core/src/robot/AbstractTransmission.cc create mode 100644 core/src/robot/BasicTransmissions.cc diff --git a/core/include/jiminy/core/robot/AbstractMotor.h b/core/include/jiminy/core/robot/AbstractMotor.h index 63fbfd789c..c978a86c40 100644 --- a/core/include/jiminy/core/robot/AbstractMotor.h +++ b/core/include/jiminy/core/robot/AbstractMotor.h @@ -33,7 +33,10 @@ namespace jiminy struct MotorSharedDataHolder_t { MotorSharedDataHolder_t(void) : - data_(), + position_(), + velocity_(), + acceleration_(), + effort_(), motors_(), num_(0) { @@ -42,7 +45,11 @@ namespace jiminy ~MotorSharedDataHolder_t(void) = default; - vectorN_t data_; ///< Buffer with current actual motor effort + vectorN_t position_; + vectorN_t velocity_; + vectorN_t acceleration_; + vectorN_t effort_; + std::vector motors_; ///< Vector of pointers to the motors. int32_t num_; ///< Number of motors }; @@ -59,7 +66,6 @@ namespace jiminy virtual configHolder_t getDefaultMotorOptions(void) { configHolder_t config; - config["mechanicalReduction"] = 1.0; config["enableCommandLimit"] = true; config["commandLimitFromUrdf"] = true; config["commandLimit"] = 0.0; @@ -71,7 +77,6 @@ namespace jiminy struct abstractMotorOptions_t { - float64_t const mechanicalReduction; ///< Mechanical reduction ratio of the transmission (joint / motor, usually >= 1.0 bool_t const enableCommandLimit; bool_t const commandLimitFromUrdf; float64_t const commandLimit; @@ -79,7 +84,6 @@ namespace jiminy float64_t const armature; abstractMotorOptions_t(configHolder_t const & options) : - mechanicalReduction(boost::get(options.at("mechanicalReduction"))), enableCommandLimit(boost::get(options.at("enableCommandLimit"))), commandLimitFromUrdf(boost::get(options.at("commandLimitFromUrdf"))), commandLimit(boost::get(options.at("commandLimit"))), @@ -135,84 +139,65 @@ namespace jiminy configHolder_t getOptions(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get the actual effort of the motor at the current time. + /// \brief Get the actual position of the motor at the current time. /////////////////////////////////////////////////////////////////////////////////////////////// - float64_t const & get(void) const; + float64_t const & getPosition(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get the actual effort of all the motors at the current time. + /// \brief Get the actual velocity of the motor at the current time. /////////////////////////////////////////////////////////////////////////////////////////////// - vectorN_t const & getAll(void) const; + float64_t const & getVelocity(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Set the configuration options of the motor. - /// - /// \param[in] motorOptions Dictionary with the parameters of the motor - /////////////////////////////////////////////////////////////////////////////////////////////// - virtual hresult_t setOptions(configHolder_t const & motorOptions); - - /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Set the same configuration options for every motors. - /// - /// \param[in] motorOptions Dictionary with the parameters used for any motor + /// \brief Get the actual acc of the motor at the current time. /////////////////////////////////////////////////////////////////////////////////////////////// - hresult_t setOptionsAll(configHolder_t const & motorOptions); + float64_t const & getAcceleration(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get isInitialized_. - /// - /// \details It is a flag used to determine if the motor has been initialized. + /// \brief Get the actual effort of the motor at the current time. /////////////////////////////////////////////////////////////////////////////////////////////// - bool_t const & getIsInitialized(void) const; + float64_t const & getEffort(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get name_. - /// - /// \details It is the name of the motor. + /// \brief Get the actual position of all the motor at the current time. /////////////////////////////////////////////////////////////////////////////////////////////// - std::string const & getName(void) const; + vectorN_t const & getPositionAll(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get motorIdx_. - /// - /// \details It is the index of the motor. + /// \brief Get the actual velocity of all the motor at the current time. /////////////////////////////////////////////////////////////////////////////////////////////// - int32_t const & getIdx(void) const; + vectorN_t const & getVelocityAll(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get jointName_. - /// - /// \details It is the name of the joint associated with the motor. + /// \brief Get the actual acc of all the motor at the current time. /////////////////////////////////////////////////////////////////////////////////////////////// - std::string const & getJointName(void) const; + vectorN_t const & getAccelerationAll(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get jointModelIdx_. - /// - /// \details It is the index of the joint associated with the motor in the kinematic tree. + /// \brief Get the actual effort of all the motor at the current time. /////////////////////////////////////////////////////////////////////////////////////////////// - jointIndex_t const & getJointModelIdx(void) const; + vectorN_t const & getEffortAll(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get jointType_. + /// \brief Set the configuration options of the motor. /// - /// \details It is the type of joint associated with the motor. + /// \param[in] motorOptions Dictionary with the parameters of the motor /////////////////////////////////////////////////////////////////////////////////////////////// - joint_t const & getJointType(void) const; + virtual hresult_t setOptions(configHolder_t const & motorOptions); /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get jointPositionIdx_. + /// \brief Set the same configuration options for every motors. /// - /// \details It is the index of the joint associated with the motor in the configuration vector. + /// \param[in] motorOptions Dictionary with the parameters used for any motor /////////////////////////////////////////////////////////////////////////////////////////////// - int32_t const & getJointPositionIdx(void) const; + hresult_t setOptionsAll(configHolder_t const & motorOptions); /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Get jointVelocityIdx_. + /// \brief Get name_. /// - /// \details It is the index of the joint associated with the motor in the velocity vector. + /// \details It is the name of the motor. /////////////////////////////////////////////////////////////////////////////////////////////// - int32_t const & getJointVelocityIdx(void) const; + std::string const & getName(void) const; /////////////////////////////////////////////////////////////////////////////////////////////// /// \brief Get commandLimit_. @@ -234,18 +219,10 @@ namespace jiminy /// \details It assumes that the internal state of the robot is consistent with the /// input arguments. /// - /// \param[in] t Current time. - /// \param[in] q Current configuration of the motor. - /// \param[in] v Current velocity of the motor. - /// \param[in] a Current acceleration of the motor. /// \param[in] command Current command effort of the motor. /// /////////////////////////////////////////////////////////////////////////////////////////////// - virtual hresult_t computeEffort(float64_t const & t, - Eigen::VectorBlock const & q, - float64_t const & v, - float64_t const & a, - float64_t command) = 0; /* copy on purpose */ + virtual hresult_t computeEffort(float64_t command) = 0; /* copy on purpose */ /////////////////////////////////////////////////////////////////////////////////////////////// /// \brief Request every motors to update their actual effort based of the input data. @@ -256,39 +233,49 @@ namespace jiminy /// \remark This method is not intended to be called manually. The Robot to which the /// motor is added is taking care of it while updating the state of the motors. /// - /// \param[in] t Current time. - /// \param[in] q Current configuration vector of the robot. - /// \param[in] v Current velocity vector of the robot. - /// \param[in] a Current acceleration vector of the robot. /// \param[in] command Current command effort vector of the robot. /// /// \return Return code to determine whether the execution of the method was successful. /////////////////////////////////////////////////////////////////////////////////////////////// - hresult_t computeEffortAll(float64_t const & t, - vectorN_t const & q, - vectorN_t const & v, - vectorN_t const & a, - vectorN_t const & command); + hresult_t computeEffortAll(vectorN_t const & command); protected: + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get a reference to the last data buffer corresponding to the actual position + /// of the motor. + /////////////////////////////////////////////////////////////////////////////////////////////// + float64_t & q(void); + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get a reference to the last data buffer corresponding to the actual velocity + /// of the motor. + /////////////////////////////////////////////////////////////////////////////////////////////// + float64_t & v(void); + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get a reference to the last data buffer corresponding to the actual acc + /// of the motor. + /////////////////////////////////////////////////////////////////////////////////////////////// + float64_t & a(void); + /////////////////////////////////////////////////////////////////////////////////////////////// /// \brief Get a reference to the last data buffer corresponding to the actual effort /// of the motor. /////////////////////////////////////////////////////////////////////////////////////////////// - float64_t & data(void); + float64_t & u(void); private: /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Attach the sensor to a robot + /// \brief Attach the motor to a robot /// - /// \details This method must be called before initializing the sensor. + /// \details This method must be called before initializing the motor. /////////////////////////////////////////////////////////////////////////////////////////////// hresult_t attach(std::weak_ptr robot, - std::function notifyRobot, + std::function notifyRobot, MotorSharedDataHolder_t * sharedHolder); /////////////////////////////////////////////////////////////////////////////////////////////// - /// \brief Detach the sensor from the robot + /// \brief Detach the motor from the robot /////////////////////////////////////////////////////////////////////////////////////////////// hresult_t detach(void); @@ -297,19 +284,13 @@ namespace jiminy protected: configHolder_t motorOptionsHolder_; ///< Dictionary with the parameters of the motor - bool_t isInitialized_; ///< Flag to determine whether the controller has been initialized or not bool_t isAttached_; ///< Flag to determine whether the motor is attached to a robot std::weak_ptr robot_; ///< Robot for which the command and internal dynamics - std::function notifyRobot_; ///< Notify the robot that the configuration of the sensors have changed + std::function notifyRobot_; ///< Notify the robot that the configuration of the motors have changed std::string name_; ///< Name of the motor int32_t motorIdx_; ///< Index of the motor in the measurement buffer - std::string jointName_; - jointIndex_t jointModelIdx_; - joint_t jointType_; - int32_t jointPositionIdx_; - int32_t jointVelocityIdx_; float64_t commandLimit_; - float64_t armature_; + float64_t armature_; private: MotorSharedDataHolder_t * sharedHolder_; ///< Shared data between every motors associated with the robot diff --git a/core/include/jiminy/core/robot/AbstractTransmission.h b/core/include/jiminy/core/robot/AbstractTransmission.h new file mode 100644 index 0000000000..5b1b21a2aa --- /dev/null +++ b/core/include/jiminy/core/robot/AbstractTransmission.h @@ -0,0 +1,255 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +/// +/// \brief Generic interface for any transmission. +/// +/// \details Any transmission must inherit from this base class and implement its virtual methods. +/// +/// \remark Each transmission added to a Jiminy Robot is downcasted as an instance of +/// AbstractTransmissionBase and polymorphism is used to call the actual implementations. +/// +/////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef JIMINY_ABSTRACT_TRANSMISSION_H +#define JIMINY_ABSTRACT_TRANSMISSION_H + +#include + +#include "jiminy/core/Macros.h" +#include "jiminy/core/Types.h" + + +namespace jiminy +{ + class Robot; + + class AbstractTransmissionBase : public std::enable_shared_from_this + { + /* AKA AbstractSensorBase */ + friend Robot; + + public: + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Forbid the copy of the class + /////////////////////////////////////////////////////////////////////////////////////////////// + AbstractTransmissionBase(AbstractTransmissionBase const & abstractTransmission) = delete; + AbstractTransmissionBase & operator = (AbstractTransmissionBase const & other) = delete; + + auto shared_from_this() { return shared_from(this); } + auto shared_from_this() const { return shared_from(this); } + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Constructor + /// + /// \param[in] robot Robot + /// \param[in] name Name of the transmission + /////////////////////////////////////////////////////////////////////////////////////////////// + AbstractTransmissionBase(std::string const & name); + virtual ~AbstractTransmissionBase(void); + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Refresh the proxies. + /// + /// \remark This method is not intended to be called manually. The Robot to which the + /// transmission is added is taking care of it when its own `refresh` method is called. + /////////////////////////////////////////////////////////////////////////////////////////////// + virtual hresult_t refreshProxies(void); + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Reset the internal state of the transmissions. + /// + /// \details This method resets the internal state of the transmission. + /// + /// \remark This method is not intended to be called manually. The Robot to which the + /// transmission is added is taking care of it when its own `reset` method is called. + /////////////////////////////////////////////////////////////////////////////////////////////// + virtual hresult_t resetAll(void); + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get the configuration options of the transmission. + /// + /// \return Dictionary with the parameters of the transmission + /////////////////////////////////////////////////////////////////////////////////////////////// + configHolder_t getOptions(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get the actual state of the transmission at the current time. + /////////////////////////////////////////////////////////////////////////////////////////////// + float64_t const & get(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get the actual state of all the transmissions at the current time. + /////////////////////////////////////////////////////////////////////////////////////////////// + vectorN_t const & getAll(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Set the configuration options of the transmission. + /// + /// \param[in] transmissionOptions Dictionary with the parameters of the transmission + /////////////////////////////////////////////////////////////////////////////////////////////// + virtual hresult_t setOptions(configHolder_t const & transmissionOptions); + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Set the same configuration options for every transmissions. + /// + /// \param[in] transmissionOptions Dictionary with the parameters used for any transmission + /////////////////////////////////////////////////////////////////////////////////////////////// + hresult_t setOptionsAll(configHolder_t const & transmissionOptions); + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get isInitialized_. + /// + /// \details It is a flag used to determine if the transmission has been initialized. + /////////////////////////////////////////////////////////////////////////////////////////////// + bool_t const & getIsInitialized(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get name_. + /// + /// \details It is the name of the transmission. + /////////////////////////////////////////////////////////////////////////////////////////////// + std::string const & getName(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get transmissionIdx_. + /// + /// \details It is the index of the transmission. + /////////////////////////////////////////////////////////////////////////////////////////////// + int32_t const & getIdx(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get jointName_. + /// + /// \details It is the name of the joints associated with the transmission. + /////////////////////////////////////////////////////////////////////////////////////////////// + std::vector const & getJointName(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get jointModelIdx_. + /// + /// \details It is the index of the joints associated with the transmission in the kinematic tree. + /////////////////////////////////////////////////////////////////////////////////////////////// + std::vectorconst & getJointModelIdx(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get jointType_. + /// + /// \details It is the type of joints associated with the transmission. + /////////////////////////////////////////////////////////////////////////////////////////////// + std::vector const & getJointType(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get jointPositionIdx_. + /// + /// \details It is the index of the joints associated with the transmission in the configuration vector. + /////////////////////////////////////////////////////////////////////////////////////////////// + std::vector const & getJointPositionIdx(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get jointVelocityIdx_. + /// + /// \details It is the index of the joints associated with the transmission in the velocity vector. + /////////////////////////////////////////////////////////////////////////////////////////////// + std::vector const & getJointVelocityIdx(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get motorName_. + /// + /// \details It is the name of the motors associated with the transmission. + /////////////////////////////////////////////////////////////////////////////////////////////// + std::vector const & getMotorName(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Get ActuatedJoints. + /// + /// \details It is a list of joints that are attached to a transmission + /////////////////////////////////////////////////////////////////////////////////////////////// + std::vector const & robot.getActuatedJoints(void) const; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Compute forward transmission. + /// + /// \details Compute forward transmission from motor to joint. + /////////////////////////////////////////////////////////////////////////////////////////////// + hresult_t computeForward(float64_t const & t, + vectorN_t & q, + vectorN_t & v, + vectorN_t & a, + vectorN_t & uJoint) final; + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Compute backward transmission. + /// + /// \details Compute backward transmission from joint to motor. + /////////////////////////////////////////////////////////////////////////////////////////////// + hresult_t computeBackward(float64_t const & t, + vectorN_t const & q, + vectorN_t const & v, + vectorN_t const & a, + vectorN_t const & uJoint) final; + + protected: + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Request the transmission to update its actual state based of the input data. + /// + /// \details It assumes that the internal state of the robot is consistent with the + /// input arguments. + /// + /// \param[in] q Current configuration of the motors. + /// \param[in] v Current velocity of the motors. + /// + /////////////////////////////////////////////////////////////////////////////////////////////// + virtual void computeTransform(Eigen::VectorBlock const & q, + Eigen::VectorBlock const & v) = 0; /* copy on purpose */ + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Request the transmission to update its actual state based of the input data. + /// + /// \details It assumes that the internal state of the robot is consistent with the + /// input arguments. + /// + /// \param[in] q Current configuration of the motors. + /// \param[in] v Current velocity of the motors. + /// + /////////////////////////////////////////////////////////////////////////////////////////////// + virtual void computeInverseTransform(Eigen::VectorBlock const & q, + Eigen::VectorBlock const & v) = 0; /* copy on purpose */ + + private: + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Attach the transmission to a robot + /// + /// \details This method must be called before initializing the transmission. + /////////////////////////////////////////////////////////////////////////////////////////////// + hresult_t attach(std::weak_ptr robot, + std::function notifyRobot); + + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Detach the transmission from the robot + /////////////////////////////////////////////////////////////////////////////////////////////// + hresult_t detach(void); + + public: + std::unique_ptr baseTransmissionOptions_; ///< Structure with the parameters of the transmission + + protected: + configHolder_t transmissionOptionsHolder_; ///< Dictionary with the parameters of the transmission + bool_t isInitialized_; ///< Flag to determine whether the transmission has been initialized or not + bool_t isAttached_; ///< Flag to determine whether the transmission is attached to a robot + std::weak_ptr robot_; ///< Robot for which the command and internal dynamics + std::function notifyRobot_; ///< Notify the robot that the configuration of the transmissions have changed + std::string name_; ///< Name of the transmission + int32_t transmissionIdx_; ///< Index of the transmission in the transmission buffer + std::vector jointNames_; + std::vector jointModelIndices_; + std::vector jointTypes_; + std::vector jointPositionIndices_; + std::vector jointVelocityIndices_; + std::vector motorNames_; + std::vector > motors_; + matrixN_t forwardTransform_; + matrixN_t backwardTransform_; + + }; +} + +#endif //end of JIMINY_ABSTRACT_TRANSMISSION_H diff --git a/core/include/jiminy/core/robot/BasicMotors.h b/core/include/jiminy/core/robot/BasicMotors.h index 13fca9c021..10e94d039d 100644 --- a/core/include/jiminy/core/robot/BasicMotors.h +++ b/core/include/jiminy/core/robot/BasicMotors.h @@ -56,15 +56,10 @@ namespace jiminy auto shared_from_this() { return shared_from(this); } auto shared_from_this() const { return shared_from(this); } - hresult_t initialize(std::string const & jointName); - virtual hresult_t setOptions(configHolder_t const & motorOptions) final override; private: - virtual hresult_t computeEffort(float64_t const & t, - Eigen::VectorBlock const & q, - float64_t const & v, - float64_t const & a, + virtual hresult_t computeEffort(float64_t const & v, float64_t command) final override; private: diff --git a/core/include/jiminy/core/robot/BasicTransmissions.h b/core/include/jiminy/core/robot/BasicTransmissions.h new file mode 100644 index 0000000000..0c5f2bb8c4 --- /dev/null +++ b/core/include/jiminy/core/robot/BasicTransmissions.h @@ -0,0 +1,67 @@ +#ifndef JIMINY_BASIC_TRANSMISSIONS_H +#define JIMINY_BASIC_TRANSMISSIONS_H + +#include "jiminy/core/robot/AbstractTransmission.h" + + +namespace jiminy +{ + class SimpleTransmission : public AbstractTransmissionBase + { + public: + /////////////////////////////////////////////////////////////////////////////////////////////// + /// \brief Dictionary gathering the configuration options shared between transmissions + /////////////////////////////////////////////////////////////////////////////////////////////// + virtual configHolder_t getDefaultTransmissionOptions(void) override + { + // Add extra options or update default values + configHolder_t config = AbstractTransmissionBase::getDefaultTransmissionOptions(); + + config["mechanicalReduction"] = 0.0; + + return config; + }; + + struct transmissionOptions_t : public abstractTransmissionOptions_t + { + float64_t const mechanicalReduction; ///< Gear reduction ratio motor to joint + + transmissionOptions_t(configHolder_t const & options) : + abstractTransmissionOptions_t(options), + mechanicalReduction(boost::get(options.at("mechanicalReduction"))) + { + // Empty. + } + }; + + public: + SimpleTransmission(std::string const & name); + virtual ~SimpleTransmission(void) = default; + + auto shared_from_this() { return shared_from(this); } + auto shared_from_this() const { return shared_from(this); } + + hresult_t initialize(std::string const & jointName, + std::string const & motorName); + + virtual hresult_t setOptions(configHolder_t const & transmissionOptions) final override; + + private: + virtual hresult_t computeTransmission(float64_t const & t, + Eigen::VectorBlock q, + float64_t v, + float64_t const & a, + float64_t command) final override; + + virtual hresult_t computeInverseTransmission(float64_t const & t, + Eigen::VectorBlock q, + float64_t v, + float64_t const & a, + float64_t command) final override; + + private: + std::unique_ptr transmissionOptions_; + }; +} + +#endif //end of JIMINY_BASIC_TRANSMISSIONS_H \ No newline at end of file diff --git a/core/include/jiminy/core/robot/Robot.h b/core/include/jiminy/core/robot/Robot.h index 4bdad1b1db..4534c2bc20 100644 --- a/core/include/jiminy/core/robot/Robot.h +++ b/core/include/jiminy/core/robot/Robot.h @@ -22,6 +22,7 @@ namespace jiminy using sensorsHolder_t = std::vector >; using sensorsGroupHolder_t = std::unordered_map; using sensorsSharedHolder_t = std::unordered_map >; + using transmissionsHolder_t = std::vector >; public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW @@ -142,6 +143,7 @@ namespace jiminy bool_t isTelemetryConfigured_; std::shared_ptr telemetryData_; motorsHolder_t motorsHolder_; + transmissionsHolder_t tranmissionsHolder_; sensorsGroupHolder_t sensorsGroupHolder_; std::unordered_map sensorTelemetryOptions_; std::vector motorsNames_; ///< Name of the motors @@ -149,6 +151,7 @@ namespace jiminy std::vector commandFieldnames_; ///< Fieldnames of the command std::vector motorEffortFieldnames_; ///< Fieldnames of the motors effort uint64_t nmotors_; ///< The number of motors + std::vector actuatedJoints_; ///< List of joints attached to a transmission private: std::unique_ptr mutexLocal_; diff --git a/core/src/robot/AbstractMotor.cc b/core/src/robot/AbstractMotor.cc index edd243cb45..6cdec5d48b 100644 --- a/core/src/robot/AbstractMotor.cc +++ b/core/src/robot/AbstractMotor.cc @@ -10,17 +10,11 @@ namespace jiminy AbstractMotorBase::AbstractMotorBase(std::string const & name) : baseMotorOptions_(nullptr), motorOptionsHolder_(), - isInitialized_(false), isAttached_(false), robot_(), notifyRobot_(), name_(name), motorIdx_(-1), - jointName_(), - jointModelIdx_(-1), - jointType_(joint_t::NONE), - jointPositionIdx_(-1), - jointVelocityIdx_(-1), commandLimit_(0.0), armature_(0.0), sharedHolder_(nullptr) @@ -216,15 +210,6 @@ namespace jiminy } } - if (returnCode == hresult_t::SUCCESS) - { - if (!isInitialized_) - { - PRINT_ERROR("Motor not initialized. Impossible to refresh proxies."); - returnCode = hresult_t::ERROR_INIT_FAILED; - } - } - if (returnCode == hresult_t::SUCCESS) { if (!robot->getIsInitialized()) @@ -236,33 +221,12 @@ namespace jiminy if (returnCode == hresult_t::SUCCESS) { - returnCode = ::jiminy::getJointModelIdx(robot->pncModel_, jointName_, jointModelIdx_); - } - - if (returnCode == hresult_t::SUCCESS) - { - returnCode = getJointTypeFromIdx(robot->pncModel_, jointModelIdx_, jointType_); - } - - if (returnCode == hresult_t::SUCCESS) - { - // Motors are only supported for linear and rotary joints - if (jointType_ != joint_t::LINEAR && jointType_ != joint_t::ROTARY && jointType_ != joint_t::ROTARY_UNBOUNDED) - { - PRINT_ERROR("A motor can only be associated with a 1-dof linear or rotary joint."); - returnCode = hresult_t::ERROR_BAD_INPUT; - } - } - - if (returnCode == hresult_t::SUCCESS) - { - ::jiminy::getJointPositionIdx(robot->pncModel_, jointName_, jointPositionIdx_); ::jiminy::getJointVelocityIdx(robot->pncModel_, jointName_, jointVelocityIdx_); // Get the motor effort limits from the URDF or the user options. if (baseMotorOptions_->commandLimitFromUrdf) { - commandLimit_ = robot->pncModel_.effortLimit[jointVelocityIdx_] / baseMotorOptions_->mechanicalReduction; + commandLimit_ = robot->pncModel_.effortLimit[jointVelocityIdx_]; } else { @@ -289,24 +253,42 @@ namespace jiminy return returnCode; } - float64_t const & AbstractMotorBase::get(void) const + float64_t & AbstractMotorBase::q(void) { - static float64_t dataEmpty; - if (isAttached_) - { - return sharedHolder_->data_[motorIdx_]; - } - return dataEmpty; + return sharedHolder_->position_[motorIdx_]; + } + + float64_t & AbstractMotorBase::v(void) + { + return sharedHolder_->velocity_[motorIdx_]; + } + float64_t & AbstractMotorBase::a(void) + { + return sharedHolder_->acceleration_[motorIdx_]; + } + float64_t & AbstractMotorBase::u(void) + { + return sharedHolder_->effort_[motorIdx_]; } - float64_t & AbstractMotorBase::data(void) + float64_t const & AbstractMotorBase::getPosition(void) { - return sharedHolder_->data_[motorIdx_]; + return sharedHolder_->position_[motorIdx_]; } - vectorN_t const & AbstractMotorBase::getAll(void) const + float64_t const & AbstractMotorBase::getVelocity(void); { - return sharedHolder_->data_; + return sharedHolder_->velocity_[motorIdx_]; + } + + float64_t const & AbstractMotorBase::getAcceleration(void); + { + return sharedHolder_->acceleration_[motorIdx_]; + } + + float64_t const & AbstractMotorBase::getEffort(void); + { + return sharedHolder_->effort_[motorIdx_]; } hresult_t AbstractMotorBase::setOptionsAll(configHolder_t const & motorOptions) @@ -346,31 +328,6 @@ namespace jiminy return motorIdx_; } - std::string const & AbstractMotorBase::getJointName(void) const - { - return jointName_; - } - - jointIndex_t const & AbstractMotorBase::getJointModelIdx(void) const - { - return jointModelIdx_; - } - - joint_t const & AbstractMotorBase::getJointType(void) const - { - return jointType_; - } - - int32_t const & AbstractMotorBase::getJointPositionIdx(void) const - { - return jointPositionIdx_; - } - - int32_t const & AbstractMotorBase::getJointVelocityIdx(void) const - { - return jointVelocityIdx_; - } - float64_t const & AbstractMotorBase::getCommandLimit(void) const { return commandLimit_; @@ -381,11 +338,7 @@ namespace jiminy return armature_; } - hresult_t AbstractMotorBase::computeEffortAll(float64_t const & t, - vectorN_t const & q, - vectorN_t const & v, - vectorN_t const & a, - vectorN_t const & command) + hresult_t AbstractMotorBase::computeEffortAll(vectorN_t const & command) { hresult_t returnCode = hresult_t::SUCCESS; @@ -401,20 +354,7 @@ namespace jiminy { if (returnCode == hresult_t::SUCCESS) { - uint8_t nq_motor; - if (motor->getJointType() == joint_t::ROTARY_UNBOUNDED) - { - nq_motor = 2; - } - else - { - nq_motor = 1; - } - returnCode = motor->computeEffort(t, - q.segment(motor->getJointPositionIdx(), nq_motor), - v[motor->getJointVelocityIdx()], - a[motor->getJointVelocityIdx()], - command[motor->getIdx()]); + returnCode = motor->computeEffort(command[motor->getIdx()]); } } diff --git a/core/src/robot/AbstractTransmission.cc b/core/src/robot/AbstractTransmission.cc new file mode 100644 index 0000000000..1ad446ef4d --- /dev/null +++ b/core/src/robot/AbstractTransmission.cc @@ -0,0 +1,405 @@ +#include "jiminy/core/robot/Robot.h" +#include "jiminy/core/Macros.h" + +#include "jiminy/core/utilities/Pinocchio.h" +#include "jiminy/core/robot/AbstractTransmission.h" + + +namespace jiminy +{ + AbstractTransmissionBase::AbstractTransmissionBase(std::string const & name) : + baseTransmissionOptions_(nullptr), + transmissionOptionsHolder_(), + isInitialized_(false), + isAttached_(false), + robot_(), + notifyRobot_(), + name_(name), + transmissionIdx_(-1), + jointName_(), + jointModelIdx_(-1), + jointType_(joint_t::NONE), + jointPositionIdx_(-1), + jointVelocityIdx_(-1), + motorName_(), + armature_(0.0), + sharedHolder_(nullptr) + { + // Initialize the options + setOptions(getDefaultTransmissionOptions()); + } + + AbstractTransmissionBase::~AbstractTransmissionBase(void) + { + // Detach the sensor before deleting it if necessary + if (isAttached_) + { + detach(); + } + } + + hresult_t AbstractTransmissionBase::attach(std::weak_ptr robot, + std::function notifyRobot) + { + // Make sure the transmission is not already attached + if (isAttached_) + { + PRINT_ERROR("Transmission already attached to a robot. Please 'detach' method before attaching it."); + return hresult_t::ERROR_GENERIC; + } + + // Make sure the robot still exists + if (robot.expired()) + { + PRINT_ERROR("Robot pointer expired or unset."); + return hresult_t::ERROR_GENERIC; + } + + // Make sure the joint is not already attached to a transmission + std::vector::iterator transmissionJointsIt = AbstractTransmissionBase::getJointName().begin(); + + for ( ; transmissionJointsIt != AbstractTransmissionBase::getJointName().end(); ++transmissionJointsIt) + std::vector::iterator actuatedJointIt = AbstractTransmissionBase::robot.getActuatedJoints.begin(); + + for ( ; actuatedJointIt != AbstractTransmissionBase::robot.getActuatedJoints.end(); ++actuatedJointIt) + { + if (*transmissionJointsIt == *actuatedJointIt) + { + PRINT_ERROR("Joint already attached to another transmission"); + return hresult_t::ERROR_GENERIC; + } + + } + + // Copy references to the robot and shared data + robot_ = robot; + notifyRobot_ = notifyRobot; + sharedHolder_ = sharedHolder; + + // Get an index + transmissionIdx_ = sharedHolder_->num_; + + // Add a value for the transmission to the shared data buffer + sharedHolder_->data_.conservativeResize(sharedHolder_->num_ + 1); + sharedHolder_->data_.tail<1>().setZero(); + + // Add the transmission to the shared memory + sharedHolder_->transmissions_.push_back(this); + ++sharedHolder_->num_; + + // Update the flag + isAttached_ = true; + + return hresult_t::SUCCESS; + } + + hresult_t AbstractTransmissionBase::detach(void) + { + // Delete the part of the shared memory associated with the transmission + + if (!isAttached_) + { + PRINT_ERROR("Transmission not attached to any robot."); + return hresult_t::ERROR_GENERIC; + } + + // Remove associated col in the global data buffer + if (transmissionIdx_ < sharedHolder_->num_ - 1) + { + int32_t transmissionShift = sharedHolder_->num_ - transmissionIdx_ - 1; + sharedHolder_->data_.segment(transmissionIdx_, transmissionShift) = + sharedHolder_->data_.segment(transmissionIdx_ + 1, transmissionShift).eval(); // eval to avoid aliasing + } + sharedHolder_->data_.conservativeResize(sharedHolder_->num_ - 1); + + // Shift the transmission ids + for (int32_t i = transmissionIdx_ + 1; i < sharedHolder_->num_; ++i) + { + --sharedHolder_->transmissions_[i]->transmissionIdx_; + } + + // Remove the transmission to the shared memory + sharedHolder_->transmissions_.erase(sharedHolder_->transmissions_.begin() + transmissionIdx_); + --sharedHolder_->num_; + + // Clear the references to the robot and shared data + robot_.reset(); + notifyRobot_ = nullptr; + sharedHolder_ = nullptr; + + // Unset the Id + transmissionIdx_ = -1; + + // Update the flag + isAttached_ = false; + + return hresult_t::SUCCESS; + } + + hresult_t AbstractTransmissionBase::resetAll(void) + { + // Make sure the transmission is attached to a robot + if (!isAttached_) + { + PRINT_ERROR("Transmission not attached to any robot."); + return hresult_t::ERROR_GENERIC; + } + + // Make sure the robot still exists + if (robot_.expired()) + { + PRINT_ERROR("Robot has been deleted. Impossible to reset the transmissions."); + return hresult_t::ERROR_GENERIC; + } + + // Clear the shared data buffer + sharedHolder_->data_.setZero(); + + // Update transmission scope information + for (AbstractTransmissionBase * transmission : sharedHolder_->transmissions_) + { + // Refresh proxies that are robot-dependent + transmission->refreshProxies(); + } + + return hresult_t::SUCCESS; + } + + hresult_t AbstractTransmissionBase::setOptions(configHolder_t const & transmissionOptions) + { + // Check if the internal buffers must be updated + bool_t internalBuffersMustBeUpdated = false; + if (isInitialized_) + { + // Check if armature has changed + bool_t const & enableArmature = boost::get(transmissionOptions.at("enableArmature")); + internalBuffersMustBeUpdated |= (baseTransmissionOptions_->enableArmature != enableArmature); + if (enableArmature) + { + float64_t const & armature = boost::get(transmissionOptions.at("armature")); + internalBuffersMustBeUpdated |= std::abs(armature - baseTransmissionOptions_->armature) > EPS; + } + } + + // Update the transmission's options + transmissionOptionsHolder_ = transmissionOptions; + baseTransmissionOptions_ = std::make_unique(transmissionOptionsHolder_); + + // Refresh the proxies if the robot is initialized if available + if (auto robot = robot_.lock()) + { + if (internalBuffersMustBeUpdated && robot->getIsInitialized() && isAttached_) + { + refreshProxies(); + } + } + + return hresult_t::SUCCESS; + } + + configHolder_t AbstractTransmissionBase::getOptions(void) const + { + return transmissionOptionsHolder_; + } + + hresult_t AbstractTransmissionBase::refreshProxies(void) + { + hresult_t returnCode = hresult_t::SUCCESS; + + if (!isAttached_) + { + PRINT_ERROR("Transmission not attached to any robot. Impossible to refresh proxies."); + returnCode = hresult_t::ERROR_INIT_FAILED; + } + + auto robot = robot_.lock(); + if (returnCode == hresult_t::SUCCESS) + { + if (!robot) + { + PRINT_ERROR("Robot has been deleted. Impossible to refresh proxies."); + returnCode = hresult_t::ERROR_GENERIC; + } + } + + if (returnCode == hresult_t::SUCCESS) + { + if (!isInitialized_) + { + PRINT_ERROR("Transmission not initialized. Impossible to refresh proxies."); + returnCode = hresult_t::ERROR_INIT_FAILED; + } + } + + if (returnCode == hresult_t::SUCCESS) + { + if (!robot->getIsInitialized()) + { + PRINT_ERROR("Robot not initialized. Impossible to refresh proxies."); + returnCode = hresult_t::ERROR_INIT_FAILED; + } + } + + for (i = 0; i < jointName_.size(); i++) + { + if (returnCode == hresult_t::SUCCESS) + { + returnCode = ::jiminy::getJointModelIdx(robot->pncModel_, jointName_[i], jointModelIdx_[i]); + } + } + for (i = 0; i < jointName_.size(); i++) + { + if (returnCode == hresult_t::SUCCESS) + { + returnCode = getJointTypeFromIdx(robot->pncModel_, jointModelIdx_[i], jointType_[i]); + } + } + + for (i = 0; i < jointName_.size(); i++) + { + if (returnCode == hresult_t::SUCCESS) + { + // Transmissions are only supported for linear and rotary joints + if (jointType_[i] != joint_t::LINEAR && jointType_[i] != joint_t::ROTARY && jointType_[i] != joint_t::ROTARY_UNBOUNDED) + { + PRINT_ERROR("A transmission can only be associated with a 1-dof linear or rotary joint."); + returnCode = hresult_t::ERROR_BAD_INPUT; + } + } + } + + for (i = 0; i < jointName_.size(); i++) + { + if (returnCode == hresult_t::SUCCESS) + { + ::jiminy::getJointPositionIdx(robot->pncModel_, jointName_[i], jointPositionIdx_[i]); + ::jiminy::getJointVelocityIdx(robot->pncModel_, jointName_[i], jointVelocityIdx_[i]); + + // Get the rotor inertia + if (baseTransmissionOptions_->enableArmature) + { + armature_ = baseTransmissionOptions_->armature; + } + else + { + armature_ = 0.0; + } + + // Propagate the user-defined transmission inertia at Pinocchio model level + if (notifyRobot_) + { + returnCode = notifyRobot_(*this); + } + } + } + + return returnCode; + } + + hresult_t AbstractTransmissionBase::setOptionsAll(configHolder_t const & transmissionOptions) + { + hresult_t returnCode = hresult_t::SUCCESS; + + // Make sure the transmission is attached to a robot + if (!isAttached_) + { + PRINT_ERROR("Transmission not attached to any robot."); + returnCode = hresult_t::ERROR_GENERIC; + } + + for (AbstractTransmissionBase * transmission : sharedHolder_->transmissions_) + { + if (returnCode == hresult_t::SUCCESS) + { + returnCode = transmission->setOptions(transmissionOptions); + } + } + + return returnCode; + } + + bool_t const & AbstractTransmissionBase::getIsInitialized(void) const + { + return isInitialized_; + } + + std::string const & AbstractTransmissionBase::getName(void) const + { + return name_; + } + + int32_t const & AbstractTransmissionBase::getIdx(void) const + { + return transmissionIdx_; + } + + std::vector::string const & AbstractTransmissionBase::getJointName(void) const + { + return jointName_; + } + + std::vector const & AbstractTransmissionBase::getJointModelIdx(void) const + { + return jointModelIdx_; + } + + std::vector const & AbstractTransmissionBase::getJointType(void) const + { + return jointType_; + } + + std::vector const & AbstractTransmissionBase::getJointPositionIdx(void) const + { + return jointPositionIdx_; + } + + int32_t const & AbstractTransmissionBase::getJointVelocityIdx(void) const + { + return jointVelocityIdx_; + } + + std::vector::string const & AbstractTransmissionBase::getMotorName(void) const + { + return motorName_; + } + + hresult_t AbstractTransmissionBase::computeTransmissionAll(float64_t const & t, + vectorN_t const & q, + vectorN_t const & v, + vectorN_t const & a, + vectorN_t const & command) + { + hresult_t returnCode = hresult_t::SUCCESS; + + // Make sure the transmission is attached to a robot + if (!isAttached_) + { + PRINT_ERROR("Transmission not attached to any robot."); + returnCode = hresult_t::ERROR_GENERIC; + } + + // Compute the actual effort of every transmission + for (AbstractTransmissionBase * transmission : sharedHolder_->transmissions_) + { + if (returnCode == hresult_t::SUCCESS) + { + uint8_t nq_transmission; + if (transmission->getJointType() == joint_t::ROTARY_UNBOUNDED) + { + nq_transmission = 2; + } + else + { + nq_transmission = 1; + } + returnCode = transmission->computeTransmission(t, + q.segment(transmission->getJointPositionIdx(), nq_transmission), + v[transmission->getJointVelocityIdx()], + a[transmission->getJointVelocityIdx()], + command[transmission->getIdx()]); + } + } + + return returnCode; + } +} diff --git a/core/src/robot/BasicMotors.cc b/core/src/robot/BasicMotors.cc index be27e536fa..6586ee37ba 100644 --- a/core/src/robot/BasicMotors.cc +++ b/core/src/robot/BasicMotors.cc @@ -17,23 +17,6 @@ namespace jiminy setOptions(getDefaultMotorOptions()); } - hresult_t SimpleMotor::initialize(std::string const & jointName) - { - hresult_t returnCode = hresult_t::SUCCESS; - - jointName_ = jointName; - isInitialized_ = true; - returnCode = refreshProxies(); - - if (returnCode != hresult_t::SUCCESS) - { - jointName_.clear(); - isInitialized_ = false; - } - - return returnCode; - } - hresult_t SimpleMotor::setOptions(configHolder_t const & motorOptions) { hresult_t returnCode = hresult_t::SUCCESS; @@ -79,25 +62,16 @@ namespace jiminy return returnCode; } - hresult_t SimpleMotor::computeEffort(float64_t const & /* t */, - Eigen::VectorBlock const & /* q */, - float64_t const & v, - float64_t const & /* a */, - float64_t command) + hresult_t SimpleMotor::computeEffort(float64_t const & v, + float64_t command) { - if (!isInitialized_) - { - PRINT_ERROR("Motor not initialized. Impossible to compute actual motor effort."); - return hresult_t::ERROR_INIT_FAILED; - } - /* Compute the motor effort, taking into account the limit, if any. It is the output of the motor on joint side, ie after the transmission. */ if (motorOptions_->enableCommandLimit) { command = clamp(command, -getCommandLimit(), getCommandLimit()); } - data() = motorOptions_->mechanicalReduction * command; + data() = command; /* Add friction to the joints associated with the motor if enable. It is computed on joint side instead of the motor. */ diff --git a/core/src/robot/BasicTransmissions.cc b/core/src/robot/BasicTransmissions.cc new file mode 100644 index 0000000000..8cd07e6276 --- /dev/null +++ b/core/src/robot/BasicTransmissions.cc @@ -0,0 +1,102 @@ +#include + +#include "jiminy/core/utilities/Helpers.h" + +#include "jiminy/core/robot/BasicTransmissions.h" + + +namespace jiminy +{ + SimpleTransmission::SimpleTransmission(std::string const & name) : + AbstractTransmissionBase(name), + transmissionOptions_(nullptr) + { + /* AbstractTransmissionBase constructor calls the base implementations of + the virtual methods since the derived class is not available at + this point. Thus it must be called explicitly in the constructor. */ + setOptions(getDefaultTransmissionOptions()); + } + + hresult_t SimpleTransmission::initialize(std::string const & jointName, std::string const & motorName) + { + hresult_t returnCode = hresult_t::SUCCESS; + + jointName_ = jointName; + motorName_ = motorName; + isInitialized_ = true; + returnCode = refreshProxies(); + + if (returnCode != hresult_t::SUCCESS) + { + jointName_.clear(); + motorName_.clear(); + isInitialized_ = false; + } + + return returnCode; + } + + hresult_t SimpleTransmission::setOptions(configHolder_t const & transmissionOptions) + { + hresult_t returnCode = hresult_t::SUCCESS; + + returnCode = AbstractTransmissionBase::setOptions(transmissionOptions); + + // Check if the friction parameters make sense + if (returnCode == hresult_t::SUCCESS) + { + // Make sure the user-defined position limit has the right dimension + if (boost::get(transmissionOptions.at("frictionViscousPositive")) > 0.0) + { + PRINT_ERROR("'frictionViscousPositive' must be negative."); + returnCode = hresult_t::ERROR_BAD_INPUT; + } + if (boost::get(transmissionOptions.at("frictionViscousNegative")) > 0.0) + { + PRINT_ERROR("'frictionViscousNegative' must be negative."); + returnCode = hresult_t::ERROR_BAD_INPUT; + } + if (boost::get(transmissionOptions.at("frictionDryPositive")) > 0.0) + { + PRINT_ERROR("'frictionDryPositive' must be negative."); + returnCode = hresult_t::ERROR_BAD_INPUT; + } + if (boost::get(transmissionOptions.at("frictionDryNegative")) > 0.0) + { + PRINT_ERROR("'frictionDryNegative' must be negative."); + returnCode = hresult_t::ERROR_BAD_INPUT; + } + if (boost::get(transmissionOptions.at("frictionDrySlope")) < 0.0) + { + PRINT_ERROR("'frictionDrySlope' must be positive."); + returnCode = hresult_t::ERROR_BAD_INPUT; + } + } + + if (returnCode == hresult_t::SUCCESS) + { + transmissionOptions_ = std::make_unique(transmissionOptions); + } + + return returnCode; + } + + hresult_t SimpleTransmission::computeTransmission(float64_t const & /* t */, + Eigen::VectorBlock q, + float64_t v, + float64_t const & /* a */, + float64_t command) + { + if (!isInitialized_) + { + PRINT_ERROR("Transmission not initialized. Impossible to compute actual transmission effort."); + return hresult_t::ERROR_INIT_FAILED; + } + + data() = transmissionOptions_->mechanicalReduction * q; + data() = transmissionOptions_->mechanicalReduction * v; + data() = transmissionOptions_->mechanicalReduction * command; + + return hresult_t::SUCCESS; + } +} diff --git a/core/src/robot/Robot.cc b/core/src/robot/Robot.cc index b766f04080..5feb4d2d73 100644 --- a/core/src/robot/Robot.cc +++ b/core/src/robot/Robot.cc @@ -28,6 +28,7 @@ namespace jiminy commandFieldnames_(), motorEffortFieldnames_(), nmotors_(0U), + actuatedJoints(), mutexLocal_(std::make_unique()), motorsSharedHolder_(std::make_shared()), sensorsSharedHolder_() @@ -619,6 +620,11 @@ namespace jiminy return motorsHolder_; } + Robot::transmissionsHolder_t const & Robot::getTransmissions(void) const + { + return tranmissionsHolder_; + } + hresult_t Robot::getSensor(std::string const & sensorType, std::string const & sensorName, std::weak_ptr & sensor) const @@ -692,6 +698,11 @@ namespace jiminy return sensorsGroupHolder_; } + Robot::tranmissionssGroupHolder_t const & Robot::getTransmissions(void) const + { + return tranmissionssGroupHolder_; + } + hresult_t Robot::setOptions(configHolder_t const & robotOptions) { hresult_t returnCode = hresult_t::SUCCESS;