orientation_tools.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Software License Agreement (BSD License)
4  *
5  * Copyright (c) 2021, Michael Ferguson
6  * Copyright (c) 2009, Willow Garage, Inc.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * * Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  * * Redistributions in binary form must reproduce the above
16  * copyright notice, this list of conditions and the following
17  * disclaimer in the documentation and/or other materials provided
18  * with the distribution.
19  * * Neither the name of Willow Garage, Inc. nor the names of its
20  * contributors may be used to endorse or promote products derived
21  * from this software without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34  * POSSIBILITY OF SUCH DAMAGE.
35  *
36  * Author: Michael Ferguson
37  *********************************************************************/
38 
39 #include <ros/ros.h>
40 #include <angles/angles.h>
41 #include <tf2/utils.h> // getYaw
43 
44 namespace graceful_controller
45 {
46 // Helper function to get yaw if "from" were to point towards "to"
47 double getRelativeYaw(const geometry_msgs::PoseStamped& from, const geometry_msgs::PoseStamped& to)
48 {
49  double dx = to.pose.position.x - from.pose.position.x;
50  double dy = to.pose.position.y - from.pose.position.y;
51  return std::atan2(dy, dx);
52 }
53 
54 void setYaw(geometry_msgs::PoseStamped& pose, double yaw)
55 {
56  pose.pose.orientation.z = sin(yaw / 2.0);
57  pose.pose.orientation.w = cos(yaw / 2.0);
58 }
59 
60 std::vector<geometry_msgs::PoseStamped> addOrientations(const std::vector<geometry_msgs::PoseStamped>& path)
61 {
62  std::vector<geometry_msgs::PoseStamped> oriented_path;
63  oriented_path.resize(path.size());
64  if (path.empty())
65  {
66  // This really shouldn't happen
67  return oriented_path;
68  }
69 
70  // The last pose will already be oriented since it is our goal
71  oriented_path.back() = path.back();
72 
73  // For each pose, point at the next one
74  for (size_t i = 0; i < oriented_path.size() - 1; ++i)
75  {
76  oriented_path[i] = path[i];
77  double yaw = getRelativeYaw(path[i], path[i + 1]);
78  setYaw(oriented_path[i], yaw);
79  }
80 
81  return oriented_path;
82 }
83 
84 std::vector<geometry_msgs::PoseStamped> applyOrientationFilter(const std::vector<geometry_msgs::PoseStamped>& path,
85  double yaw_tolerance, double gap_tolerance)
86 {
87  std::vector<geometry_msgs::PoseStamped> filtered_path;
88  filtered_path.reserve(path.size());
89  if (path.empty())
90  {
91  // This really shouldn't happen
92  return filtered_path;
93  }
94 
95  // Always keep the first pose
96  filtered_path.push_back(path.front());
97 
98  // Possibly filter some intermediate poses
99  for (size_t i = 1; i < path.size() - 1; ++i)
100  {
101  // Get the yaw angle if the previous pose were to be pointing at this pose
102  // We need to recompute because we might have dropped poses
103  double yaw_previous = getRelativeYaw(filtered_path.back(), path[i]);
104 
105  // Get the yaw angle of this pose pointing at next pose
106  double yaw_this = tf2::getYaw(path[i].pose.orientation);
107 
108  // Get the yaw angle if previous pose were to be pointing at next pose, filtering this pose
109  double yaw_without = getRelativeYaw(filtered_path.back(), path[i + 1]);
110 
111  // Determine if this pose is far off a direct line between previous and next pose
112  if (fabs(angles::shortest_angular_distance(yaw_previous, yaw_without)) < yaw_tolerance &&
113  fabs(angles::shortest_angular_distance(yaw_this, yaw_without)) < yaw_tolerance)
114  {
115  // Update previous heading in case we dropped some poses
116  setYaw(filtered_path.back(), yaw_previous);
117  // Add this pose to the filtered plan
118  filtered_path.push_back(path[i]);
119  }
120  else if (std::hypot(path[i].pose.position.x - filtered_path.back().pose.position.x,
121  path[i].pose.position.y - filtered_path.back().pose.position.y) >= gap_tolerance)
122  {
123  ROS_DEBUG_NAMED("orientation_filter", "Including pose %lu to meet max_separation_dist", i);
124  // Update previous heading in case we dropped some poses
125  setYaw(filtered_path.back(), yaw_previous);
126  // Add this pose to the filtered plan
127  filtered_path.push_back(path[i]);
128  }
129  else
130  {
131  // Sorry pose, the plan is better without you :(
132  ROS_DEBUG_NAMED("orientation_filter", "Filtering pose %lu", i);
133  }
134  }
135 
136  // Reset heading of what will be penultimate pose, in case we dropped some poses
137  setYaw(filtered_path.back(), getRelativeYaw(filtered_path.back(), path.back()));
138 
139  // Always add the last pose, since this is our goal
140  filtered_path.push_back(path.back());
141 
142  ROS_DEBUG_NAMED("orientation_filter", "Filtered %lu points from plan", path.size() - filtered_path.size());
143  return filtered_path;
144 }
145 
146 } // namespace graceful_controller
graceful_controller::applyOrientationFilter
std::vector< geometry_msgs::PoseStamped > applyOrientationFilter(const std::vector< geometry_msgs::PoseStamped > &path, double yaw_tolerance, double gap_tolerance)
Filter a path for orientation noise.
Definition: orientation_tools.cpp:120
angles::shortest_angular_distance
static double shortest_angular_distance(double from, double to)
tf2::getYaw
double getYaw(const A &a)
utils.h
ros.h
graceful_controller
graceful_controller::setYaw
void setYaw(geometry_msgs::PoseStamped &pose, double yaw)
Definition: orientation_tools.cpp:90
ROS_DEBUG_NAMED
#define ROS_DEBUG_NAMED(name,...)
orientation_tools.hpp
graceful_controller::addOrientations
std::vector< geometry_msgs::PoseStamped > addOrientations(const std::vector< geometry_msgs::PoseStamped > &path)
Add orientation to each pose in a path.
Definition: orientation_tools.cpp:96
graceful_controller::getRelativeYaw
double getRelativeYaw(const geometry_msgs::PoseStamped &from, const geometry_msgs::PoseStamped &to)
Definition: orientation_tools.cpp:83
angles.h


graceful_controller_ros
Author(s): Michael Ferguson
autogenerated on Wed Oct 23 2024 02:43:04