YARP
Yet Another Robot Platform
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 
6 #include <yarp/math/Quaternion.h>
7 
10 #include <yarp/os/LogComponent.h>
11 #include <yarp/math/Math.h>
12 #include <cmath>
13 #include <cstdio>
14 
15 using namespace yarp::math;
16 
17 namespace {
18 YARP_LOG_COMPONENT(QUATERNION, "yarp.math.Quaternion")
19 }
20 
23 {
24 public:
25  yarp::os::NetInt32 listTag{0};
26  yarp::os::NetInt32 listLen{0};
28 };
30 
32 {
33  internal_data[0] = 1;
34  internal_data[1] = 0;
35  internal_data[2] = 0;
36  internal_data[3] = 0;
37 }
38 
39 Quaternion::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 
47 const double* Quaternion::data() const
48 {
49  return internal_data;
50 }
51 
53 {
54  return internal_data;
55 }
56 
57 bool Quaternion::isValid() const
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 {
68  yarp::sig::Vector v(4);
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 
76 double Quaternion::w() const
77 {
78  return internal_data[0];
79 }
80 
81 double Quaternion::x() const
82 {
83  return internal_data[1];
84 }
85 
86 double Quaternion::y() const
87 {
88  return internal_data[2];
89 }
90 
91 double Quaternion::z() const
92 {
93  return internal_data[3];
94 }
95 
96 double& Quaternion::w()
97 {
98  return internal_data[0];
99 }
100 
101 double& Quaternion::x()
102 {
103  return internal_data[1];
104 }
105 
106 double& Quaternion::y()
107 {
108  return internal_data[2];
109 }
110 
111 double& Quaternion::z()
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 
260 std::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;
286  q.fromRotationMatrix(m);
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 
293 void 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;
299  q.fromRotationMatrix(m);
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 
307 {
310  return v;
311 }
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
Definition: Quaternion.cpp:26
yarp::os::NetInt32 listTag
Definition: Quaternion.cpp:25
void fromRotationMatrix(const yarp::sig::Matrix &R)
Converts a rotation matrix to a quaternion.
Definition: Quaternion.cpp:162
double abs()
Computes the modulus of the quaternion.
Definition: Quaternion.cpp:313
double x() const
Definition: Quaternion.cpp:81
bool read(yarp::os::ConnectionReader &connection) override
Read this object from a network connection.
Definition: Quaternion.cpp:116
yarp::sig::Vector toVector() const
Converts the quaternion to a vector of length 4.
Definition: Quaternion.cpp:66
yarp::sig::Matrix toRotationMatrix3x3() const
Converts a quaternion to a rotation matrix.
Definition: Quaternion.cpp:241
Quaternion inverse() const
Computes the inverse of the quaternion.
Definition: Quaternion.cpp:339
std::string toString(int precision=-1, int width=-1) const
Definition: Quaternion.cpp:260
void normalize()
Normalizes the quaternion elements.
Definition: Quaternion.cpp:321
void fromAxisAngle(const yarp::sig::Vector &v)
Computes the quaternion from an axis-angle representation.
Definition: Quaternion.cpp:282
double arg()
Computes the argument or phase of the quaternion in radians.
Definition: Quaternion.cpp:331
yarp::sig::Matrix toRotationMatrix4x4() const
Converts a quaternion to a rotation matrix.
Definition: Quaternion.cpp:222
double z() const
Definition: Quaternion.cpp:91
double w() const
Definition: Quaternion.cpp:76
yarp::sig::Vector toAxisAngle()
Definition: Quaternion.cpp:306
bool isValid() const
Check if the quaternion is valid.
Definition: Quaternion.cpp:57
bool write(yarp::os::ConnectionWriter &connection) const override
Write vector to a connection.
Definition: Quaternion.cpp:141
double y() const
Definition: Quaternion.cpp:86
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:43
size_t cols() const
Return number of columns.
Definition: Matrix.h:98
size_t rows() const
Return number of rows.
Definition: Matrix.h:92
void resize(size_t size) override
Resize the vector.
Definition: Vector.h:222
#define yCError(component,...)
Definition: LogComponent.h:154
#define yCAssert(component, x)
Definition: LogComponent.h:169
#define YARP_LOG_COMPONENT(name,...)
Definition: LogComponent.h:77
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:30
#define YARP_END_PACK
Ends 1 byte packing for structs/classes.
Definition: system.h:191
#define YARP_BEGIN_PACK
Starts 1 byte packing for structs/classes.
Definition: system.h:190