test_amcl_core.cpp
Go to the documentation of this file.
1 // Copyright 2024 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 <execution>
18 #include <utility>
19 #include <vector>
20 
21 #include <Eigen/Core>
22 #include <sophus/se2.hpp>
23 
32 
33 namespace {
34 
35 const auto kDummyControl = Sophus::SE2d{};
36 const std::vector kDummyMeasurement = {
37  std::make_pair(0.0, 0.0),
38  std::make_pair(0.0, 0.0),
39  std::make_pair(0.0, 0.0),
40 };
41 
42 auto make_amcl(const beluga::AmclParams& params = {}) {
43  constexpr double kResolution = 1.0;
44  // clang-format off
46  false, false, false, false, false ,
47  false, false, false, false , false,
48  false, false, true , false, false,
49  false, false , false, false, false,
50  false , false, false, false, false},
51  kResolution};
52  // clang-format on
53  const beluga::BeamModelParam param{};
54 
55  auto random_state_maker = []() { return Sophus::SE2d{}; };
56 
57  beluga::spatial_hash<Sophus::SE2d> hasher{0.1, 0.1, 0.1};
58 
59  beluga::Amcl amcl{
61  beluga::BeamSensorModel{param, map}, //
62  std::move(random_state_maker),
63  std::move(hasher),
64  std::move(params), //
65  std::execution::seq,
66  };
67  return amcl;
68 }
69 } // namespace
70 
71 namespace beluga {
73 TEST(TestAmclCore, InitializeWithNoParticles) {
74  auto amcl = make_amcl();
75  ASSERT_EQ(amcl.particles().size(), 0);
76 }
77 TEST(TestAmclCore, Update) {
78  auto amcl = make_amcl();
79  amcl.update(kDummyControl, kDummyMeasurement);
80 }
81 
82 TEST(TestAmclCore, InitializeFromPose) {
83  auto amcl = make_amcl();
84  amcl.initialize(Sophus::SE2d{}, Eigen::Vector3d::Ones().asDiagonal());
85  ASSERT_EQ(amcl.particles().size(), AmclParams{}.max_particles);
86 }
87 
88 TEST(TestAmclCore, UpdateWithNoParticles) {
89  auto amcl = make_amcl();
90  ASSERT_EQ(amcl.particles().size(), 0);
91  auto estimate = amcl.update(kDummyControl, kDummyMeasurement);
92  ASSERT_FALSE(estimate.has_value());
93 }
94 
95 TEST(TestAmclCore, UpdateWithParticles) {
96  auto amcl = make_amcl();
97  ASSERT_EQ(amcl.particles().size(), 0);
98  amcl.initialize(Sophus::SE2d{}, Eigen::Vector3d::Ones().asDiagonal());
99  ASSERT_EQ(amcl.particles().size(), AmclParams{}.max_particles);
100  auto estimate = amcl.update(kDummyControl, kDummyMeasurement);
101  ASSERT_TRUE(estimate.has_value());
102 }
103 
104 TEST(TestAmclCore, UpdateWithParticlesNoMotion) {
105  auto amcl = make_amcl();
106  ASSERT_EQ(amcl.particles().size(), 0);
107  amcl.initialize(Sophus::SE2d{}, Eigen::Vector3d::Ones().asDiagonal());
108  ASSERT_EQ(amcl.particles().size(), AmclParams{}.max_particles);
109  auto estimate = amcl.update(kDummyControl, kDummyMeasurement);
110  ASSERT_TRUE(estimate.has_value());
111  estimate = amcl.update(kDummyControl, kDummyMeasurement);
112  ASSERT_FALSE(estimate.has_value());
113 }
114 
115 TEST(TestAmclCore, UpdateWithParticlesForced) {
116  auto amcl = make_amcl();
117  ASSERT_EQ(amcl.particles().size(), 0);
118  amcl.initialize(Sophus::SE2d{}, Eigen::Vector3d::Ones().asDiagonal());
119  ASSERT_EQ(amcl.particles().size(), AmclParams{}.max_particles);
120  auto estimate = amcl.update(kDummyControl, kDummyMeasurement);
121  ASSERT_TRUE(estimate.has_value());
122  amcl.force_update();
123  estimate = amcl.update(kDummyControl, kDummyMeasurement);
124  ASSERT_TRUE(estimate.has_value());
125 }
126 
127 TEST(TestAmclCore, ParticlesDependentRandomStateGenerator) {
128  auto params = beluga::AmclParams{};
130 
131  constexpr double kResolution = 0.5;
132  // clang-format off
134  false, false, false, false, false ,
135  false, false, false, false , false,
136  false, false, false , false, false,
137  false, false , false, false, false,
138  false , false, false, false, false},
139  kResolution};
140  // clang-format on
141 
142  // Demonstrate how we can provide a generator that depends on the current filter state.
143  auto random_state_maker = [](const auto& particles) {
144  const auto last_particle_state = beluga::views::states(particles).back();
145  return [last_particle_state]() { return last_particle_state; };
146  };
147 
148  beluga::spatial_hash<Sophus::SE2d> hasher{0.5, 0.5, 0.5};
149 
150  beluga::Amcl amcl{
153  std::move(random_state_maker),
154  std::move(hasher),
155  std::move(params), //
156  std::execution::seq,
157  };
158  amcl.initialize(Sophus::SE2d{}, Eigen::Vector3d::Ones().asDiagonal());
159  ASSERT_EQ(amcl.particles().size(), AmclParams{}.max_particles);
160  auto estimate = amcl.update(kDummyControl, kDummyMeasurement);
161  ASSERT_TRUE(estimate.has_value());
162 }
163 
164 TEST(TestAmclCore, SelectiveResampleCanBeConstructed) {
165  auto params = beluga::AmclParams{};
166  params.selective_resampling = true;
167  auto amcl = make_amcl(params);
168  amcl.initialize(Sophus::SE2d{}, Eigen::Vector3d::Ones().asDiagonal());
169  ASSERT_EQ(amcl.particles().size(), AmclParams{}.max_particles);
170  auto estimate = amcl.update(kDummyControl, kDummyMeasurement);
171  ASSERT_TRUE(estimate.has_value());
172 }
173 
174 TEST(TestAmclCore, TestRandomParticlesInserting) {
175  auto params = beluga::AmclParams{};
176  params.min_particles = 2;
177  params.max_particles = 100;
178  params.alpha_slow = 0.0;
179  params.alpha_fast = 100.0; // Ensure we exercise random state generation
180  auto amcl = make_amcl(params);
181  amcl.initialize(Sophus::SE2d{Sophus::SO2d{}, Eigen::Vector2d{1, 1}}, (Eigen::Vector3d::Ones()).asDiagonal());
182  for (int i = 0; i < 30; ++i) {
183  amcl.force_update();
184  amcl.update(kDummyControl, kDummyMeasurement);
185  }
186 }
187 
188 } // namespace beluga
Sophus::SO2
beam_model.hpp
Implementation of a beam sensor model for range finders.
tuple_vector.hpp
Implementation of a tuple of containers.
static_occupancy_grid.hpp
beluga::AmclParams
Struct containing parameters for the Adaptive Monte Carlo Localization (AMCL) implementation.
Definition: amcl_core.hpp:33
beluga::AmclParams::selective_resampling
bool selective_resampling
Whether to use selective resampling or not.
Definition: amcl_core.hpp:41
particles.hpp
Implementation of views related to particle ranges.
beluga::DifferentialDriveModelParam
Parameters to construct a DifferentialDriveModel instance.
Definition: differential_drive_model.hpp:40
se2.hpp
beluga::AmclParams::min_particles
std::size_t min_particles
Minimum number of particles in the filter at any point in time.
Definition: amcl_core.hpp:43
beluga::AmclParams::max_particles
std::size_t max_particles
Maximum number of particles in the filter at any point in time.
Definition: amcl_core.hpp:45
beluga::LikelihoodFieldModel
Likelihood field sensor model for range finders.
Definition: likelihood_field_model.hpp:78
Sophus::SE2
beluga::testing::StaticOccupancyGrid
Definition: static_occupancy_grid.hpp:28
beluga::spatial_hash
Callable class, allowing to calculate the hash of a particle state.
Definition: spatial_hash.hpp:100
beluga::DifferentialDriveModel
Sampled odometry model for a differential drive.
Definition: differential_drive_model.hpp:80
beluga::LikelihoodFieldModelParam
Parameters used to construct a LikelihoodFieldModel instance.
Definition: likelihood_field_model.hpp:43
beluga::estimate
std::pair< Sophus::SE2< Scalar >, Sophus::Matrix3< Scalar > > estimate(Poses &&poses, Weights &&weights)
Returns a pair consisting of the estimated mean pose and its covariance.
Definition: estimation.hpp:129
spatial_hash.hpp
Implementation of a spatial hash for N dimensional states.
beluga::BeamSensorModel
Beam sensor model for range finders.
Definition: beam_model.hpp:75
differential_drive_model.hpp
Implementation of a differential drive odometry motion model.
beluga::BeamModelParam
Parameters used to construct a BeamSensorModel instance.
Definition: beam_model.hpp:42
amcl_core.hpp
beluga::Amcl
Implementation of the Adaptive Monte Carlo Localization (AMCL) algorithm.
Definition: amcl_core.hpp:80
likelihood_field_model.hpp
Implementation of a likelihood field sensor model for range finders.
beluga::views::states
constexpr auto states
Definition: particles.hpp:30
beluga
The main Beluga namespace.
Definition: 3d_embedding.hpp:21
beluga::TEST
TEST(Bresenham, MultiPassGuarantee)
Definition: test_bresenham.cpp:27


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