Control Libraries 7.4.0
Loading...
Searching...
No Matches
Jacobian.cpp
1#include "state_representation/space/Jacobian.hpp"
2
3#include "state_representation/exceptions/EmptyStateException.hpp"
4#include "state_representation/exceptions/IncompatibleStatesException.hpp"
5#include "state_representation/exceptions/InvalidCastException.hpp"
6
7namespace state_representation {
8
9using namespace exceptions;
10
11static void assert_matrix_size(const Eigen::MatrixXd& matrix, unsigned int expected_rows, unsigned int expected_cols) {
12 if (expected_rows != matrix.rows() || expected_cols != matrix.cols()) {
13 throw exceptions::IncompatibleSizeException(
14 "Matrix is of incorrect size, expected " + std::to_string(expected_rows) + "x" + std::to_string(expected_cols)
15 + " got " + std::to_string(matrix.rows()) + "x" + std::to_string(matrix.cols()));
16 }
17}
18
20 this->set_type(StateType::JACOBIAN);
21}
22
24 const std::string& robot_name, unsigned int nb_joints, const std::string& frame, const std::string& reference_frame
25) :
26 State(robot_name),
27 joint_names_(nb_joints),
28 frame_(frame),
29 reference_frame_(reference_frame),
30 data_(Eigen::MatrixXd::Zero(6, nb_joints)) {
31 this->set_type(StateType::JACOBIAN);
32 this->set_joint_names(nb_joints);
33}
34
36 const std::string& robot_name, const std::vector<std::string>& joint_names, const std::string& frame,
37 const std::string& reference_frame
38) : Jacobian(robot_name, joint_names.size(), frame, reference_frame) {
39 this->set_joint_names(joint_names);
40}
41
43 const std::string& robot_name, const std::string& frame, const Eigen::MatrixXd& data,
44 const std::string& reference_frame
45) : Jacobian(robot_name, data.cols(), frame, reference_frame) {
46 assert_matrix_size(data, 6, data.cols());
47 this->data_ = data;
48 this->set_empty(false);
49}
50
52 const std::string& robot_name, const std::vector<std::string>& joint_names, const std::string& frame,
53 const Eigen::MatrixXd& data, const std::string& reference_frame
54) : Jacobian(robot_name, frame, data, reference_frame) {
55 this->set_joint_names(joint_names);
56}
57
58Jacobian::Jacobian(const Jacobian& jacobian) :
59 Jacobian(jacobian.get_name(), jacobian.joint_names_, jacobian.frame_, jacobian.reference_frame_) {
60 if (jacobian) {
61 this->data_ = jacobian.data_;
62 this->set_empty(false);
63 }
64}
65
67 const std::string& robot_name, unsigned int nb_joints, const std::string& frame, const std::string& reference_frame
68) {
69 return {robot_name, frame, Eigen::MatrixXd::Random(6, nb_joints), reference_frame};
70}
71
73 const std::string& robot_name, const std::vector<std::string>& joint_names, const std::string& frame,
74 const std::string& reference_frame
75) {
76 return {robot_name, joint_names, frame, Eigen::MatrixXd::Random(6, joint_names.size()), reference_frame};
77}
78
80 Jacobian tmp(jacobian);
81 swap(*this, tmp);
82 return *this;
83}
84
85unsigned int Jacobian::rows() const {
86 return 6;
87}
88
89Eigen::VectorXd Jacobian::row(unsigned int index) const {
90 return this->data().row(index);
91}
92
93unsigned int Jacobian::cols() const {
94 return this->joint_names_.size();
95}
96
97Eigen::VectorXd Jacobian::col(unsigned int index) const {
98 return this->data().col(index);
99}
100
101const std::vector<std::string>& Jacobian::get_joint_names() const {
102 return this->joint_names_;
103}
104
105const std::string& Jacobian::get_frame() const {
106 return this->frame_;
107}
108
109const std::string& Jacobian::get_reference_frame() const {
110 return this->reference_frame_;
111}
112
113const Eigen::MatrixXd& Jacobian::data() const {
114 this->assert_not_empty();
115 return this->data_;
116}
117
118void Jacobian::set_joint_names(unsigned int nb_joints) {
119 if (this->joint_names_.size() != nb_joints) {
121 "Input number of joints is of incorrect size, expected " + std::to_string(this->joint_names_.size()) + " got "
122 + std::to_string(nb_joints));
123 }
124 for (unsigned int i = 0; i < nb_joints; ++i) {
125 this->joint_names_[i] = "joint" + std::to_string(i);
126 }
127 this->reset_timestamp();
128}
129
130void Jacobian::set_joint_names(const std::vector<std::string>& joint_names) {
131 if (this->joint_names_.size() != joint_names.size()) {
133 "Input vector of joint names is of incorrect size, expected " + std::to_string(this->joint_names_.size())
134 + " got " + std::to_string(joint_names.size()));
135 }
136 this->joint_names_ = joint_names;
137 this->reset_timestamp();
138}
139
140void Jacobian::set_frame(const std::string& frame) {
141 this->frame_ = frame;
142 this->reset_timestamp();
143}
144
145void Jacobian::set_reference_frame(const std::string& reference_frame) {
146 this->reference_frame_ = reference_frame;
147 this->reset_timestamp();
148}
149
150void Jacobian::set_data(const Eigen::MatrixXd& data) {
151 assert_matrix_size(data, this->rows(), this->cols());
152 this->set_empty(false);
153 this->data_ = data;
154}
155
157 this->data_.resize(this->rows(), this->cols());
158 this->data_.setZero();
159 this->set_empty(false);
160}
161
163 Jacobian result(*this);
164 return result;
165}
166
168 this->set_zero();
169 this->State::reset();
170}
171
172Eigen::MatrixXd Jacobian::inverse() const {
173 if (this->rows() != this->cols()) {
175 "The Jacobian matrix is not invertible, use the pseudoinverse function instead");
176 }
177 return this->data().inverse();
178}
179
180Eigen::MatrixXd Jacobian::inverse(const Eigen::MatrixXd& matrix) const {
181 assert_matrix_size(matrix, this->rows(), matrix.cols());
182 return this->data().colPivHouseholderQr().solve(matrix);
183}
184
186 if (this->is_incompatible(twist)) {
187 throw IncompatibleStatesException("The Jacobian and the given Cartesian twist are incompatible");
188 }
189 return JointVelocities(this->get_name(), this->get_joint_names(), this->inverse(twist.data()));
190}
191
192bool Jacobian::is_incompatible(const State& state) const {
193 try {
194 switch (state.get_type()) {
195 case StateType::JACOBIAN: {
196 auto other = dynamic_cast<const Jacobian&>(state);
197 if (this->cols() != other.joint_names_.size()) {
198 return true;
199 }
200 if (this->reference_frame_ != other.reference_frame_) {
201 return true;
202 }
203 for (unsigned int i = 0; i < this->cols(); ++i) {
204 if (this->joint_names_[i] != other.joint_names_[i]) {
205 return true;
206 }
207 }
208 return false;
209 }
210 case StateType::JOINT_STATE:
211 case StateType::JOINT_POSITIONS:
212 case StateType::JOINT_VELOCITIES:
213 case StateType::JOINT_ACCELERATIONS:
214 case StateType::JOINT_TORQUES: {
215 auto other = dynamic_cast<const JointState&>(state);
216 if (this->cols() != other.get_names().size()) {
217 return true;
218 }
219 for (unsigned int i = 0; i < this->cols(); ++i) {
220 if (this->joint_names_[i] != other.get_names()[i]) {
221 return true;
222 }
223 }
224 return false;
225 }
226 case StateType::CARTESIAN_STATE:
227 case StateType::CARTESIAN_POSE:
228 case StateType::CARTESIAN_TWIST:
229 case StateType::CARTESIAN_ACCELERATION:
230 case StateType::CARTESIAN_WRENCH: {
231 auto other = dynamic_cast<const CartesianState&>(state);
232 if (this->reference_frame_ != other.get_reference_frame()) {
233 return true;
234 }
235 return false;
236 }
237 default:
238 return true;
239 }
240 } catch (const std::bad_cast& ex) {
241 throw exceptions::InvalidCastException(std::string("Could not cast the given object: ") + ex.what());
242 }
243}
244
245Eigen::MatrixXd Jacobian::pseudoinverse() const {
246 return this->data().completeOrthogonalDecomposition().pseudoInverse();
247}
248
249Eigen::MatrixXd Jacobian::pseudoinverse(const Eigen::MatrixXd& matrix) const {
250 assert_matrix_size(matrix, this->rows(), matrix.cols());
251 return this->pseudoinverse() * matrix;
252}
253
255 if (this->is_incompatible(twist)) {
256 throw IncompatibleStatesException("The Jacobian and the given Cartesian twist are incompatible");
257 }
258 return JointVelocities(this->get_name(), this->get_joint_names(), this->pseudoinverse(twist.data()));
259}
260
261Eigen::MatrixXd Jacobian::transpose() const {
262 return this->data().transpose();
263}
264
266 if (this->is_incompatible(wrench)) {
267 throw IncompatibleStatesException("The Jacobian and the given Cartesian wrench are incompatible");
268 }
269 return JointTorques(this->get_name(), this->get_joint_names(), this->transpose() * wrench.data());
270}
271
272Eigen::MatrixXd Jacobian::operator*(const Eigen::MatrixXd& matrix) const {
273 assert_matrix_size(matrix, this->cols(), matrix.cols());
274 return this->data() * matrix;
275}
276
277Jacobian operator*(const Eigen::Matrix<double, 6, 6>& matrix, const Jacobian& jacobian) {
278 Jacobian result(jacobian);
279 result.set_data(matrix * jacobian.data());
280 return result;
281}
282
284 if (this->is_incompatible(dq)) {
285 throw IncompatibleStatesException("The Jacobian and the input JointVelocities are incompatible");
286 }
287 Eigen::Vector<double, 6> twist = (*this) * dq.data();
288 return CartesianTwist(this->get_frame(), twist, this->get_reference_frame());
289}
290
291Jacobian operator*(const CartesianPose& pose, const Jacobian& jacobian) {
292 if (pose.get_name() != jacobian.get_reference_frame()) {
294 "The CartesianPose and the Jacobian are incompatible, expected pose of '" + jacobian.get_reference_frame()
295 + "', got '" + pose.get_name() + "'.");
296 }
297 Jacobian result(jacobian);
298 // change the reference frame of all the columns
299 for (unsigned int i = 0; i < jacobian.cols(); ++i) {
300 // update position part
301 result.data_.col(i).head(3) = pose.get_orientation() * jacobian.col(i).head(3);
302 // update orientation part
303 result.data_.col(i).tail(3) = pose.get_orientation() * jacobian.col(i).tail(3);
304 }
305 // change the reference frame
306 result.reference_frame_ = pose.get_reference_frame();
307 return result;
308}
309
310double& Jacobian::operator()(unsigned int row, unsigned int col) {
311 this->assert_not_empty();
312 if (row > this->rows()) {
313 throw std::out_of_range("Given row is out of range: number of rows is " + std::to_string(this->rows()));
314 }
315 if (col > this->cols()) {
316 throw std::out_of_range("Given column is out of range: number of columns is " + std::to_string(this->cols()));
317 }
318 this->reset_timestamp();
319 return this->data_(row, col);
320}
321
322const double& Jacobian::operator()(unsigned int row, unsigned int col) const {
323 this->assert_not_empty();
324 if (row > this->rows()) {
325 throw std::out_of_range("Given row is out of range: number of rows is " + std::to_string(this->rows()));
326 }
327 if (col > this->cols()) {
328 throw std::out_of_range("Given column is out of range: number of columns is " + std::to_string(this->cols()));
329 }
330 return this->data_(row, col);
331}
332
333std::ostream& operator<<(std::ostream& os, const Jacobian& jacobian) {
334 os << jacobian.to_string();
335 os << " associated to '" << jacobian.get_frame();
336 os << "', expressed in frame '" << jacobian.get_reference_frame() << "'" << std::endl;
337 os << "joint names: [";
338 for (auto& n : jacobian.get_joint_names()) { os << n << ", "; }
339 os << "]";
340 if (jacobian.is_empty()) {
341 return os;
342 }
343 os << std::endl;
344 os << "number of rows: " << jacobian.rows() << std::endl;
345 os << "number of columns: " << jacobian.cols() << std::endl;
346 for (unsigned int i = 0; i < jacobian.rows(); ++i) {
347 os << "| " << jacobian(i, 0);
348 for (unsigned int j = 1; j < jacobian.cols(); ++j) {
349 os << ", " << jacobian(i, j);
350 }
351 os << " |";
352 if (i != jacobian.rows() - 1) {
353 os << std::endl;
354 }
355 }
356 return os;
357}
358}// namespace state_representation
Class to define Cartesian pose in Cartesian space as 3D position and quaternion based orientation.
Class to represent a state in Cartesian space.
const Eigen::Quaterniond & get_orientation() const
Getter of the orientation attribute.
Class to define twist in Cartesian space as 3D linear and angular velocity vectors.
Eigen::VectorXd data() const override
Returns the twist data as an Eigen vector.
Class to define wrench in Cartesian space as 3D force and torque vectors.
Eigen::VectorXd data() const override
Returns the wrench data as an Eigen vector.
Class to define a robot Jacobian matrix.
Definition Jacobian.hpp:21
friend void swap(Jacobian &jacobian1, Jacobian &jacobian2)
Swap the values of the two Jacobians.
Definition Jacobian.hpp:333
Jacobian copy() const
Return a copy of the Jacobian.
Definition Jacobian.cpp:162
const std::vector< std::string > & get_joint_names() const
Getter of the joint names attribute.
Definition Jacobian.cpp:101
void reset() override
Reset the object to a post-construction state.
Definition Jacobian.cpp:167
Eigen::VectorXd row(unsigned int index) const
Accessor of the row data at given index.
Definition Jacobian.cpp:89
const Eigen::MatrixXd & data() const
Getter of the data attribute.
Definition Jacobian.cpp:113
void set_frame(const std::string &frame)
Setter of the frame.
Definition Jacobian.cpp:140
void set_zero()
Set the Jacobian matrix to a zero value.
Definition Jacobian.cpp:156
Eigen::MatrixXd pseudoinverse() const
Return the pseudoinverse of the Jacobian matrix.
Definition Jacobian.cpp:245
unsigned int cols() const
Getter of the number of columns attribute.
Definition Jacobian.cpp:93
Eigen::MatrixXd transpose() const
Return the transpose of the Jacobian matrix.
Definition Jacobian.cpp:261
const std::string & get_reference_frame() const
Getter of the reference frame attribute.
Definition Jacobian.cpp:109
unsigned int rows() const
Getter of the number of rows attribute.
Definition Jacobian.cpp:85
Eigen::MatrixXd inverse() const
Return the inverse of the Jacobian matrix.
Definition Jacobian.cpp:172
const std::string & get_frame() const
Getter of the frame attribute.
Definition Jacobian.cpp:105
friend Jacobian operator*(const Eigen::Matrix< double, 6, 6 > &matrix, const Jacobian &jacobian)
Overload the * operator with a 6x6 matrix on the left side.
Definition Jacobian.cpp:277
void set_joint_names(unsigned int nb_joints)
Setter of the joint names attribute from the number of joints.
Definition Jacobian.cpp:118
Jacobian & operator=(const Jacobian &jacobian)
Copy assignment operator that has to be defined to the custom assignment operator.
Definition Jacobian.cpp:79
bool is_incompatible(const State &state) const override
Check if the Jacobian is incompatible for operations with the state given as argument.
Definition Jacobian.cpp:192
void set_data(const Eigen::MatrixXd &data) override
Setter of the data attribute.
Definition Jacobian.cpp:150
Jacobian()
Empty constructor for a Jacobian.
Definition Jacobian.cpp:19
void set_reference_frame(const std::string &reference_frame)
Setter of the reference frame.
Definition Jacobian.cpp:145
double & operator()(unsigned int row, unsigned int col)
Overload the () operator in a non const fashion to modify the value at given (row,...
Definition Jacobian.cpp:310
Eigen::VectorXd col(unsigned int index) const
Accessor of the column data at given index.
Definition Jacobian.cpp:97
JointTorques transpose(const CartesianWrench &wrench) const
Transform a Cartesian wrench to joint space by pre-multiplying the Jacobian transpose.
Definition Jacobian.cpp:265
static Jacobian Random(const std::string &robot_name, unsigned int nb_joints, const std::string &frame, const std::string &reference_frame="world")
Constructor for a random Jacobian.
Definition Jacobian.cpp:66
Class to define a state in joint space.
Class to define torques of the joints.
Class to define velocities of the joints.
Eigen::VectorXd data() const override
Returns the velocities data as an Eigen vector.
const std::string & get_reference_frame() const
Getter of the reference frame as const reference.
Abstract class to represent a state.
Definition State.hpp:25
void reset_timestamp()
Reset the timestamp attribute to now.
Definition State.cpp:61
const std::string & get_name() const
Getter of the name attribute.
Definition State.cpp:29
void set_type(const StateType &type)
Setter of the state type attribute.
Definition State.cpp:41
virtual std::string to_string() const
Convert the state to its string representation.
Definition State.cpp:99
virtual void reset()
Reset the object to a post-construction state.
Definition State.cpp:77
void assert_not_empty() const
Throw an exception if the state is empty.
Definition State.cpp:55
bool is_empty() const
Getter of the empty attribute.
Definition State.cpp:33
void set_empty(bool empty=true)
Setter of the empty attribute.
Definition State.cpp:50
Core state variables and objects.
std::ostream & operator<<(std::ostream &os, const AnalogIOState &state)
CartesianAcceleration operator*(double lambda, const CartesianAcceleration &acceleration)