ros_filter_utilities.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2014, 2015, 2016, Charles River Analytics, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  * notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above
00012  * copyright notice, this list of conditions and the following
00013  * disclaimer in the documentation and/or other materials provided
00014  * with the distribution.
00015  * 3. Neither the name of the copyright holder nor the names of its
00016  * contributors may be used to endorse or promote products derived
00017  * from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00026  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00027  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00028  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00029  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00030  * POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #include "robot_localization/ros_filter_utilities.h"
00034 #include "robot_localization/filter_common.h"
00035 
00036 #include <tf2_geometry_msgs/tf2_geometry_msgs.h>
00037 #include <ros/console.h>
00038 
00039 #include <string>
00040 
00041 std::ostream& operator<<(std::ostream& os, const tf2::Vector3 &vec)
00042 {
00043   os << "(" << std::setprecision(20) << vec.getX() << " " << vec.getY() << " " << vec.getZ() << ")\n";
00044 
00045   return os;
00046 }
00047 
00048 std::ostream& operator<<(std::ostream& os, const tf2::Quaternion &quat)
00049 {
00050   double roll, pitch, yaw;
00051   tf2::Matrix3x3 orTmp(quat);
00052   orTmp.getRPY(roll, pitch, yaw);
00053 
00054   os << "(" << std::setprecision(20) << roll << ", " << pitch << ", " << yaw << ")\n";
00055 
00056   return os;
00057 }
00058 
00059 std::ostream& operator<<(std::ostream& os, const tf2::Transform &trans)
00060 {
00061   os << "Origin: " << trans.getOrigin() <<
00062         "Rotation (RPY): " << trans.getRotation();
00063 
00064   return os;
00065 }
00066 
00067 std::ostream& operator<<(std::ostream& os, const std::vector<double> &vec)
00068 {
00069   os << "(" << std::setprecision(20);
00070 
00071   for(size_t i = 0; i < vec.size(); ++i)
00072   {
00073     os << vec[i] << " ";
00074   }
00075 
00076   os << ")\n";
00077 
00078   return os;
00079 }
00080 
00081 namespace RobotLocalization
00082 {
00083 namespace RosFilterUtilities
00084 {
00085 
00086   double getYaw(const tf2::Quaternion quat)
00087   {
00088     tf2::Matrix3x3 mat(quat);
00089 
00090     double dummy;
00091     double yaw;
00092     mat.getRPY(dummy, dummy, yaw);
00093 
00094     return yaw;
00095   }
00096 
00097   bool lookupTransformSafe(const tf2_ros::Buffer &buffer,
00098                            const std::string &targetFrame,
00099                            const std::string &sourceFrame,
00100                            const ros::Time &time,
00101                            const ros::Duration &timeout,
00102                            tf2::Transform &targetFrameTrans)
00103   {
00104     bool retVal = true;
00105 
00106     // First try to transform the data at the requested time
00107     try
00108     {
00109       tf2::fromMsg(buffer.lookupTransform(targetFrame, sourceFrame, time, timeout).transform,
00110                    targetFrameTrans);
00111     }
00112     catch (tf2::TransformException &ex)
00113     {
00114       // The issue might be that the transforms that are available are not close
00115       // enough temporally to be used. In that case, just use the latest available
00116       // transform and warn the user.
00117       try
00118       {
00119         tf2::fromMsg(buffer.lookupTransform(targetFrame, sourceFrame, ros::Time(0)).transform,
00120                      targetFrameTrans);
00121 
00122         ROS_WARN_STREAM_THROTTLE(2.0, "Transform from " << sourceFrame << " to " << targetFrame <<
00123                                       " was unavailable for the time requested. Using latest instead.\n");
00124       }
00125       catch(tf2::TransformException &ex)
00126       {
00127         ROS_WARN_STREAM_THROTTLE(2.0, "Could not obtain transform from " << sourceFrame <<
00128                                       " to " << targetFrame << ". Error was " << ex.what() << "\n");
00129 
00130         retVal = false;
00131       }
00132     }
00133 
00134     // Transforming from a frame id to itself can fail when the tf tree isn't
00135     // being broadcast (e.g., for some bag files). This is the only failure that
00136     // would throw an exception, so check for this situation before giving up.
00137     if (!retVal)
00138     {
00139       if (targetFrame == sourceFrame)
00140       {
00141         targetFrameTrans.setIdentity();
00142         retVal = true;
00143       }
00144     }
00145 
00146     return retVal;
00147   }
00148 
00149   bool lookupTransformSafe(const tf2_ros::Buffer &buffer,
00150                            const std::string &targetFrame,
00151                            const std::string &sourceFrame,
00152                            const ros::Time &time,
00153                            tf2::Transform &targetFrameTrans)
00154   {
00155     return lookupTransformSafe(buffer, targetFrame, sourceFrame, time, ros::Duration(0), targetFrameTrans);
00156   }
00157 
00158   void quatToRPY(const tf2::Quaternion &quat, double &roll, double &pitch, double &yaw)
00159   {
00160     tf2::Matrix3x3 orTmp(quat);
00161     orTmp.getRPY(roll, pitch, yaw);
00162   }
00163 
00164   void stateToTF(const Eigen::VectorXd &state, tf2::Transform &stateTF)
00165   {
00166     stateTF.setOrigin(tf2::Vector3(state(StateMemberX),
00167                                    state(StateMemberY),
00168                                    state(StateMemberZ)));
00169     tf2::Quaternion quat;
00170     quat.setRPY(state(StateMemberRoll),
00171                 state(StateMemberPitch),
00172                 state(StateMemberYaw));
00173 
00174     stateTF.setRotation(quat);
00175   }
00176 
00177   void TFtoState(const tf2::Transform &stateTF, Eigen::VectorXd &state)
00178   {
00179     state(StateMemberX) = stateTF.getOrigin().getX();
00180     state(StateMemberY) = stateTF.getOrigin().getY();
00181     state(StateMemberZ) = stateTF.getOrigin().getZ();
00182     quatToRPY(stateTF.getRotation(), state(StateMemberRoll), state(StateMemberPitch), state(StateMemberYaw));
00183   }
00184 
00185 }  // namespace RosFilterUtilities
00186 }  // namespace RobotLocalization


robot_localization
Author(s): Tom Moore
autogenerated on Sun Apr 2 2017 03:39:46