test_raycasting.cpp
Go to the documentation of this file.
1 // Copyright 2023 Ekumen, Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <gtest/gtest.h>
16 
17 #include <cmath>
18 #include <optional>
19 
20 #include <sophus/common.hpp>
21 #include <sophus/se2.hpp>
22 
26 
27 namespace beluga {
28 
29 using testing::StaticOccupancyGrid;
30 
31 TEST(Raycasting, Nominal) {
32  constexpr double kResolution = 0.5;
33  // Note that axes are:
34  // Positive X -> Right
35  // Positive Y -> Down
36 
37  // clang-format off
38  const auto grid = StaticOccupancyGrid<5, 5>{{
39  false, false, false, false, false,
40  false, false, false, false, false,
41  false, false, true , false, false,
42  false, false, false, false, false,
43  false, false, false, false, false},
44  kResolution};
45  // clang-format on
46 
47  constexpr double kMaxRange = 5.;
48 
49  {
50  // Horizontal ray that hits the map boundary.
51  const auto pose = Sophus::SE2d{0., Eigen::Vector2d{0.5, 0.}};
52  const auto ray = Ray2d{grid, pose, kMaxRange};
53  EXPECT_EQ(ray.cast(Sophus::SO2d{0.}), std::nullopt);
54  }
55 
56  {
57  // Horizontal ray that hits the occupied cell.
58  const auto pose = Sophus::SE2d{0., Eigen::Vector2d{0., 1.}};
59  const auto ray = Ray2d{grid, pose, kMaxRange};
60  EXPECT_EQ(ray.cast(Sophus::SO2d{0.}), 1.);
61  }
62 
63  {
64  // Downwards ray that hits the map boundary.
65  const auto pose = Sophus::SE2d{0., Eigen::Vector2d{0., 1.}};
66  const auto ray = Ray2d{grid, pose, kMaxRange};
67  const auto distance = ray.cast(Sophus::SO2d{Sophus::Constants<double>::pi() / 2.});
68  EXPECT_EQ(distance, std::nullopt);
69  }
70 
71  {
72  // Start cell is occupied, should return 0.
73  const auto pose = Sophus::SE2d{0., Eigen::Vector2d{1., 1.}};
74  const auto ray = Ray2d{grid, pose, kMaxRange};
75  const auto distance = ray.cast(Sophus::SO2d{Sophus::Constants<double>::pi() / 2.});
76  EXPECT_EQ(distance, 0.);
77  }
78 
79  {
80  // Downwards ray that is limited by beam range.
81  constexpr double kShortenedRange = 1.;
82  const auto pose = Sophus::SE2d{Sophus::Constants<double>::pi() / 2., Eigen::Vector2d{0., 0.}};
83  const auto ray = Ray2d{grid, pose, kShortenedRange};
84  EXPECT_EQ(ray.cast(Sophus::SO2d{0}), std::nullopt);
85  }
86 
87  {
88  // Downwards ray that hits the occupied cell.
89  const auto pose = Sophus::SE2d{0., Eigen::Vector2d{1., 0.}};
90  const auto ray = Ray2d{grid, pose, kMaxRange};
91  const auto distance = ray.cast(Sophus::SO2d{Sophus::Constants<double>::pi() / 2.});
92  EXPECT_EQ(distance, 1.);
93  }
94 
95  {
96  // Diagonal ray that hits the occupied cell.
97  const auto pose = Sophus::SE2d{0., Eigen::Vector2d{0., 0.}};
98  const auto ray = Ray2d{grid, pose, kMaxRange};
99  const auto distance = ray.cast(Sophus::SO2d{Sophus::Constants<double>::pi() / 4.});
100  EXPECT_EQ(distance, std::sqrt(2));
101  }
102 }
103 
104 TEST(Raycasting, NonIdentityGridOrigin) {
105  constexpr double kResolution = 0.5;
106 
107  const auto origin = Sophus::SE2d{Sophus::SO2d{-Sophus::Constants<double>::pi() / 4.}, Eigen::Vector2d{0.5, 0.}};
108  // Note that axes are:
109  // Positive X -> Diagonal downwards right
110  // Positive Y -> Diagonal downwards left
111 
112  // clang-format off
113  const auto grid = StaticOccupancyGrid<5, 5>{{
114  false, false, false, false, false,
115  false, false, false, false, false,
116  false, false, true , false, false,
117  false, false, false, false, false,
118  false, false, false, false, false},
119  kResolution, origin};
120  // clang-format on
121 
122  constexpr double kMaxRange = 5.;
123 
124  {
125  // Diagonal ray that hits the occupied cell.
126  const auto pose = Sophus::SE2d{0., Eigen::Vector2d{0.5, 0.}};
127  const auto ray = Ray2d{grid, pose, kMaxRange};
128  const auto distance = ray.cast(Sophus::SO2d{0.});
129  EXPECT_EQ(distance, std::sqrt(2));
130  }
131 }
132 
133 TEST(BaselineRaycasting, Nominal) {
134  constexpr double kResolution = 0.5;
135  // Note that axes are:
136  // Positive X -> Right
137  // Positive Y -> Down
138 
139  // clang-format off
140  const auto grid = StaticOccupancyGrid<5, 5>{{
141  false, false, false, false, false,
142  false, false, false, false, false,
143  false, false, true , false, false,
144  false, false, false, false, false,
145  false, false, false, false, false},
146  kResolution};
147  // clang-format on
148 
149  constexpr double kMaxRange = 5.;
150 
151  using Constants = Sophus::Constants<double>;
152 
153  {
154  // Horizontal ray that hits the map boundary.
155  const auto pose = Eigen::Vector2d{0.5, 0.};
156  const auto source = grid.cell_near(pose);
157  const auto target = grid.cell_near(pose + kMaxRange * Sophus::SO2d{0.}.unit_complex());
158  EXPECT_EQ(beluga::testing::raycast(grid, source, target), std::nullopt);
159  }
160 
161  {
162  // Horizontal ray that hits the occupied cell.
163  const auto pose = Eigen::Vector2d{0., 1.};
164  const auto source = grid.cell_near(pose);
165  const auto target = grid.cell_near(pose + kMaxRange * Sophus::SO2d{0.}.unit_complex());
166  EXPECT_EQ(beluga::testing::raycast(grid, source, target), 1.);
167  }
168 
169  {
170  // Downwards ray that hits the map boundary.
171  const auto pose = Eigen::Vector2d{0., 1.};
172  const auto source = grid.cell_near(pose);
173  const auto target = grid.cell_near(pose + kMaxRange * Sophus::SO2d{Constants::pi() / 2.}.unit_complex());
174  EXPECT_EQ(beluga::testing::raycast(grid, source, target), std::nullopt);
175  }
176 
177  {
178  // Start cell is occupied, should return 0.
179  const auto pose = Eigen::Vector2d{1., 1.};
180  const auto source = grid.cell_near(pose);
181  const auto target = grid.cell_near(pose + kMaxRange * Sophus::SO2d{Constants::pi() / 2.}.unit_complex());
182  EXPECT_EQ(beluga::testing::raycast(grid, source, target), 0.);
183  }
184 
185  {
186  // Downwards ray that is limited by beam range.
187  constexpr double kShortenedRange = 1.;
188  const auto pose = Eigen::Vector2d{0., 0.};
189  const auto source = grid.cell_near(pose);
190  const auto target = grid.cell_near(pose + kShortenedRange * Sophus::SO2d{Constants::pi() / 2.}.unit_complex());
191  EXPECT_EQ(beluga::testing::raycast(grid, source, target), std::nullopt);
192  }
193 
194  {
195  // Downwards ray that hits the occupied cell.
196  const auto pose = Eigen::Vector2d{1., 0.};
197  const auto source = grid.cell_near(pose);
198  const auto target = grid.cell_near(pose + kMaxRange * Sophus::SO2d{Constants::pi() / 2.}.unit_complex());
199  EXPECT_EQ(beluga::testing::raycast(grid, source, target), 1.);
200  }
201 
202  {
203  // Diagonal ray that hits the occupied cell.
204  const auto pose = Eigen::Vector2d{0., 0.};
205  const auto source = grid.cell_near(pose);
206  const auto target = grid.cell_near(pose + kMaxRange * Sophus::SO2d{Constants::pi() / 4.}.unit_complex());
207  EXPECT_EQ(beluga::testing::raycast(grid, source, target), std::sqrt(2));
208  }
209 }
210 
211 } // namespace beluga
raycasting.hpp
Sophus::SO2
raycasting.hpp
Implementation of raycasting algorithms.
beluga::Ray2d::cast
std::optional< double > cast(const Sophus::SO2d &bearing) const
Casts ray along a given direction.
Definition: include/beluga/algorithm/raycasting.hpp:97
static_occupancy_grid.hpp
se2.hpp
common.hpp
Sophus::SE2
beluga::testing::StaticOccupancyGrid
Definition: static_occupancy_grid.hpp:28
beluga::testing::raycast
std::optional< double > raycast(const Map &map, Eigen::Vector2i source, Eigen::Vector2i target)
Definition: test/beluga/include/beluga/test/raycasting.hpp:23
Sophus::Constants::pi
static SOPHUS_FUNC Scalar pi()
Sophus::Constants
beluga
The main Beluga namespace.
Definition: 3d_embedding.hpp:21
beluga::Ray2d
Castable 2D ray.
Definition: include/beluga/algorithm/raycasting.hpp:44
beluga::TEST
TEST(Bresenham, MultiPassGuarantee)
Definition: test_bresenham.cpp:27
Sophus::SO2::unit_complex
SOPHUS_FUNC ComplexMember const & unit_complex() const


beluga
Author(s):
autogenerated on Tue Jul 16 2024 02:59:53