tf2_eigen  master
Eigen binding for tf2.
tf2_eigen.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Koji Terada
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  */
26 
29 #ifndef TF2_EIGEN_H
30 #define TF2_EIGEN_H
31 
32 #include <tf2/convert.h>
34 #include <Eigen/Geometry>
35 #include <geometry_msgs/msg/point_stamped.hpp>
36 #include <geometry_msgs/msg/pose_stamped.hpp>
37 #include <geometry_msgs/msg/quaternion_stamped.hpp>
38 #include <geometry_msgs/msg/twist.hpp>
39 #include <geometry_msgs/msg/point.hpp>
40 #include <geometry_msgs/msg/quaternion.hpp>
41 #include <tf2_ros/buffer.h>
42 
43 
44 namespace tf2
45 {
46 
51  inline
52  Eigen::Isometry3d transformToEigen(const geometry_msgs::msg::Transform& t) {
53  return Eigen::Isometry3d(Eigen::Translation3d(t.translation.x, t.translation.y, t.translation.z)
54  * Eigen::Quaterniond(t.rotation.w, t.rotation.x, t.rotation.y, t.rotation.z));
55 }
56 
61 inline
62 Eigen::Isometry3d transformToEigen(const geometry_msgs::msg::TransformStamped& t) {
63  return transformToEigen(t.transform);
64 }
65 
70 inline
71 geometry_msgs::msg::TransformStamped eigenToTransform(const Eigen::Affine3d& T)
72 {
73  geometry_msgs::msg::TransformStamped t;
74  t.transform.translation.x = T.translation().x();
75  t.transform.translation.y = T.translation().y();
76  t.transform.translation.z = T.translation().z();
77 
78  Eigen::Quaterniond q(T.linear()); // assuming that upper 3x3 matrix is orthonormal
79  t.transform.rotation.x = q.x();
80  t.transform.rotation.y = q.y();
81  t.transform.rotation.z = q.z();
82  t.transform.rotation.w = q.w();
83 
84  return t;
85 }
86 
91 inline
92 geometry_msgs::msg::TransformStamped eigenToTransform(const Eigen::Isometry3d& T)
93 {
94  geometry_msgs::msg::TransformStamped t;
95  t.transform.translation.x = T.translation().x();
96  t.transform.translation.y = T.translation().y();
97  t.transform.translation.z = T.translation().z();
98 
99  Eigen::Quaterniond q(T.rotation());
100  t.transform.rotation.x = q.x();
101  t.transform.rotation.y = q.y();
102  t.transform.rotation.z = q.z();
103  t.transform.rotation.w = q.w();
104 
105  return t;
106 }
107 
117 template <>
118 inline
119 void doTransform(const Eigen::Vector3d& t_in, Eigen::Vector3d& t_out, const geometry_msgs::msg::TransformStamped& transform)
120 {
121  t_out = Eigen::Vector3d(transformToEigen(transform) * t_in);
122 }
123 
129 inline
130 geometry_msgs::msg::Point toMsg(const Eigen::Vector3d& in)
131 {
132  geometry_msgs::msg::Point msg;
133  msg.x = in.x();
134  msg.y = in.y();
135  msg.z = in.z();
136  return msg;
137 }
138 
144 inline
145 void fromMsg(const geometry_msgs::msg::Point& msg, Eigen::Vector3d& out)
146 {
147  out.x() = msg.x;
148  out.y() = msg.y;
149  out.z() = msg.z;
150 }
151 
157 inline
158 geometry_msgs::msg::Vector3& toMsg(const Eigen::Vector3d& in, geometry_msgs::msg::Vector3& out)
159 {
160  out.x = in.x();
161  out.y = in.y();
162  out.z = in.z();
163  return out;
164 }
165 
171 inline
172 void fromMsg(const geometry_msgs::msg::Vector3& msg, Eigen::Vector3d& out)
173 {
174  out.x() = msg.x;
175  out.y() = msg.y;
176  out.z() = msg.z;
177 }
178 
185 template <>
186 inline
189  const geometry_msgs::msg::TransformStamped& transform) {
190  t_out = tf2::Stamped<Eigen::Vector3d>(transformToEigen(transform) * t_in,
191  tf2_ros::fromMsg(transform.header.stamp),
192  transform.header.frame_id);
193 }
194 
200 inline
201 geometry_msgs::msg::PointStamped toMsg(const tf2::Stamped<Eigen::Vector3d>& in)
202 {
203  geometry_msgs::msg::PointStamped msg;
204  msg.header.stamp = tf2_ros::toMsg(in.stamp_);
205  msg.header.frame_id = in.frame_id_;
206  msg.point = toMsg(static_cast<const Eigen::Vector3d&>(in));
207  return msg;
208 }
209 
215 inline
216 void fromMsg(const geometry_msgs::msg::PointStamped& msg, tf2::Stamped<Eigen::Vector3d>& out) {
217  out.stamp_ = tf2_ros::fromMsg(msg.header.stamp);
218  out.frame_id_ = msg.header.frame_id;
219  fromMsg(msg.point, static_cast<Eigen::Vector3d&>(out));
220 }
221 
231 template <>
232 inline
233 void doTransform(const Eigen::Affine3d& t_in,
234  Eigen::Affine3d& t_out,
235  const geometry_msgs::msg::TransformStamped& transform) {
236  t_out = Eigen::Affine3d(transformToEigen(transform) * t_in);
237 }
238 
239 template <>
240 inline
241 void doTransform(const Eigen::Isometry3d& t_in,
242  Eigen::Isometry3d& t_out,
243  const geometry_msgs::msg::TransformStamped& transform) {
244  t_out = Eigen::Isometry3d(transformToEigen(transform) * t_in);
245 }
246 
252 inline
253 geometry_msgs::msg::Quaternion toMsg(const Eigen::Quaterniond& in) {
254  geometry_msgs::msg::Quaternion msg;
255  msg.w = in.w();
256  msg.x = in.x();
257  msg.y = in.y();
258  msg.z = in.z();
259  return msg;
260 }
261 
267 inline
268 void fromMsg(const geometry_msgs::msg::Quaternion& msg, Eigen::Quaterniond& out) {
269  out = Eigen::Quaterniond(msg.w, msg.x, msg.y, msg.z);
270 }
271 
281 template<>
282 inline
283 void doTransform(const Eigen::Quaterniond& t_in,
284  Eigen::Quaterniond& t_out,
285  const geometry_msgs::msg::TransformStamped& transform) {
286  Eigen::Quaterniond t;
287  fromMsg(transform.transform.rotation, t);
288  t_out = t.inverse() * t_in * t;
289 }
290 
296 inline
297 geometry_msgs::msg::QuaternionStamped toMsg(const Stamped<Eigen::Quaterniond>& in) {
298  geometry_msgs::msg::QuaternionStamped msg;
299  msg.header.stamp = tf2_ros::toMsg(in.stamp_);
300  msg.header.frame_id = in.frame_id_;
301  msg.quaternion = toMsg(static_cast<const Eigen::Quaterniond&>(in));
302  return msg;
303 }
304 
310 inline
311 void fromMsg(const geometry_msgs::msg::QuaternionStamped& msg, Stamped<Eigen::Quaterniond>& out) {
312  out.frame_id_ = msg.header.frame_id;
313  out.stamp_ = tf2_ros::fromMsg(msg.header.stamp);
314  fromMsg(msg.quaternion, static_cast<Eigen::Quaterniond&>(out));
315 }
316 
323 template <>
324 inline
327  const geometry_msgs::msg::TransformStamped& transform) {
328  t_out.frame_id_ = transform.header.frame_id;
329  t_out.stamp_ = tf2_ros::fromMsg(transform.header.stamp);
330  doTransform(static_cast<const Eigen::Quaterniond&>(t_in), static_cast<Eigen::Quaterniond&>(t_out), transform);
331 }
332 
338 inline
339 geometry_msgs::msg::Pose toMsg(const Eigen::Affine3d& in) {
340  geometry_msgs::msg::Pose msg;
341  msg.position.x = in.translation().x();
342  msg.position.y = in.translation().y();
343  msg.position.z = in.translation().z();
344  Eigen::Quaterniond q(in.linear());
345  msg.orientation.x = q.x();
346  msg.orientation.y = q.y();
347  msg.orientation.z = q.z();
348  msg.orientation.w = q.w();
349  return msg;
350 }
351 
357 inline
358 geometry_msgs::msg::Pose toMsg(const Eigen::Isometry3d& in) {
359  geometry_msgs::msg::Pose msg;
360  msg.position.x = in.translation().x();
361  msg.position.y = in.translation().y();
362  msg.position.z = in.translation().z();
363  Eigen::Quaterniond q(in.linear());
364  msg.orientation.x = q.x();
365  msg.orientation.y = q.y();
366  msg.orientation.z = q.z();
367  msg.orientation.w = q.w();
368  return msg;
369 }
370 
378 inline
379 geometry_msgs::msg::Vector3 toMsg2(const Eigen::Vector3d& in) {
380  geometry_msgs::msg::Vector3 msg;
381  msg.x = in(0);
382  msg.y = in(1);
383  msg.z = in(2);
384  return msg;
385 }
386 
392 inline
393 void fromMsg(const geometry_msgs::msg::Pose& msg, Eigen::Affine3d& out) {
394  out = Eigen::Affine3d(
395  Eigen::Translation3d(msg.position.x, msg.position.y, msg.position.z) *
396  Eigen::Quaterniond(msg.orientation.w,
397  msg.orientation.x,
398  msg.orientation.y,
399  msg.orientation.z));
400 }
401 
407 inline
408 void fromMsg(const geometry_msgs::msg::Pose& msg, Eigen::Isometry3d& out) {
409  out = Eigen::Isometry3d(
410  Eigen::Translation3d(msg.position.x, msg.position.y, msg.position.z) *
411  Eigen::Quaterniond(msg.orientation.w,
412  msg.orientation.x,
413  msg.orientation.y,
414  msg.orientation.z));
415 }
416 
422 inline
423 geometry_msgs::msg::Twist toMsg(const Eigen::Matrix<double,6,1>& in) {
424  geometry_msgs::msg::Twist msg;
425  msg.linear.x = in[0];
426  msg.linear.y = in[1];
427  msg.linear.z = in[2];
428  msg.angular.x = in[3];
429  msg.angular.y = in[4];
430  msg.angular.z = in[5];
431  return msg;
432 }
433 
439 inline
440 void fromMsg(const geometry_msgs::msg::Twist &msg, Eigen::Matrix<double,6,1>& out) {
441  out[0] = msg.linear.x;
442  out[1] = msg.linear.y;
443  out[2] = msg.linear.z;
444  out[3] = msg.angular.x;
445  out[4] = msg.angular.y;
446  out[5] = msg.angular.z;
447 }
448 
458 template <>
459 inline
462  const geometry_msgs::msg::TransformStamped& transform) {
463  t_out = tf2::Stamped<Eigen::Affine3d>(transformToEigen(transform) * t_in, tf2_ros::fromMsg(transform.header.stamp), transform.header.frame_id);
464 }
465 
475 template <>
476 inline
479  const geometry_msgs::msg::TransformStamped& transform) {
480  t_out = tf2::Stamped<Eigen::Isometry3d>(transformToEigen(transform) * t_in, tf2_ros::fromMsg(transform.header.stamp), transform.header.frame_id);
481 }
482 
488 inline
489 geometry_msgs::msg::PoseStamped toMsg(const tf2::Stamped<Eigen::Affine3d>& in)
490 {
491  geometry_msgs::msg::PoseStamped msg;
492  msg.header.stamp = tf2_ros::toMsg(in.stamp_);
493  msg.header.frame_id = in.frame_id_;
494  msg.pose = toMsg(static_cast<const Eigen::Affine3d&>(in));
495  return msg;
496 }
497 
498 inline
499 geometry_msgs::msg::PoseStamped toMsg(const tf2::Stamped<Eigen::Isometry3d>& in)
500 {
501  geometry_msgs::msg::PoseStamped msg;
502  msg.header.stamp = tf2_ros::toMsg(in.stamp_);
503  msg.header.frame_id = in.frame_id_;
504  msg.pose = toMsg(static_cast<const Eigen::Isometry3d&>(in));
505  return msg;
506 }
507 
513 inline
514 void fromMsg(const geometry_msgs::msg::PoseStamped& msg, tf2::Stamped<Eigen::Affine3d>& out)
515 {
516  out.stamp_ = tf2_ros::fromMsg(msg.header.stamp);
517  out.frame_id_ = msg.header.frame_id;
518  fromMsg(msg.pose, static_cast<Eigen::Affine3d&>(out));
519 }
520 
521 inline
522 void fromMsg(const geometry_msgs::msg::PoseStamped& msg, tf2::Stamped<Eigen::Isometry3d>& out)
523 {
524  out.stamp_ = tf2_ros::fromMsg(msg.header.stamp);
525  out.frame_id_ = msg.header.frame_id;
526  fromMsg(msg.pose, static_cast<Eigen::Isometry3d&>(out));
527 }
528 
529 } // namespace
530 
531 
532 namespace Eigen {
533 // This is needed to make the usage of the following conversion functions usable in tf2::convert().
534 // According to clangs error note 'fromMsg'/'toMsg' should be declared prior to the call site or
535 // in an associated namespace of one of its arguments. The stamped versions of this conversion
536 // functions work because they have tf2::Stamped as an argument which is the same namespace as
537 // which 'fromMsg'/'toMsg' is defined in. The non-stamped versions have no argument which is
538 // defined in tf2, so it take the following definitions in Eigen namespace to make them usable in
539 // tf2::convert().
540 
541 inline
542 geometry_msgs::msg::Pose toMsg(const Eigen::Affine3d& in) {
543  return tf2::toMsg(in);
544 }
545 
546 inline
547 geometry_msgs::msg::Pose toMsg(const Eigen::Isometry3d& in) {
548  return tf2::toMsg(in);
549 }
550 
551 inline
552 void fromMsg(const geometry_msgs::msg::Point& msg, Eigen::Vector3d& out) {
553  tf2::fromMsg(msg, out);
554 }
555 
556 inline
557 geometry_msgs::msg::Point toMsg(const Eigen::Vector3d& in) {
558  return tf2::toMsg(in);
559 }
560 
561 inline
562 void fromMsg(const geometry_msgs::msg::Pose& msg, Eigen::Affine3d& out) {
563  tf2::fromMsg(msg, out);
564 }
565 
566 inline
567 void fromMsg(const geometry_msgs::msg::Pose& msg, Eigen::Isometry3d& out) {
568  tf2::fromMsg(msg, out);
569 }
570 
571 inline
572 geometry_msgs::msg::Quaternion toMsg(const Eigen::Quaterniond& in) {
573  return tf2::toMsg(in);
574 }
575 
576 inline
577 geometry_msgs::msg::Twist toMsg(const Eigen::Matrix<double,6,1>& in) {
578  return tf2::toMsg(in);
579 }
580 
581 inline
582 void fromMsg(const geometry_msgs::msg::Twist &msg, Eigen::Matrix<double,6,1>& out) {
583  tf2::fromMsg(msg, out);
584 }
585 
586 } // namespace
587 
588 #endif // TF2_EIGEN_H
Eigen
Definition: tf2_eigen.h:532
tf2::toMsg2
geometry_msgs::msg::Vector3 toMsg2(const Eigen::Vector3d &in)
Convert a Eigen::Vector3d type to a geometry_msgs::msg::Vector3. This function is a specialization of...
Definition: tf2_eigen.h:379
tf2::Stamped::stamp_
TimePoint stamp_
tf2::fromMsg
void fromMsg(const A &, B &b)
buffer.h
tf2::Stamped
Eigen::fromMsg
void fromMsg(const geometry_msgs::msg::Point &msg, Eigen::Vector3d &out)
Definition: tf2_eigen.h:552
tf2::Stamped::frame_id_
std::string frame_id_
Eigen::toMsg
geometry_msgs::msg::Pose toMsg(const Eigen::Affine3d &in)
Definition: tf2_eigen.h:542
tf2::eigenToTransform
geometry_msgs::msg::TransformStamped eigenToTransform(const Eigen::Affine3d &T)
Convert an Eigen Affine3d transform to the equivalent geometry_msgs message type.
Definition: tf2_eigen.h:71
tf2_ros::fromMsg
tf2::TimePoint fromMsg(const builtin_interfaces::msg::Time &time_msg)
tf2::transformToEigen
Eigen::Isometry3d transformToEigen(const geometry_msgs::msg::Transform &t)
Convert a timestamped transform to the equivalent Eigen data type.
Definition: tf2_eigen.h:52
tf2
tf2::toMsg
B toMsg(const A &a)
convert.h
tf2::doTransform
void doTransform(const T &data_in, T &data_out, const geometry_msgs::msg::TransformStamped &transform)
tf2_ros::toMsg
builtin_interfaces::msg::Time toMsg(const tf2::TimePoint &t)
buffer_interface.h