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