linear_pose_filter_2d.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2015 Fetch Robotics Inc.
3  * Author: Griswald Brooks
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include <linear_pose_filter_2d.h>
20 
21 // STL includes.
22 #include <algorithm>
23 
24 // ROS includes.
25 #include <tf/transform_datatypes.h>
26 #include <angles/angles.h>
27 
28 LinearPoseFilter2D::LinearPoseFilter2D(const std::vector<float>& b, const std::vector<float>& a)
29 {
30  setCoeff(b, a);
31 }
32 
33 void LinearPoseFilter2D::setCoeff(const std::vector<float>& b, const std::vector<float>& a)
34 {
35  // Check for the smallest vector and use that as the number of elements to push.
36  size_t N = std::min(b.size(), a.size());;
37 
38  // Clear the existing coefficients.
39  b_.resize(N);
40  a_.resize(N);
41 
42  // Copy in the new coefficients. Only copy the N elements from the back.
43  // Ideally this should be all of the elements.
44  std::copy_backward(b.end() - N, b.end(), b_.end());
45  std::copy_backward(a.end() - N, a.end(), a_.end());
46 
47  // Ensure that the sample vectors are appropriately sized. It is done in this way so if we
48  // modify the coefficients but want to mainatain history we don't corrupt the past samples.
49  int K = in_.size() - b_.size();
50  if (K > 0)
51  {
52  // Remove the extra elements.
53  for (int i = 0; i < K; i++)
54  {
55  in_.pop_front();
56  out_.pop_front();
57  yaw_in_.pop_front();
58  yaw_out_.pop_front();
59  }
60  }
61  else
62  {
63  // Add the extra elements.
64  for (int i = 0; i > K; i--)
65  {
66  in_.push_front(originPose());
67  out_.push_front(originPose());
68  yaw_in_.push_front(tf::getYaw(originPose().orientation));
69  yaw_out_.push_front(tf::getYaw(originPose().orientation));
70  }
71  }
72 }
73 
74 geometry_msgs::Pose LinearPoseFilter2D::filter(const geometry_msgs::Pose& pose)
75 {
76  // Add the new input pose to the vector of inputs.
77  in_.push_back(pose);
78  yaw_in_.push_back(getUnnormalizedYaw(pose, getNewestOutputYaw()));
79  // Store a new output.
80  out_.push_back(originPose());
81  yaw_out_.push_back(0.0f);
82  // Remove the oldest elements.
83  in_.pop_front();
84  out_.pop_front();
85  yaw_in_.pop_front();
86  yaw_out_.pop_front();
87 
88  // Grab the iterator to the new output.
89  std::deque<geometry_msgs::Pose>::iterator outn = --out_.end();
90  std::deque<float>::iterator yaw_outn = --yaw_out_.end();
91 
92  // Terminal index of vector.
93  size_t N = b_.size() - 1;
94  for (size_t i = 0; i < (N+1); i++)
95  {
96  // Sweep the inputs.
97  outn->position.x += b_[i]*in_[N - i].position.x;
98  outn->position.y += b_[i]*in_[N - i].position.y;
99  *yaw_outn += b_[i]*yaw_in_[N - i];
100 
101  // Skip the first index for the outputs.
102  if (i > 0)
103  {
104  // Sweep the outputs.
105  outn->position.x -= a_[i]*out_[N - i].position.x;
106  outn->position.y -= a_[i]*out_[N - i].position.y;
107  *yaw_outn -= a_[i]*yaw_out_[N - i];
108  }
109  }
110 
111  // Store orientation.
112  outn->orientation.z = sin(*yaw_outn/2.0);
113  outn->orientation.w = cos(*yaw_outn/2.0);
114 
115  // Return the output.
116  return *outn;
117 }
118 
120 {
121  // Copy in the origins.
123 }
124 
125 void LinearPoseFilter2D::setFilterState(const geometry_msgs::Pose& input_pose, const geometry_msgs::Pose& output_pose)
126 {
127  // Get output yaw.
128  float yaw_out = tf::getYaw(output_pose.orientation);
129  // Fill the output buffer with poses
130  std::fill(out_.begin(), out_.end(), output_pose);
131  std::fill(yaw_out_.begin(), yaw_out_.end(), yaw_out);
132 
133  // Fill the input buffer with poses.
134  std::fill(in_.begin(), in_.end(), input_pose);
135  std::fill(yaw_in_.begin(), yaw_in_.end(), getUnnormalizedYaw(input_pose, yaw_out));
136 }
137 
138 void LinearPoseFilter2D::setFilterState(const std::vector<geometry_msgs::Pose>& input_poses,
139  const std::vector<geometry_msgs::Pose>& output_poses)
140 {
141  // Check length of new output set.
142  // If it is less than or equal to the output buffer size, then copy all of it into
143  // the output buffer.
144  std::vector<geometry_msgs::Pose>::const_iterator earliest_pose_out;
145  if (output_poses.size() <= out_.size())
146  {
147  earliest_pose_out = output_poses.begin();
148  }
149  else
150  {
151  // If the new set is bigger than the output buffer, just copy the the newest
152  // elements of the new set.
153  earliest_pose_out = output_poses.end() - out_.size();
154  }
155 
156  // Copy output poses.
157  std::copy_backward(earliest_pose_out, output_poses.end(), out_.end());
158 
159  // Copy unnormalized output yaw.
160  std::deque<float>::iterator yaw_out = yaw_out_.end();
161  std::deque<float>::iterator yaw_previous = yaw_out_.end();
162  std::vector<geometry_msgs::Pose>::const_iterator pose_out = output_poses.end();
163  while (pose_out != earliest_pose_out)
164  {
165  // // If this is the first time then initialize previous yaw.
166  if (yaw_previous == yaw_out_.end())
167  {
168  // Dereference the newest output pose, convert it to a yaw and save it to
169  // the vector of unnormalized yaws.
170  *(--yaw_previous) = tf::getYaw((--output_poses.end())->orientation);
171  }
172 
173  // Convert the output pose to unnormalized yaw wrt the previous yaw and
174  // increment the previous yaw to the current yaw.
175  *(--yaw_out) = getUnnormalizedYaw(*(--pose_out), *(yaw_previous--));
176  }
177 
178  // Check length of new input set.
179  // If it is less than or equal to the input buffer size, then copy all of it into
180  // the input buffer.
181  std::vector<geometry_msgs::Pose>::const_iterator earliest_pose_in;
182  if (input_poses.size() <= in_.size())
183  {
184  earliest_pose_in = input_poses.begin();
185  }
186  else
187  {
188  // If the new set is bigger than the input buffer, just copy the the newest
189  // elements of the new set.
190  earliest_pose_in = input_poses.end() - in_.size();
191  }
192 
193  // Copy input poses.
194  std::copy_backward(earliest_pose_in, input_poses.end(), in_.end());
195 
196  // Copy unnormalized input yaw.
197  yaw_previous = yaw_out_.end();
198  std::deque<float>::iterator yaw_in = yaw_in_.end();
199  std::vector<geometry_msgs::Pose>::const_iterator pose_in = input_poses.end();
200  while (pose_in != earliest_pose_in)
201  {
202  *(--yaw_in) = getUnnormalizedYaw(*(--pose_in), *(--yaw_previous));
203  }
204 }
205 
206 geometry_msgs::Pose LinearPoseFilter2D::originPose()
207 {
208  geometry_msgs::Pose origin;
209  origin.position.x = 0;
210  origin.position.y = 0;
211  origin.position.z = 0;
212  origin.orientation.x = 0;
213  origin.orientation.y = 0;
214  origin.orientation.z = 0;
215  origin.orientation.w = 1;
216 
217  return origin;
218 }
219 
220 float LinearPoseFilter2D::getUnnormalizedYaw(geometry_msgs::Pose pose, float reference_yaw)
221 {
222  // Get the normalized yaw.
223  float yaw = tf::getYaw(pose.orientation);
224 
225  // Add the normalized difference in angles to the reference.
226  return reference_yaw + angles::normalize_angle(yaw - reference_yaw);
227 }
228 
230 {
231  // If there aren't any previous yaws, return zero.
232  if (yaw_out_.empty())
233  {
234  return 0.0f;
235  }
236  else
237  {
238  return *(--yaw_out_.end());
239  }
240 }
float getNewestOutputYaw()
Method to get the most recent filtered unnormalized yaw. If the filter has never produced an output b...
void reset()
Method to reset the filter to ensure that if the filter is being reused, it is not corrupted by old v...
f
geometry_msgs::Pose filter(const geometry_msgs::Pose &pose)
Method to filter pose objects. Filter only filters position.x, position.y and the yaw of the pose...
static double getYaw(const Quaternion &bt_q)
std::deque< geometry_msgs::Pose > in_
Vector of previous output poses.
float getUnnormalizedYaw(geometry_msgs::Pose pose, float reference_yaw)
Method to return the unnormalized/wrapped-up yaw.
std::deque< geometry_msgs::Pose > out_
std::deque< float > yaw_in_
Vector of previous output yaws that aren&#39;t normalized.
void setCoeff(const std::vector< float > &b, const std::vector< float > &a)
Method to set the filter coefficients.
std::vector< float > b_
Vector of previous input yaws that aren&#39;t normalized.
def normalize_angle(angle)
geometry_msgs::Pose originPose()
Method to get origin pose.
void setFilterState(const geometry_msgs::Pose &input_pose, const geometry_msgs::Pose &output_pose)
Method to set the sample history of the filter to some state. All of the sample histories will be set...
std::vector< float > a_
Vector of input coefficients.
LinearPoseFilter2D(const std::vector< float > &b, const std::vector< float > &a)
Constructor for LinearPoseFilter2D.
std::deque< float > yaw_out_
Vector of previous input poses.
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)


caster_app
Author(s): Ye Tian
autogenerated on Wed Dec 18 2019 03:34:44