ftf_frame_conversions.cpp
Go to the documentation of this file.
1 
10 /*
11  * Copyright 2015 Nuno Marques.
12  * Copyright 2016 Vladimir Ermakov
13  *
14  * This file is part of the mavros package and subject to the license terms
15  * in the top-level LICENSE file of the mavros repository.
16  * https://github.com/mavlink/mavros/tree/master/LICENSE.md
17  */
18 
19 #include <mavros/frame_tf.h>
20 #include <stdexcept>
21 
22 namespace mavros {
23 namespace ftf {
24 namespace detail {
30 static const auto NED_ENU_Q = quaternion_from_rpy(M_PI, 0.0, M_PI_2);
31 
37 static const auto AIRCRAFT_BASELINK_Q = quaternion_from_rpy(M_PI, 0.0, 0.0);
38 
45 static const Eigen::Affine3d NED_ENU_AFFINE(NED_ENU_Q);
46 
52 static const Eigen::Affine3d AIRCRAFT_BASELINK_AFFINE(AIRCRAFT_BASELINK_Q);
53 
57 static const auto NED_ENU_R = NED_ENU_Q.normalized().toRotationMatrix();
58 static const auto AIRCRAFT_BASELINK_R = AIRCRAFT_BASELINK_Q.normalized().toRotationMatrix();
59 
65 static const Eigen::PermutationMatrix<3> NED_ENU_REFLECTION_XY(Eigen::Vector3i(1,0,2));
66 static const Eigen::DiagonalMatrix<double,3> NED_ENU_REFLECTION_Z(1,1,-1);
67 
71 using Matrix6d = Eigen::Matrix<double, 6, 6>;
72 using Matrix9d = Eigen::Matrix<double, 9, 9>;
73 
74 
75 Eigen::Quaterniond transform_orientation(const Eigen::Quaterniond &q, const StaticTF transform)
76 {
77  // Transform the attitude representation from frame to frame.
78  // The proof for this transform can be seen
79  // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/transforms/
80  switch (transform) {
83  return NED_ENU_Q * q;
84 
87  return q * AIRCRAFT_BASELINK_Q;
88 
91  return AIRCRAFT_BASELINK_Q * q;
92 
93  default:
94  ROS_FATAL("unsupported StaticTF mode");
95  return q;
96  }
97 }
98 
99 
100 Eigen::Vector3d transform_static_frame(const Eigen::Vector3d &vec, const StaticTF transform)
101 {
102  switch (transform) {
106 
109  return AIRCRAFT_BASELINK_AFFINE * vec;
110 
111  default:
112  ROS_FATAL("unsupported StaticTF mode");
113  return vec;
114  }
115 }
116 
118 {
119  Covariance3d cov_out_;
120  EigenMapConstCovariance3d cov_in(cov.data());
121  EigenMapCovariance3d cov_out(cov_out_.data());
122 
123  switch (transform) {
127  NED_ENU_REFLECTION_XY.transpose();
128  return cov_out_;
129 
132  cov_out = cov_in * AIRCRAFT_BASELINK_Q;
133  return cov_out_;
134 
135  default:
136  ROS_FATAL("unsupported StaticTF mode");
137  return cov;
138  }
139 }
140 
142 {
143  Covariance6d cov_out_;
144  Matrix6d R = Matrix6d::Zero(); // not `auto` because Zero ret is const
145 
146  EigenMapConstCovariance6d cov_in(cov.data());
147  EigenMapCovariance6d cov_out(cov_out_.data());
148 
149  switch (transform) {
152  {
153  Eigen::PermutationMatrix<6> NED_ENU_REFLECTION_XY_6 (NED_ENU_REFLECTION_XY.indices().replicate<2,1>());
154  NED_ENU_REFLECTION_XY_6.indices().middleRows<3>(3).array() += 3;
155  Eigen::DiagonalMatrix<double,6> NED_ENU_REFLECTION_Z_6(NED_ENU_REFLECTION_Z.diagonal().replicate<2,1>());
156 
157  cov_out = NED_ENU_REFLECTION_XY_6 * (NED_ENU_REFLECTION_Z_6 * cov_in * NED_ENU_REFLECTION_Z_6) *
158  NED_ENU_REFLECTION_XY_6.transpose();
159 
160  return cov_out_;
161  }
164  R.block<3, 3>(0, 0) =
165  R.block<3, 3>(3, 3) = AIRCRAFT_BASELINK_R;
166 
167  cov_out = R * cov_in * R.transpose();
168  return cov_out_;
169 
170  default:
171  ROS_FATAL("unsupported StaticTF mode");
172  return cov;
173  }
174 }
175 
177 {
178  Covariance9d cov_out_;
179  Matrix9d R = Matrix9d::Zero();
180 
181  EigenMapConstCovariance9d cov_in(cov.data());
182  EigenMapCovariance9d cov_out(cov_out_.data());
183 
184  switch (transform) {
187  {
188  Eigen::PermutationMatrix<9> NED_ENU_REFLECTION_XY_9 (NED_ENU_REFLECTION_XY.indices().replicate<3,1>());
189  NED_ENU_REFLECTION_XY_9.indices().middleRows<3>(3).array() += 3;
190  NED_ENU_REFLECTION_XY_9.indices().middleRows<3>(6).array() += 6;
191  Eigen::DiagonalMatrix<double,9> NED_ENU_REFLECTION_Z_9(NED_ENU_REFLECTION_Z.diagonal().replicate<3,1>());
192 
193  cov_out = NED_ENU_REFLECTION_XY_9 * (NED_ENU_REFLECTION_Z_9 * cov_in * NED_ENU_REFLECTION_Z_9) *
194  NED_ENU_REFLECTION_XY_9.transpose();
195 
196  return cov_out_;
197  }
200  R.block<3, 3>(0, 0) =
201  R.block<3, 3>(3, 3) =
202  R.block<3, 3>(6, 6) = AIRCRAFT_BASELINK_R;
203 
204  cov_out = R * cov_in * R.transpose();
205  return cov_out_;
206 
207  default:
208  ROS_FATAL("unsupported StaticTF mode");
209  return cov;
210  }
211 }
212 
213 Eigen::Vector3d transform_static_frame(const Eigen::Vector3d &vec, const Eigen::Vector3d &map_origin, const StaticEcefTF transform)
214 {
216  static constexpr double DEG_TO_RAD = (M_PI / 180.0);
217 
218  // Don't forget to convert from degrees to radians
219  const double sin_lat = std::sin(map_origin.x() * DEG_TO_RAD);
220  const double sin_lon = std::sin(map_origin.y() * DEG_TO_RAD);
221  const double cos_lat = std::cos(map_origin.x() * DEG_TO_RAD);
222  const double cos_lon = std::cos(map_origin.y() * DEG_TO_RAD);
223 
238  Eigen::Matrix3d R;
239  R << -sin_lon, cos_lon, 0.0,
240  -cos_lon * sin_lat, -sin_lon * sin_lat, cos_lat,
241  cos_lon * cos_lat, sin_lon * cos_lat, sin_lat;
242 
243  switch (transform) {
245  return R * vec;
246 
248  // ENU to ECEF rotation is just an inverse rotation from ECEF to ENU, which means transpose.
249  R.transposeInPlace();
250  return R * vec;
251 
252  default:
253  ROS_FATAL("unsupported StaticTF mode");
254  return vec;
255  }
256 }
257 
258 Eigen::Vector3d transform_frame(const Eigen::Vector3d &vec, const Eigen::Quaterniond &q)
259 {
260  Eigen::Affine3d transformation(q);
261  return transformation * vec;
262 }
263 
264 Covariance3d transform_frame(const Covariance3d &cov, const Eigen::Quaterniond &q)
265 {
266  Covariance3d cov_out_;
267  EigenMapConstCovariance3d cov_in(cov.data());
268  EigenMapCovariance3d cov_out(cov_out_.data());
269 
270  cov_out = cov_in * q;
271  return cov_out_;
272 }
273 
274 Covariance6d transform_frame(const Covariance6d &cov, const Eigen::Quaterniond &q)
275 {
276  Covariance6d cov_out_;
277  Matrix6d R = Matrix6d::Zero();
278 
279  EigenMapConstCovariance6d cov_in(cov.data());
280  EigenMapCovariance6d cov_out(cov_out_.data());
281 
282  R.block<3, 3>(0, 0) =
283  R.block<3, 3>(3, 3) = q.normalized().toRotationMatrix();
284 
285  cov_out = R * cov_in * R.transpose();
286  return cov_out_;
287 }
288 
289 Covariance9d transform_frame(const Covariance9d &cov, const Eigen::Quaterniond &q)
290 {
291  Covariance9d cov_out_;
292  Matrix9d R = Matrix9d::Zero();
293 
294  EigenMapConstCovariance9d cov_in(cov.data());
295  EigenMapCovariance9d cov_out(cov_out_.data());
296 
297  R.block<3, 3>(0, 0) =
298  R.block<3, 3>(3, 3) =
299  R.block<3, 3>(6, 6) = q.normalized().toRotationMatrix();
300 
301  cov_out = R * cov_in * R.transpose();
302  return cov_out_;
303 }
304 
305 } // namespace detail
306 } // namespace ftf
307 } // namespace mavros
change orientation from being expressed in baselink frame to aircraft frame in an absolute frame of r...
change from expressed WRT ENU frame to WRT ECEF frame
#define ROS_FATAL(...)
will change orientation from being expressed WRT NED frame to WRT ENU frame
StaticEcefTF
Orientation transform options when applying rotations to data, for ECEF.
Definition: frame_tf.h:72
static const auto NED_ENU_Q
Static quaternion needed for rotating between ENU and NED frames NED to ENU: +PI/2 rotation about Z (...
static const Eigen::Affine3d NED_ENU_AFFINE(NED_ENU_Q)
Static vector needed for rotating between ENU and NED frames +PI rotation around X (North) axis follw...
StaticTF
Orientation transform options when applying rotations to data.
Definition: frame_tf.h:60
Eigen::Map< Eigen::Matrix< double, 6, 6, Eigen::RowMajor > > EigenMapCovariance6d
Eigen::Map for Covariance6d.
Definition: frame_tf.h:50
Eigen::Map< const Eigen::Matrix< double, 3, 3, Eigen::RowMajor > > EigenMapConstCovariance3d
Definition: frame_tf.h:47
Eigen::Quaterniond transform_orientation(const Eigen::Quaterniond &q, const StaticTF transform)
Transform representation of attitude from 1 frame to another (e.g. transfrom attitude from representi...
static const Eigen::DiagonalMatrix< double, 3 > NED_ENU_REFLECTION_Z(1, 1,-1)
Eigen::Vector3d transform_static_frame(const Eigen::Vector3d &vec, const StaticTF transform)
Transform data expressed in one frame to another frame.
Eigen::Matrix< double, 9, 9 > Matrix9d
static const Eigen::PermutationMatrix< 3 > NED_ENU_REFLECTION_XY(Eigen::Vector3i(1, 0, 2))
Use reflections instead of rotations for NED <-> ENU transformation to avoid NaN/Inf floating point p...
Eigen::Vector3d transform_frame(const Eigen::Vector3d &vec, const Eigen::Quaterniond &q)
Transform data expressed in one frame to another frame.
change from expressed WRT aircraft frame to WRT to baselink frame
static const auto AIRCRAFT_BASELINK_R
static const Eigen::Affine3d AIRCRAFT_BASELINK_AFFINE(AIRCRAFT_BASELINK_Q)
Static vector needed for rotating between aircraft and base_link frames +PI rotation around X (Forwar...
Eigen::Map< Eigen::Matrix< double, 9, 9, Eigen::RowMajor > > EigenMapCovariance9d
Eigen::Map for Covariance9d.
Definition: frame_tf.h:54
geometry_msgs::PoseWithCovariance::_covariance_type Covariance6d
Type matching rosmsg for 6x6 covariance matrix.
Definition: frame_tf.h:40
boost::array< double, 81 > Covariance9d
Type matching rosmsg for 9x9 covariance matrix.
Definition: frame_tf.h:43
change orientation from being expressed in aircraft frame to baselink frame in an absolute frame of r...
Eigen::Map< Eigen::Matrix< double, 3, 3, Eigen::RowMajor > > EigenMapCovariance3d
Eigen::Map for Covariance3d.
Definition: frame_tf.h:46
Eigen::Matrix< double, 6, 6 > Matrix6d
Auxiliar matrices to Covariance transforms.
sensor_msgs::Imu::_angular_velocity_covariance_type Covariance3d
Type matching rosmsg for 3x3 covariance matrix.
Definition: frame_tf.h:37
Eigen::Quaterniond quaternion_from_rpy(const Eigen::Vector3d &rpy)
Convert euler angles to quaternion.
change from expressed WRT baselnk to WRT aircraft
static const auto AIRCRAFT_BASELINK_Q
Static quaternion needed for rotating between aircraft and base_link frames +PI rotation around X (Fo...
change from expressed WRT ECEF frame to WRT ENU frame
static const auto NED_ENU_R
3-D matrices to fill 6-D rotation matrix applied to change covariance matrices coordinate frames ...
Eigen::Map< const Eigen::Matrix< double, 9, 9, Eigen::RowMajor > > EigenMapConstCovariance9d
Definition: frame_tf.h:55
Frame transformation utilities.
Eigen::Map< const Eigen::Matrix< double, 6, 6, Eigen::RowMajor > > EigenMapConstCovariance6d
Definition: frame_tf.h:51
change from expressed WRT ENU frame to WRT NED frame


mavros
Author(s): Vladimir Ermakov
autogenerated on Tue Jun 13 2023 02:17:50