motion_cache.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018-2019, the neonavigation authors
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  * * Neither the name of the copyright holder nor the names of its
14  * contributors may be used to endorse or promote products derived from
15  * this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include <algorithm>
31 #include <cmath>
32 #include <list>
33 #include <unordered_map>
34 #include <vector>
35 
36 #include <ros/ros.h>
37 
40 
41 namespace planner_cspace
42 {
43 namespace planner_3d
44 {
46  const float linear_resolution,
47  const float angular_resolution,
48  const int range,
49  const std::function<void(CyclicVecInt<3, 2>, size_t&, size_t&)> gm_addr,
50  const float interpolation_resolution,
51  const float grid_enumeration_resolution)
52 {
53  const int angle = std::lround(M_PI * 2 / angular_resolution);
54 
55  CyclicVecInt<3, 2> max_range(0, 0, 0);
56  page_size_ = angle;
57  cache_.resize(angle);
58  for (int syaw = 0; syaw < angle; syaw++)
59  {
60  const float yaw = syaw * angular_resolution;
62  for (d[0] = -range; d[0] <= range; d[0]++)
63  {
64  for (d[1] = -range; d[1] <= range; d[1]++)
65  {
66  if (d[0] == 0 && d[1] == 0)
67  continue;
68  if (d.sqlen() > range * range)
69  continue;
70  for (d[2] = 0; d[2] < angle; d[2]++)
71  {
72  Page page;
73  const float yaw_e = d[2] * angular_resolution;
74  const float diff_val[3] =
75  {
76  d[0] * linear_resolution,
77  d[1] * linear_resolution,
78  d[2] * angular_resolution,
79  };
80  std::unordered_map<CyclicVecInt<3, 2>, bool, CyclicVecInt<3, 2>> registered;
81  registered[d] = true;
82 
83  CyclicVecFloat<3, 2> motion(diff_val[0], diff_val[1], diff_val[2]);
84  motion.rotate(-syaw * angular_resolution);
85  const float cos_v = cosf(motion[2]);
86  const float sin_v = sinf(motion[2]);
87 
88  const int total_step = static_cast<int>(std::round(d.len() / grid_enumeration_resolution));
89  const int interpolation_step =
90  std::max(1, static_cast<int>(std::round(interpolation_resolution / grid_enumeration_resolution)));
91  if (std::abs(sin_v) < 0.1)
92  {
93  for (int step = 0; step < total_step; ++step)
94  {
95  const float ratio = step / static_cast<float>(total_step);
96  const float x = diff_val[0] * ratio;
97  const float y = diff_val[1] * ratio;
98 
99  const CyclicVecFloat<3, 2> posf(x / linear_resolution, y / linear_resolution, yaw / angular_resolution);
100  CyclicVecInt<3, 2> pos(posf[0], posf[1], posf[2]);
101  pos.cycleUnsigned(angle);
102 
103  if ((pos != d) && (registered.find(pos) == registered.end()))
104  {
105  page.motion_.push_back(pos);
106  for (int i = 0; i < 3; ++i)
107  max_range[i] = std::max(max_range[i], std::abs(pos[i]));
108  registered[pos] = true;
109  }
110  if (step % interpolation_step == 0)
111  {
112  page.interpolated_motion_.push_back(posf);
113  }
114  }
115  page.distance_ = d.len();
116  cache_[syaw][d] = page;
117  continue;
118  }
119 
120  float distf = 0.0;
121  const float r1 = motion[1] + motion[0] * cos_v / sin_v;
122  const float r2 = std::copysign(
123  std::sqrt(std::pow(motion[0], 2) + std::pow(motion[0] * cos_v / sin_v, 2)),
124  motion[0] * sin_v);
125 
126  float dyaw = yaw_e - yaw;
127  if (dyaw < -M_PI)
128  dyaw += 2 * M_PI;
129  else if (dyaw > M_PI)
130  dyaw -= 2 * M_PI;
131 
132  const float cx = d[0] * linear_resolution + r2 * cosf(yaw_e + M_PI / 2);
133  const float cy = d[1] * linear_resolution + r2 * sinf(yaw_e + M_PI / 2);
134  const float cx_s = r1 * cosf(yaw + M_PI / 2);
135  const float cy_s = r1 * sinf(yaw + M_PI / 2);
136 
137  CyclicVecFloat<3, 2> posf_prev(0, 0, 0);
138 
139  for (int step = 0; step < total_step; ++step)
140  {
141  const float ratio = step / static_cast<float>(total_step);
142  const float r = r1 * (1.0 - ratio) + r2 * ratio;
143  const float cx2 = cx_s * (1.0 - ratio) + cx * ratio;
144  const float cy2 = cy_s * (1.0 - ratio) + cy * ratio;
145  const float cyaw = yaw + ratio * dyaw;
146 
147  const CyclicVecFloat<3, 2> posf((cx2 - r * cosf(cyaw + M_PI / 2)) / linear_resolution,
148  (cy2 - r * sinf(cyaw + M_PI / 2)) / linear_resolution,
149  cyaw / angular_resolution);
150  CyclicVecInt<3, 2> pos(posf[0], posf[1], posf[2]);
151  pos.cycleUnsigned(angle);
152  if ((pos != d) && (registered.find(pos) == registered.end()))
153  {
154  page.motion_.push_back(pos);
155  registered[pos] = true;
156  }
157  if (step % interpolation_step == 0)
158  {
159  page.interpolated_motion_.push_back(posf);
160  }
161  if (ratio > 0)
162  distf += (posf - posf_prev).len();
163  posf_prev = posf;
164  }
165  distf += (CyclicVecFloat<3, 2>(d) - posf_prev).len();
166  page.distance_ = distf;
167  cache_[syaw][d] = page;
168  }
169  }
170  }
171  // Sort to improve cache hit rate
172  for (auto& cache : cache_[syaw])
173  {
174  auto comp = [this, &gm_addr](const CyclicVecInt<3, 2> a, const CyclicVecInt<3, 2> b)
175  {
176  size_t a_baddr, a_addr;
177  size_t b_baddr, b_addr;
178  gm_addr(a, a_baddr, a_addr);
179  gm_addr(b, b_baddr, b_addr);
180  if (a_baddr == b_baddr)
181  {
182  return (a_addr < b_addr);
183  }
184  return (a_baddr < b_baddr);
185  };
186  std::sort(cache.second.motion_.begin(), cache.second.motion_.end(), comp);
187  }
188  }
189  max_range_ = max_range;
190 }
191 
192 std::list<CyclicVecFloat<3, 2>> MotionCache::interpolatePath(const std::list<CyclicVecInt<3, 2>>& grid_path) const
193 {
194  std::list<CyclicVecFloat<3, 2>> result;
195  if (grid_path.size() < 2)
196  {
197  for (const auto& p : grid_path)
198  {
199  result.push_back(CyclicVecFloat<3, 2>(p[0], p[1], p[2]));
200  }
201  return result;
202  }
203  auto it_prev = grid_path.begin();
204  for (auto it = std::next(it_prev); it != grid_path.end(); ++it, ++it_prev)
205  {
206  if (((*it_prev)[0] == (*it)[0]) && ((*it_prev)[1] == (*it)[1]))
207  {
208  result.push_back(CyclicVecFloat<3, 2>((*it_prev)[0], (*it_prev)[1], (*it_prev)[2]));
209  continue;
210  }
211 
212  const auto motion_it = find(*it_prev, *it);
213  if (motion_it == end((*it)[2]))
214  {
215  ROS_ERROR("Failed to find motion between [%d %d %d] and [%d %d %d]",
216  (*it_prev)[0], (*it_prev)[1], (*it_prev)[2], (*it)[0], (*it)[1], (*it)[2]);
217  result.push_back(CyclicVecFloat<3, 2>((*it_prev)[0], (*it_prev)[1], (*it_prev)[2]));
218  }
219  else
220  {
221  for (const auto& pos_diff : motion_it->second.getInterpolatedMotion())
222  {
223  result.push_back(CyclicVecFloat<3, 2>((*it_prev)[0] + pos_diff[0], (*it_prev)[1] + pos_diff[1], pos_diff[2]));
224  }
225  }
226  }
227  result.push_back(CyclicVecFloat<3, 2>(grid_path.back()[0], grid_path.back()[1], grid_path.back()[2]));
228  return result;
229 }
230 
231 } // namespace planner_3d
232 } // namespace planner_cspace
planner_cspace
Definition: bbf.h:33
planner_cspace::planner_3d::MotionCache::find
const Cache::const_iterator find(const int start_yaw, const CyclicVecInt< 3, 2 > &goal) const
Definition: motion_cache.h:76
motion_cache.h
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
planner_cspace::planner_3d::MotionCache::reset
void reset(const float linear_resolution, const float angular_resolution, const int range, const std::function< void(CyclicVecInt< 3, 2 >, size_t &, size_t &)> gm_addr, const float interpolation_resolution, const float grid_enumeration_resolution)
Definition: motion_cache.cpp:45
planner_cspace::planner_3d::MotionCache::Page::motion_
std::vector< CyclicVecInt< 3, 2 > > motion_
Definition: motion_cache.h:52
ros.h
step
unsigned int step
planner_cspace::planner_3d::MotionCache::Page::distance_
float distance_
Definition: motion_cache.h:54
d
d
planner_cspace::CyclicVecBase::rotate
void rotate(const float ang)
Definition: cyclic_vec.h:268
planner_cspace::planner_3d::MotionCache::Page::interpolated_motion_
std::vector< CyclicVecFloat< 3, 2 > > interpolated_motion_
Definition: motion_cache.h:53
planner_cspace::CyclicVecBase::cycleUnsigned
void cycleUnsigned(const int res, const ArgList &... rest)
Definition: cyclic_vec.h:289
planner_cspace::planner_3d::MotionCache::page_size_
int page_size_
Definition: motion_cache.h:119
ROS_ERROR
#define ROS_ERROR(...)
planner_cspace::planner_3d::MotionCache::end
const Cache::const_iterator end(const int start_yaw) const
Definition: motion_cache.h:93
cyclic_vec.h
planner_cspace::planner_3d::MotionCache::max_range_
CyclicVecInt< 3, 2 > max_range_
Definition: motion_cache.h:120
planner_cspace::planner_3d::MotionCache::interpolatePath
std::list< CyclicVecFloat< 3, 2 > > interpolatePath(const std::list< CyclicVecInt< 3, 2 >> &path_grid) const
Definition: motion_cache.cpp:192
planner_cspace::planner_3d::MotionCache::cache_
std::vector< Cache > cache_
Definition: motion_cache.h:118
planner_cspace::planner_3d::MotionCache::Page
Definition: motion_cache.h:47
planner_cspace::CyclicVecBase
Definition: cyclic_vec.h:78


planner_cspace
Author(s): Atsushi Watanabe
autogenerated on Fri May 16 2025 02:15:23