YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
Quaternion.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5
7
11#include <yarp/math/Math.h>
12#include <cmath>
13#include <cstdio>
14
15using namespace yarp::math;
16
17namespace {
18YARP_LOG_COMPONENT(QUATERNION, "yarp.math.Quaternion")
19}
20
30
32{
33 internal_data[0] = 1;
34 internal_data[1] = 0;
35 internal_data[2] = 0;
36 internal_data[3] = 0;
37}
38
39Quaternion::Quaternion(double x, double y, double z, double w)
40{
41 internal_data[0] = w;
42 internal_data[1] = x;
43 internal_data[2] = y;
44 internal_data[3] = z;
45}
46
47const double* Quaternion::data() const
48{
49 return internal_data;
50}
51
53{
54 return internal_data;
55}
56
58{
59 if (internal_data[0] == 0 &&
60 internal_data[1] == 0 &&
61 internal_data[2] == 0 &&
62 internal_data[3] == 0) {return false;}
63 return true;
64}
65
67{
69 v[0] = internal_data[0];
70 v[1] = internal_data[1];
71 v[2] = internal_data[2];
72 v[3] = internal_data[3];
73 return v;
74}
75
76double Quaternion::w() const
77{
78 return internal_data[0];
79}
80
81double Quaternion::x() const
82{
83 return internal_data[1];
84}
85
86double Quaternion::y() const
87{
88 return internal_data[2];
89}
90
91double Quaternion::z() const
92{
93 return internal_data[3];
94}
95
97{
98 return internal_data[0];
99}
100
102{
103 return internal_data[1];
104}
105
107{
108 return internal_data[2];
109}
110
112{
113 return internal_data[3];
114}
115
117{
118 // auto-convert text mode interaction
119 connection.convertTextMode();
121 bool ok = connection.expectBlock((char*)&header, sizeof(header));
122 if (!ok) {
123 return false;
124 }
125
126 if (header.listLen == 4 && header.listTag == (BOTTLE_TAG_LIST | BOTTLE_TAG_FLOAT64))
127 {
128 this->internal_data[0] = connection.expectFloat64();
129 this->internal_data[1] = connection.expectFloat64();
130 this->internal_data[2] = connection.expectFloat64();
131 this->internal_data[3] = connection.expectFloat64();
132 }
133 else
134 {
135 return false;
136 }
137
138 return !connection.isError();
139}
140
142{
144
146 header.listLen = 4;
147
148 connection.appendBlock((char*)&header, sizeof(header));
149
150 connection.appendFloat64(this->internal_data[0]);
151 connection.appendFloat64(this->internal_data[1]);
152 connection.appendFloat64(this->internal_data[2]);
153 connection.appendFloat64(this->internal_data[3]);
154
155 // if someone is foolish enough to connect in text mode,
156 // let them see something readable.
157 connection.convertTextMode();
158
159 return !connection.isError();
160}
161
163{
164 if ((R.rows()<3) || (R.cols()<3))
165 {
166 yCError(QUATERNION, "fromRotationMatrix() failed, matrix should be >= 3x3");
167 yCAssert(QUATERNION, R.rows() >= 3 && R.cols() >= 3);
168 }
169
170 double tr = R(0, 0) + R(1, 1) + R(2, 2);
171
172 if (tr>0.0)
173 {
174 double sqtrp1 = sqrt(tr + 1.0);
175 double sqtrp12 = 2.0*sqtrp1;
176 internal_data[0] = 0.5*sqtrp1;
177 internal_data[1] = (R(2, 1) - R(1, 2)) / sqtrp12;
178 internal_data[2] = (R(0, 2) - R(2, 0)) / sqtrp12;
179 internal_data[3] = (R(1, 0) - R(0, 1)) / sqtrp12;
180 }
181 else if ((R(1, 1)>R(0, 0)) && (R(1, 1)>R(2, 2)))
182 {
183 double sqdip1 = sqrt(R(1, 1) - R(0, 0) - R(2, 2) + 1.0);
184 internal_data[2] = 0.5*sqdip1;
185
186 if (sqdip1 > 0.0) {
187 sqdip1 = 0.5 / sqdip1;
188 }
189
190 internal_data[0] = (R(0, 2) - R(2, 0))*sqdip1;
191 internal_data[1] = (R(1, 0) + R(0, 1))*sqdip1;
192 internal_data[3] = (R(2, 1) + R(1, 2))*sqdip1;
193 }
194 else if (R(2, 2)>R(0, 0))
195 {
196 double sqdip1 = sqrt(R(2, 2) - R(0, 0) - R(1, 1) + 1.0);
197 internal_data[3] = 0.5*sqdip1;
198
199 if (sqdip1 > 0.0) {
200 sqdip1 = 0.5 / sqdip1;
201 }
202
203 internal_data[0] = (R(1, 0) - R(0, 1))*sqdip1;
204 internal_data[1] = (R(0, 2) + R(2, 0))*sqdip1;
205 internal_data[2] = (R(2, 1) + R(1, 2))*sqdip1;
206 }
207 else
208 {
209 double sqdip1 = sqrt(R(0, 0) - R(1, 1) - R(2, 2) + 1.0);
210 internal_data[1] = 0.5*sqdip1;
211
212 if (sqdip1 > 0.0) {
213 sqdip1 = 0.5 / sqdip1;
214 }
215
216 internal_data[0] = (R(2, 1) - R(1, 2))*sqdip1;
217 internal_data[2] = (R(1, 0) + R(0, 1))*sqdip1;
218 internal_data[3] = (R(0, 2) + R(2, 0))*sqdip1;
219 }
220}
221
223{
224 yarp::sig::Vector q = this->toVector();
225 yarp::sig::Vector qin = (1.0 / yarp::math::norm(q))*q;
226
228 R(0, 0) = qin[0] * qin[0] + qin[1] * qin[1] - qin[2] * qin[2] - qin[3] * qin[3];
229 R(1, 0) = 2.0*(qin[1] * qin[2] + qin[0] * qin[3]);
230 R(2, 0) = 2.0*(qin[1] * qin[3] - qin[0] * qin[2]);
231 R(0, 1) = 2.0*(qin[1] * qin[2] - qin[0] * qin[3]);
232 R(1, 1) = qin[0] * qin[0] - qin[1] * qin[1] + qin[2] * qin[2] - qin[3] * qin[3];
233 R(2, 1) = 2.0*(qin[2] * qin[3] + qin[0] * qin[1]);
234 R(0, 2) = 2.0*(qin[1] * qin[3] + qin[0] * qin[2]);
235 R(1, 2) = 2.0*(qin[2] * qin[3] - qin[0] * qin[1]);
236 R(2, 2) = qin[0] * qin[0] - qin[1] * qin[1] - qin[2] * qin[2] + qin[3] * qin[3];
237
238 return R;
239}
240
242{
243 yarp::sig::Vector q = this->toVector();
244 yarp::sig::Vector qin = (1.0 / yarp::math::norm(q))*q;
245
247 R(0, 0) = qin[0] * qin[0] + qin[1] * qin[1] - qin[2] * qin[2] - qin[3] * qin[3];
248 R(1, 0) = 2.0*(qin[1] * qin[2] + qin[0] * qin[3]);
249 R(2, 0) = 2.0*(qin[1] * qin[3] - qin[0] * qin[2]);
250 R(0, 1) = 2.0*(qin[1] * qin[2] - qin[0] * qin[3]);
251 R(1, 1) = qin[0] * qin[0] - qin[1] * qin[1] + qin[2] * qin[2] - qin[3] * qin[3];
252 R(2, 1) = 2.0*(qin[2] * qin[3] + qin[0] * qin[1]);
253 R(0, 2) = 2.0*(qin[1] * qin[3] + qin[0] * qin[2]);
254 R(1, 2) = 2.0*(qin[2] * qin[3] - qin[0] * qin[1]);
255 R(2, 2) = qin[0] * qin[0] - qin[1] * qin[1] - qin[2] * qin[2] + qin[3] * qin[3];
256
257 return R;
258}
259
260std::string Quaternion::toString(int precision, int width) const
261{
262 std::string ret;
263 char tmp[350];
264 if (width<0)
265 {
266 sprintf(tmp, "w=% .*lf\t", precision, internal_data[0]); ret += tmp;
267 sprintf(tmp, "x=% .*lf\t", precision, internal_data[1]); ret += tmp;
268 sprintf(tmp, "y=% .*lf\t", precision, internal_data[2]); ret += tmp;
269 sprintf(tmp, "z=% .*lf\t", precision, internal_data[3]); ret += tmp;
270 }
271 else
272 {
273 sprintf(tmp, "w=% *.*lf ", width, precision, internal_data[0]); ret += tmp;
274 sprintf(tmp, "x=% *.*lf ", width, precision, internal_data[1]); ret += tmp;
275 sprintf(tmp, "y=% *.*lf ", width, precision, internal_data[2]); ret += tmp;
276 sprintf(tmp, "z=% *.*lf ", width, precision, internal_data[3]); ret += tmp;
277 }
278
279 return ret.substr(0, ret.length() - 1);
280}
281
283{
285 Quaternion q;
287 this->internal_data[0] = q.internal_data[0];
288 this->internal_data[1] = q.internal_data[1];
289 this->internal_data[2] = q.internal_data[2];
290 this->internal_data[3] = q.internal_data[3];
291}
292
293void Quaternion::fromAxisAngle(const yarp::sig::Vector& axis, const double& angle)
294{
295 yarp::sig::Vector v = axis;
296 v.resize(4); v[4] = angle;
298 Quaternion q;
300 this->internal_data[0] = q.internal_data[0];
301 this->internal_data[1] = q.internal_data[1];
302 this->internal_data[2] = q.internal_data[2];
303 this->internal_data[3] = q.internal_data[3];
304}
305
312
314{
315 return sqrt(internal_data[0] * internal_data[0] +
316 internal_data[1] * internal_data[1] +
317 internal_data[2] * internal_data[2] +
318 internal_data[3] * internal_data[3]);
319}
320
322{
323 double length = abs();
324 internal_data[0] /= length;
325 internal_data[1] /= length;
326 internal_data[2] /= length;
327 internal_data[3] /= length;
328 return;
329}
330
332{
333 return atan2(sqrt(internal_data[1] * internal_data[1] +
334 internal_data[2] * internal_data[2] +
335 internal_data[3] * internal_data[3]),
336 internal_data[0]);
337}
338
340{
341 // w x y z
342 return Quaternion(internal_data[0], -internal_data[1], -internal_data[2], -internal_data[3]);
343}
#define BOTTLE_TAG_FLOAT64
Definition Bottle.h:25
#define BOTTLE_TAG_LIST
Definition Bottle.h:28
bool ret
yarp::os::NetInt32 listLen
yarp::os::NetInt32 listTag
void fromRotationMatrix(const yarp::sig::Matrix &R)
Converts a rotation matrix to a quaternion.
double abs()
Computes the modulus of the quaternion.
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
yarp::sig::Vector toVector() const
Converts the quaternion to a vector of length 4.
yarp::sig::Matrix toRotationMatrix3x3() const
Converts a quaternion to a rotation matrix.
Quaternion inverse() const
Computes the inverse of the quaternion.
std::string toString(int precision=-1, int width=-1) const
void normalize()
Normalizes the quaternion elements.
void fromAxisAngle(const yarp::sig::Vector &v)
Computes the quaternion from an axis-angle representation.
double arg()
Computes the argument or phase of the quaternion in radians.
yarp::sig::Matrix toRotationMatrix4x4() const
Converts a quaternion to a rotation matrix.
yarp::sig::Vector toAxisAngle()
bool isValid() const
Check if the quaternion is valid.
bool write(yarp::os::ConnectionWriter &connection) const override
Write vector to a connection.
An interface for reading from a network connection.
virtual bool expectBlock(char *data, size_t len)=0
Read a block of data from the network connection.
virtual bool convertTextMode()=0
Reads in a standard description in text mode, and converts it to a standard description in binary.
virtual bool isError() const =0
virtual yarp::conf::float64_t expectFloat64()=0
Read a 64-bit floating point number from the network connection.
An interface for writing to a network connection.
virtual bool isError() const =0
virtual bool convertTextMode()=0
Converts a standard description in binary into a textual description, if the connection is in text-mo...
virtual void appendFloat64(yarp::conf::float64_t data)=0
Send a representation of a 64-bit floating point number to the network connection.
virtual void appendBlock(const char *data, size_t len)=0
Send a block of data to the network connection.
A class for a Matrix.
Definition Matrix.h:39
size_t cols() const
Return number of columns.
Definition Matrix.h:94
size_t rows() const
Return number of rows.
Definition Matrix.h:88
void resize(size_t size) override
Resize the vector.
Definition Vector.h:221
#define yCError(component,...)
#define yCAssert(component, x)
#define YARP_LOG_COMPONENT(name,...)
yarp::sig::Matrix eye(int r, int c)
Build an identity matrix (defined in Math.h).
Definition math.cpp:586
double norm(const yarp::sig::Vector &v)
Returns the Euclidean norm of the vector (defined in Math.h).
Definition math.cpp:538
yarp::sig::Vector zeros(int s)
Creates a vector of zeros (defined in Math.h).
Definition math.cpp:576
yarp::sig::Matrix axis2dcm(const yarp::sig::Vector &v)
Returns a dcm (direction cosine matrix) rotation matrix R from axis/angle representation (defined in ...
Definition math.cpp:715
yarp::sig::Vector dcm2axis(const yarp::sig::Matrix &R)
Converts a dcm (direction cosine matrix) rotation matrix R to axis/angle representation (defined in M...
Definition math.cpp:673
std::int32_t NetInt32
Definition of the NetInt32 type.
Definition NetInt32.h:29
#define YARP_END_PACK
Ends 1 byte packing for structs/classes.
Definition system.h:193
#define YARP_BEGIN_PACK
Starts 1 byte packing for structs/classes.
Definition system.h:192