1 |
|
|
/* |
2 |
|
|
* Copyright 2017, Andrea Del Prete, LAAS-CNRS |
3 |
|
|
* |
4 |
|
|
*/ |
5 |
|
|
|
6 |
|
|
#ifndef _DeviceTorqueCtrl_H_ |
7 |
|
|
#define _DeviceTorqueCtrl_H_ |
8 |
|
|
|
9 |
|
|
#include <pinocchio/fwd.hpp> |
10 |
|
|
|
11 |
|
|
// include pinocchio first |
12 |
|
|
|
13 |
|
|
#include <dynamic-graph/entity.h> |
14 |
|
|
#include <dynamic-graph/linear-algebra.h> |
15 |
|
|
#include <dynamic-graph/signal-ptr.h> |
16 |
|
|
#include <dynamic-graph/signal.h> |
17 |
|
|
|
18 |
|
|
#include <Eigen/Cholesky> |
19 |
|
|
#include <boost/random/mersenne_twister.hpp> |
20 |
|
|
#include <boost/random/normal_distribution.hpp> |
21 |
|
|
#include <boost/random/variate_generator.hpp> |
22 |
|
|
#include <sot/core/abstract-sot-external-interface.hh> |
23 |
|
|
#include <sot/core/device.hh> |
24 |
|
|
#include <tsid/robots/robot-wrapper.hpp> |
25 |
|
|
#include <tsid/tasks/task-se3-equality.hpp> |
26 |
|
|
|
27 |
|
|
/* HELPER */ |
28 |
|
|
#include <dynamic-graph/signal-helper.h> |
29 |
|
|
|
30 |
|
|
#include <sot/core/robot-utils.hh> |
31 |
|
|
|
32 |
|
|
namespace dgsot = dynamicgraph::sot; |
33 |
|
|
|
34 |
|
|
namespace dynamicgraph { |
35 |
|
|
namespace sot { |
36 |
|
|
namespace torque_control { |
37 |
|
|
|
38 |
|
|
/** Version of device for testing the code without the |
39 |
|
|
* real robot. This version of the device assumes that the robot |
40 |
|
|
* is torque controlled (i.e. the control input are the desired |
41 |
|
|
* joint torques). These desired joint torques are used to compute |
42 |
|
|
* the joint accelerations and the contact forces. |
43 |
|
|
* The joint accelerations are then integrated to get the |
44 |
|
|
* measured joint angles. |
45 |
|
|
* |
46 |
|
|
* The feet are supposed to be fixed to the ground. The accelerometer |
47 |
|
|
* and the gyrometer output a constant value. |
48 |
|
|
* |
49 |
|
|
* A white Gaussian noise is added to the force/torque sensor |
50 |
|
|
* measurements. |
51 |
|
|
* |
52 |
|
|
* TODO: The original Device class should be a clean abstraction for |
53 |
|
|
* the concept of device, but currently it is not. It defines a lot |
54 |
|
|
* of input/output signals that are specific of HRP-2 (e.g. zmpSIN, |
55 |
|
|
* attitudeSIN, forcesSOUT) and some design choices (e.g. |
56 |
|
|
* secondOrderIntegration). It would be nice to clean the original Device from |
57 |
|
|
* all this stuff and move it in the specific subclasses. |
58 |
|
|
*/ |
59 |
|
|
class DeviceTorqueCtrl : public dgsot::Device { |
60 |
|
|
public: |
61 |
|
|
static const std::string CLASS_NAME; |
62 |
|
|
static const double TIMESTEP_DEFAULT; |
63 |
|
|
static const double FORCE_SENSOR_NOISE_STD_DEV; |
64 |
|
|
|
65 |
|
|
virtual const std::string& getClassName() const { return CLASS_NAME; } |
66 |
|
|
|
67 |
|
|
DeviceTorqueCtrl(std::string RobotName); |
68 |
|
|
virtual ~DeviceTorqueCtrl(); |
69 |
|
|
|
70 |
|
|
virtual void setStateSize(const unsigned int& size); |
71 |
|
|
virtual void setState(const dynamicgraph::Vector& st); |
72 |
|
|
virtual void setVelocity(const dynamicgraph::Vector& vel); |
73 |
|
|
virtual void setControlInputType(const std::string& cit); |
74 |
|
|
|
75 |
|
|
virtual void init(const double& dt, const std::string& urdfFile); |
76 |
|
|
|
77 |
|
|
protected: |
78 |
|
|
virtual void integrate(const double& dt); |
79 |
|
|
void computeForwardDynamics(); |
80 |
|
|
|
81 |
|
|
void sendMsg(const std::string& msg, MsgType t = MSG_TYPE_INFO, |
82 |
|
|
const char* = "", int = 0) { |
83 |
|
|
logger_.stream(t) << ("[DeviceTorqueCtrl] " + msg) << '\n'; |
84 |
|
|
} |
85 |
|
|
|
86 |
|
|
/// \brief Current integration step. |
87 |
|
|
double timestep_; |
88 |
|
|
bool m_initSucceeded; |
89 |
|
|
|
90 |
|
|
/// input force sensor values |
91 |
|
|
dynamicgraph::SignalPtr<dynamicgraph::Vector, int>* forcesSIN_[4]; |
92 |
|
|
|
93 |
|
|
/// Accelerations measured by accelerometers |
94 |
|
|
dynamicgraph::Signal<dynamicgraph::Vector, int> accelerometerSOUT_; |
95 |
|
|
/// Rotation velocity measured by gyrometers |
96 |
|
|
dynamicgraph::Signal<dynamicgraph::Vector, int> gyrometerSOUT_; |
97 |
|
|
/// base 6d pose + joints' angles measured by encoders |
98 |
|
|
dynamicgraph::Signal<dynamicgraph::Vector, int> robotStateSOUT_; |
99 |
|
|
/// joints' velocities computed by the integrator |
100 |
|
|
dynamicgraph::Signal<dynamicgraph::Vector, int> jointsVelocitiesSOUT_; |
101 |
|
|
/// joints' accelerations computed by the integrator |
102 |
|
|
dynamicgraph::Signal<dynamicgraph::Vector, int> jointsAccelerationsSOUT_; |
103 |
|
|
/// motor currents |
104 |
|
|
dynamicgraph::Signal<dynamicgraph::Vector, int> currentSOUT_; |
105 |
|
|
/// proportional and derivative position-control gains |
106 |
|
|
dynamicgraph::Signal<dynamicgraph::Vector, int> p_gainsSOUT_; |
107 |
|
|
dynamicgraph::Signal<dynamicgraph::Vector, int> d_gainsSOUT_; |
108 |
|
|
|
109 |
|
|
DECLARE_SIGNAL_IN(kp_constraints, dynamicgraph::Vector); |
110 |
|
|
DECLARE_SIGNAL_IN(kd_constraints, dynamicgraph::Vector); |
111 |
|
|
DECLARE_SIGNAL_IN(rotor_inertias, dynamicgraph::Vector); |
112 |
|
|
DECLARE_SIGNAL_IN(gear_ratios, dynamicgraph::Vector); |
113 |
|
|
|
114 |
|
|
/// Intermediate variables to avoid allocation during control |
115 |
|
|
dynamicgraph::Vector accelerometer_; |
116 |
|
|
dynamicgraph::Vector gyrometer_; |
117 |
|
|
|
118 |
|
|
dynamicgraph::Vector base6d_encoders_; /// base 6d pose + joints' angles |
119 |
|
|
dynamicgraph::Vector jointsVelocities_; /// joints' velocities |
120 |
|
|
dynamicgraph::Vector jointsAccelerations_; /// joints' accelerations |
121 |
|
|
|
122 |
|
|
dynamicgraph::Vector wrenches_[4]; |
123 |
|
|
dynamicgraph::Vector temp6_; |
124 |
|
|
|
125 |
|
|
bool m_isTorqueControlled; |
126 |
|
|
|
127 |
|
|
/// robot geometric/inertial data |
128 |
|
|
tsid::robots::RobotWrapper* m_robot; |
129 |
|
|
pinocchio::Data* m_data; |
130 |
|
|
tsid::tasks::TaskSE3Equality* m_contactRF; |
131 |
|
|
tsid::tasks::TaskSE3Equality* m_contactLF; |
132 |
|
|
unsigned int m_nk; // number of contact forces |
133 |
|
|
|
134 |
|
|
tsid::math::Vector m_q, m_v, m_dv, m_f; |
135 |
|
|
tsid::math::Vector m_q_sot, m_v_sot, m_dv_sot; |
136 |
|
|
|
137 |
|
|
typedef Eigen::LDLT<Eigen::MatrixXd> Cholesky; |
138 |
|
|
Cholesky m_K_chol; /// cholesky decomposition of the K matrix |
139 |
|
|
Eigen::MatrixXd m_K; |
140 |
|
|
Eigen::VectorXd m_k; |
141 |
|
|
Eigen::MatrixXd m_Jc; /// constraint Jacobian |
142 |
|
|
|
143 |
|
|
double m_numericalDamping; /// numerical damping to regularize constraint |
144 |
|
|
/// resolution |
145 |
|
|
Eigen::JacobiSVD<Matrix> m_Jc_svd; /// svd of the constraint matrix |
146 |
|
|
Vector m_dJcv; |
147 |
|
|
Matrix m_Z; /// base of constraint null space |
148 |
|
|
Matrix m_ZMZ; /// projected mass matrix: Z_c^T*M*Z_c |
149 |
|
|
Eigen::LDLT<Matrix> m_ZMZ_chol; /// Cholesky decomposition of _ZMZ |
150 |
|
|
Vector m_dv_c; /// constrained accelerations |
151 |
|
|
Vector m_dvBar; /// solution of Jc*dv=-dJc*v |
152 |
|
|
Vector m_tau_np6; |
153 |
|
|
int m_nj; /// number of joints |
154 |
|
|
|
155 |
|
|
typedef boost::mt11213b ENG; // uniform random number generator |
156 |
|
|
typedef boost::normal_distribution<double> DIST; // Normal Distribution |
157 |
|
|
typedef boost::variate_generator<ENG, DIST> GEN; // Variate generator |
158 |
|
|
ENG randomNumberGenerator_; |
159 |
|
|
DIST normalDistribution_; |
160 |
|
|
GEN normalRandomNumberGenerator_; |
161 |
|
|
|
162 |
|
|
RobotUtilShrPtr m_robot_util; |
163 |
|
|
}; |
164 |
|
|
|
165 |
|
|
} // end namespace torque_control |
166 |
|
|
} // end namespace sot |
167 |
|
|
} // end namespace dynamicgraph |
168 |
|
|
#endif /* DevicePosCtrl*/ |