motion_primitive_builder.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2020, 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 
31 
32 #include <utility>
33 #include <vector>
34 
35 #include <costmap_cspace_msgs/MapMetaData3D.h>
39 
40 namespace planner_cspace
41 {
42 namespace planner_3d
43 {
44 std::vector<std::vector<MotionPrimitiveBuilder::Vec>> MotionPrimitiveBuilder::build(
45  const costmap_cspace_msgs::MapMetaData3D& map_info, const CostCoeff& cc, const int range)
46 {
47  RotationCache rot_cache;
48  rot_cache.reset(map_info.linear_resolution, map_info.angular_resolution, range);
49  Vecf resolution_(1.0f / map_info.linear_resolution,
50  1.0f / map_info.linear_resolution,
51  1.0f / map_info.angular_resolution);
52 
53  std::vector<std::vector<Vec>> motion_primitives;
54  std::vector<Vec> search_list;
55  {
56  Vec d;
57  for (d[0] = -range; d[0] <= range; d[0]++)
58  {
59  for (d[1] = -range; d[1] <= range; d[1]++)
60  {
61  if (d.sqlen() > range * range)
62  continue;
63  for (d[2] = 0; d[2] < static_cast<int>(map_info.angle); d[2]++)
64  {
65  search_list.push_back(d);
66  }
67  }
68  }
69  }
70 
71  motion_primitives.resize(map_info.angle);
72  for (int i = 0; i < static_cast<int>(motion_primitives.size()); ++i)
73  {
74  auto& current_primitives = motion_primitives[i];
75  for (const auto& prim : search_list)
76  {
77  if (prim[0] == 0 && prim[1] == 0)
78  {
79  if (prim[2] == 0)
80  {
81  continue;
82  }
83  // Rotation
84  current_primitives.push_back(prim);
85  continue;
86  }
87  int next_angle = i + prim[2];
88  if (next_angle >= static_cast<int>(map_info.angle))
89  {
90  next_angle -= map_info.angle;
91  }
92  const Vec d2(prim[0] + range, prim[1] + range, next_angle);
93  const Vecf motion = rot_cache.getMotion(i, d2);
94  const Vecf motion_grid = motion * resolution_;
95 
96  if (std::lround(motion_grid[0]) == 0 && std::lround(motion_grid[1]) != 0)
97  {
98  // Not non-holonomic
99  continue;
100  }
101 
102  static constexpr float EPS = 1.0e-6f;
103  if (std::abs(motion[2]) >= 2.0 * M_PI / 4.0 - EPS)
104  {
105  // Over 90 degree turn
106  // must be separated into two curves
107  continue;
108  }
109 
110  if (prim[2] == 0)
111  {
112  // Straight
113  if (std::lround(motion_grid[0]) == 0)
114  {
115  // side slip
116  continue;
117  }
118  const float aspect = motion[0] / motion[1];
119  if (std::abs(aspect) < cc.angle_resolution_aspect_)
120  {
121  // large y offset
122  continue;
123  }
124  current_primitives.push_back(prim);
125  }
126  else
127  {
128  // Curve
129  if (std::abs(motion[1]) < map_info.linear_resolution / 2.0)
130  {
131  // No y direction movement
132  continue;
133  }
134  if (motion[0] * motion[1] * motion[2] < 0)
135  {
136  continue;
137  }
138  if (prim.sqlen() < 3 * 3)
139  {
140  continue;
141  }
142  const std::pair<float, float>& radiuses = rot_cache.getRadiuses(i, d2);
143  const float r1 = radiuses.first;
144  const float r2 = radiuses.second;
145  if (std::abs(r1 - r2) >= map_info.linear_resolution * 1.5)
146  {
147  // Drifted
148  continue;
149  }
150  const float curv_radius = (r1 + r2) / 2;
151  if (std::abs(curv_radius) < cc.min_curve_radius_)
152  {
153  continue;
154  }
155  current_primitives.push_back(prim);
156  }
157  }
158  }
159 
160  return motion_primitives;
161 }
162 } // namespace planner_3d
163 } // namespace planner_cspace
d
Chain d2()
f
const CyclicVecFloat< 3, 2 > & getMotion(const int start_angle, const CyclicVecInt< 3, 2 > &end) const
void reset(const float linear_resolution, const float angular_resolution, const int range)
const std::pair< float, float > & getRadiuses(const int start_angle, const CyclicVecInt< 3, 2 > &end) const
static std::vector< std::vector< Vec > > build(const costmap_cspace_msgs::MapMetaData3D &map_info, const CostCoeff &cc, const int range)


planner_cspace
Author(s): Atsushi Watanabe
autogenerated on Wed May 12 2021 02:20:42