ros_filter_utilities.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, 2015, 2016, Charles River Analytics, Inc.
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
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following
13  * disclaimer in the documentation and/or other materials provided
14  * with the distribution.
15  * 3. Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
35 
37 #include <ros/console.h>
38 
39 #include <string>
40 #include <vector>
41 
42 std::ostream& operator<<(std::ostream& os, const tf2::Vector3 &vec)
43 {
44  os << "(" << std::setprecision(20) << vec.getX() << " " << vec.getY() << " " << vec.getZ() << ")\n";
45 
46  return os;
47 }
48 
49 std::ostream& operator<<(std::ostream& os, const tf2::Quaternion &quat)
50 {
51  double roll, pitch, yaw;
52  tf2::Matrix3x3 orTmp(quat);
53  orTmp.getRPY(roll, pitch, yaw);
54 
55  os << "(" << std::setprecision(20) << roll << ", " << pitch << ", " << yaw << ")\n";
56 
57  return os;
58 }
59 
60 std::ostream& operator<<(std::ostream& os, const tf2::Transform &trans)
61 {
62  os << "Origin: " << trans.getOrigin() <<
63  "Rotation (RPY): " << trans.getRotation();
64 
65  return os;
66 }
67 
68 std::ostream& operator<<(std::ostream& os, const std::vector<double> &vec)
69 {
70  os << "(" << std::setprecision(20);
71 
72  for (size_t i = 0; i < vec.size(); ++i)
73  {
74  os << vec[i] << " ";
75  }
76 
77  os << ")\n";
78 
79  return os;
80 }
81 
82 namespace RobotLocalization
83 {
84 namespace RosFilterUtilities
85 {
86 
87  double getYaw(const tf2::Quaternion quat)
88  {
89  tf2::Matrix3x3 mat(quat);
90 
91  double dummy;
92  double yaw;
93  mat.getRPY(dummy, dummy, yaw);
94 
95  return yaw;
96  }
97 
99  const std::string &targetFrame,
100  const std::string &sourceFrame,
101  const ros::Time &time,
102  const ros::Duration &timeout,
103  tf2::Transform &targetFrameTrans,
104  const bool silent)
105  {
106  bool retVal = true;
107 
108  // First try to transform the data at the requested time
109  try
110  {
111  tf2::fromMsg(buffer.lookupTransform(targetFrame, sourceFrame, time, timeout).transform,
112  targetFrameTrans);
113  }
114  catch (tf2::TransformException &ex)
115  {
116  // The issue might be that the transforms that are available are not close
117  // enough temporally to be used. In that case, just use the latest available
118  // transform and warn the user.
119  try
120  {
121  tf2::fromMsg(buffer.lookupTransform(targetFrame, sourceFrame, ros::Time(0)).transform,
122  targetFrameTrans);
123 
124  if (!silent)
125  {
126  ROS_WARN_STREAM_THROTTLE(2.0, "Transform from " << sourceFrame << " to " << targetFrame <<
127  " was unavailable for the time requested. Using latest instead.\n");
128  }
129  }
130  catch(tf2::TransformException &ex)
131  {
132  if (!silent)
133  {
134  ROS_WARN_STREAM_THROTTLE(2.0, "Could not obtain transform from " << sourceFrame <<
135  " to " << targetFrame << ". Error was " << ex.what() << "\n");
136  }
137 
138  retVal = false;
139  }
140  }
141 
142  // Transforming from a frame id to itself can fail when the tf tree isn't
143  // being broadcast (e.g., for some bag files). This is the only failure that
144  // would throw an exception, so check for this situation before giving up.
145  if (!retVal)
146  {
147  if (targetFrame == sourceFrame)
148  {
149  targetFrameTrans.setIdentity();
150  retVal = true;
151  }
152  }
153 
154  return retVal;
155  }
156 
158  const std::string &targetFrame,
159  const std::string &sourceFrame,
160  const ros::Time &time,
161  tf2::Transform &targetFrameTrans,
162  const bool silent)
163  {
164  return lookupTransformSafe(buffer, targetFrame, sourceFrame, time, ros::Duration(0), targetFrameTrans, silent);
165  }
166 
167  void quatToRPY(const tf2::Quaternion &quat, double &roll, double &pitch, double &yaw)
168  {
169  tf2::Matrix3x3 orTmp(quat);
170  orTmp.getRPY(roll, pitch, yaw);
171  }
172 
173  void stateToTF(const Eigen::VectorXd &state, tf2::Transform &stateTF)
174  {
175  stateTF.setOrigin(tf2::Vector3(state(StateMemberX),
176  state(StateMemberY),
177  state(StateMemberZ)));
178  tf2::Quaternion quat;
179  quat.setRPY(state(StateMemberRoll),
180  state(StateMemberPitch),
181  state(StateMemberYaw));
182 
183  stateTF.setRotation(quat);
184  }
185 
186  void TFtoState(const tf2::Transform &stateTF, Eigen::VectorXd &state)
187  {
188  state(StateMemberX) = stateTF.getOrigin().getX();
189  state(StateMemberY) = stateTF.getOrigin().getY();
190  state(StateMemberZ) = stateTF.getOrigin().getZ();
191  quatToRPY(stateTF.getRotation(), state(StateMemberRoll), state(StateMemberPitch), state(StateMemberYaw));
192  }
193 
194 } // namespace RosFilterUtilities
195 } // namespace RobotLocalization
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
void getRPY(tf2Scalar &roll, tf2Scalar &pitch, tf2Scalar &yaw, unsigned int solution_number=1) const
Quaternion getRotation() const
TF2SIMD_FORCE_INLINE void setRotation(const Quaternion &q)
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
void setIdentity()
void stateToTF(const Eigen::VectorXd &state, tf2::Transform &stateTF)
Converts our Eigen state vector into a TF transform/pose.
TF2SIMD_FORCE_INLINE Vector3 & getOrigin()
void fromMsg(const A &, B &b)
std::ostream & operator<<(std::ostream &os, const tf2::Vector3 &vec)
TF2SIMD_FORCE_INLINE void setOrigin(const Vector3 &origin)
#define ROS_WARN_STREAM_THROTTLE(rate, args)
bool lookupTransformSafe(const tf2_ros::Buffer &buffer, const std::string &targetFrame, const std::string &sourceFrame, const ros::Time &time, const ros::Duration &timeout, tf2::Transform &targetFrameTrans, const bool silent=false)
Method for safely obtaining transforms.
double getYaw(const tf2::Quaternion quat)
void quatToRPY(const tf2::Quaternion &quat, double &roll, double &pitch, double &yaw)
Utility method for converting quaternion to RPY.
void TFtoState(const tf2::Transform &stateTF, Eigen::VectorXd &state)
Converts a TF transform/pose into our Eigen state vector.


robot_localization
Author(s): Tom Moore
autogenerated on Wed Feb 3 2021 03:34:02