8#include "TinyRobotics/coordinates/Coordinates.h"
9#include "TinyRobotics/utils/Common.h"
10#include "TinyRobotics/utils/LoggerClass.h"
12namespace tinyrobotics {
15
16
17
19 float tx = 0, ty = 0, tz = 0;
20 float qx = 0, qy = 0, qz = 0, qw = 1;
22 static Transform3D identity() {
return {}; }
25 Transform3D operator*(
const Transform3D& other)
const {
28 r.qw = qw * other.qw - qx * other.qx - qy * other.qy - qz * other.qz;
29 r.qx = qw * other.qx + qx * other.qw + qy * other.qz - qz * other.qy;
30 r.qy = qw * other.qy - qx * other.qz + qy * other.qw + qz * other.qx;
31 r.qz = qw * other.qz + qx * other.qy - qy * other.qx + qz * other.qw;
34 float x = other.tx, y = other.ty, z = other.tz;
35 float ix = qw * x + qy * z - qz * y;
36 float iy = qw * y + qz * x - qx * z;
37 float iz = qw * z + qx * y - qy * x;
38 float iw = -qx * x - qy * y - qz * z;
39 r.tx = tx + (ix * qw + iw * -qx + iy * -qz - iz * -qy);
40 r.ty = ty + (iy * qw + iw * -qy + iz * -qx - ix * -qz);
41 r.tz = tz + (iz * qw + iw * -qz + ix * -qy - iy * -qx);
47 Transform3D inverse()
const {
55 float x = -tx, y = -ty, z = -tz;
56 float ix = r.qw * x + r.qy * z - r.qz * y;
57 float iy = r.qw * y + r.qz * x - r.qx * z;
58 float iz = r.qw * z + r.qx * y - r.qy * x;
59 float iw = -r.qx * x - r.qy * y - r.qz * z;
60 r.tx = (ix * r.qw + iw * -r.qx + iy * -r.qz - iz * -r.qy);
61 r.ty = (iy * r.qw + iw * -r.qy + iz * -r.qx - ix * -r.qz);
62 r.tz = (iz * r.qw + iw * -r.qz + ix * -qy - iy * -qx);
67
68
69
70
71
72 std::array<
float, 3> apply(
const std::array<
float, 3>& point)
const {
74 float x = point[0], y = point[1], z = point[2];
76 float qx2 = qx + qx, qy2 = qy + qy, qz2 = qz + qz;
77 float xx = qx * qx2, yy = qy * qy2, zz = qz * qz2;
78 float xy = qx * qy2, xz = qx * qz2, yz = qy * qz2;
79 float wx = qw * qx2, wy = qw * qy2, wz = qw * qz2;
80 float rx = (1 - (yy + zz)) * x + (xy - wz) * y + (xz + wy) * z;
81 float ry = (xy + wz) * x + (1 - (xx + zz)) * y + (yz - wx) * z;
82 float rz = (xz - wy) * x + (yz + wx) * y + (1 - (xx + yy)) * z;
83 return {rx + tx, ry + ty, rz + tz};
88
89
90
91
92
93
94
95
96
99 Frame3D(FrameType type,
int index = 0, Frame3D* parent =
nullptr,
100 const Transform3D& tf = Transform3D::identity())
101 : type(type), index(index), parent(parent), tf(tf) {}
103 void setParent(Frame3D* p) { parent = p; }
104 void setTransform(
const Transform3D& t) { tf = t; }
105 Frame3D* getParent()
const {
return parent; }
106 const Transform3D& getTransform()
const {
return tf; }
107 FrameType getType()
const {
return type; }
108 int getIndex()
const {
return index; }
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
144 Transform3D getTransform(
const Frame3D& from,
const Frame3D& to)
const {
145 std::vector<
const Frame3D*> fromPath = getPathToRoot(&from);
146 std::vector<
const Frame3D*> toPath = getPathToRoot(&to);
149 int i = fromPath.size() - 1;
150 int j = toPath.size() - 1;
151 while (i >= 0 && j >= 0 && fromPath[i] == toPath[j]) {
159 Transform3D tf_from = Transform3D::identity();
160 for (
int k = 0; k < i; ++k) {
161 tf_from = fromPath[k]->getTransform() * tf_from;
164 Transform3D tf_to = Transform3D::identity();
165 for (
int k = 0; k < j; ++k) {
166 tf_to = toPath[k]->getTransform() * tf_to;
169 return tf_to.inverse() * tf_from;
174 Frame3D* p_gpsParent =
nullptr;
175 GPSCoordinate gpsCoordinate;
176 float gpsRotationDeg = 0.0f;
180
181
182
183
184
185 void setGPS(Frame3D& gpsParent,
const GPSCoordinate& gps,
186 float rotationDeg = 0.0f) {
187 p_gpsParent = &gpsParent;
189 gpsRotationDeg = rotationDeg;
193
194
195
196
197
198 GPSCoordinate toGPS(
const Frame3D& frame,
199 const std::array<
float, 3>& local)
const {
200 if (!p_gpsParent)
return gpsCoordinate;
202 Transform3D tf = getTransform(frame, *p_gpsParent);
205 std::array<
float, 3> xyz = tf.apply(local);
207 float theta_rad = gpsRotationDeg *
static_cast<
float>(M_PI) / 180.0f;
208 float cos_theta = std::cos(theta_rad);
209 float sin_theta = std::sin(theta_rad);
210 float dx = cos_theta * xyz[0] - sin_theta * xyz[1];
211 float dy = sin_theta * xyz[0] + cos_theta * xyz[1];
215 float distance = std::sqrt(dx * dx + dy * dy);
216 float bearing_deg = std::atan2(dx, dy) * 180.0f /
static_cast<
float>(M_PI);
217 bearing_deg = normalizeAngleDeg(bearing_deg);
218 return gpsCoordinate.navigate(distance, bearing_deg, dz);
223 std::vector<
const Frame3D*> getPathToRoot(
const Frame3D* frame)
const {
224 std::vector<
const Frame3D*> path;
226 path.push_back(frame);
227 frame = frame->getParent();