test_landmark_sensor_model.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 // standard library
18 #include <functional>
19 #include <numeric>
20 #include <utility>
21 #include <vector>
22 
23 // external
24 #include <sophus/common.hpp>
25 #include <sophus/se2.hpp>
26 #include <sophus/se3.hpp>
27 #include <sophus/so2.hpp>
28 #include <sophus/so3.hpp>
29 
30 // project
34 
35 namespace beluga {
36 
37 namespace {
38 
41 
42 double expected_aggregate_probability(std::vector<double> landmark_probs) {
43  return std::transform_reduce(
44  landmark_probs.cbegin(), landmark_probs.cend(), 1.0, std::multiplies{}, [](const double v) { return v; });
45 }
46 
47 LandmarkModelParam get_default_model_params() {
48  LandmarkModelParam ret;
49  ret.sigma_range = 1.0;
50  ret.sigma_bearing = Sophus::Constants<double>::pi() / 2.0; // 90 degrees
51  return ret;
52 }
53 
54 template <typename T>
56 
57 template <>
58 Sophus::SE2d get_robot_pose_in_world<Sophus::SE2d>() {
59  return Sophus::SE2d{Sophus::SO2d{-Sophus::Constants<double>::pi() / 2.0}, Eigen::Vector2d{1.0, -1.0}};
60 }
61 
62 template <>
63 Sophus::SE3d get_robot_pose_in_world<Sophus::SE3d>() {
64  return Sophus::SE3d{Sophus::SO3d::rotZ(-Sophus::Constants<double>::pi() / 2.0), Eigen::Vector3d{1.0, -1.0, 0.0}};
65 }
66 
67 LandmarkMapBoundaries default_map_boundaries{Eigen::Vector3d{-10.0, -10.0, 0.0}, Eigen::Vector3d{10.0, 10.0, 0.0}};
68 
69 template <typename T>
70 struct LandmarkSensorModelTests : public ::testing::Test {};
71 
72 using LandmarkSensorModelTestsTypes = ::testing::Types<Sensor2D, Sensor3D>;
73 
74 TYPED_TEST_SUITE(LandmarkSensorModelTests, LandmarkSensorModelTestsTypes, );
75 
76 TYPED_TEST(LandmarkSensorModelTests, BullsEyeDetection) {
77  // test case where the landmark is exactly where we expected it
78  auto map = LandmarkMap{default_map_boundaries, {{{3.0, -2.0, 0.0}, 0}}};
79  const auto sensor_model = TypeParam{get_default_model_params(), std::move(map)};
80  const auto state_weighting_function = sensor_model({{{1.0, 2.0, 0.0}, 0}});
81  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
82  EXPECT_NEAR(expected_aggregate_probability({1.0}), state_weighting_function(pose), 1e-02);
83 }
84 
85 TYPED_TEST(LandmarkSensorModelTests, MapUpdate) {
86  // test calls to the update_map function
87  auto map_1 = LandmarkMap(default_map_boundaries, {});
88  auto map_2 = LandmarkMap(default_map_boundaries, {{{3.0, -2.0, 0.0}, 0}});
89  auto sensor_model = TypeParam{get_default_model_params(), std::move(map_1)};
90  const auto state_weighting_function = sensor_model({{{1.0, 2.0, 0.0}, 0}});
91  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
92  EXPECT_NEAR(expected_aggregate_probability({0.0}), state_weighting_function(pose), 1e-02);
93  ASSERT_NO_THROW(sensor_model.update_map(std::move(map_2)));
94  EXPECT_NEAR(expected_aggregate_probability({1.0}), state_weighting_function(pose), 1e-02);
95 }
96 
97 TYPED_TEST(LandmarkSensorModelTests, MultipleBullsEyeDetections) {
98  // Test multiple detections of with different ids, all perfectly matching
99  const auto sensor_model = TypeParam{
101  LandmarkMap( //
103  {
104  {{1.0, -2.0, 0.0}, 0}, // landmark 0
105  {{1.0, -0.0, 0.0}, 1}, // landmark 1
106  {{2.0, -1.0, 0.0}, 2}, // landmark 2
107  {{0.0, -1.0, 0.0}, 3}, // landmark 3
108  })};
109 
110  const auto state_weighting_function = sensor_model({
111  {{+1.0, +0.0, 0.0}, 0}, // landmark 0 detection
112  {{-1.0, +0.0, 0.0}, 1}, // landmark 1 detection
113  {{+0.0, +1.0, 0.0}, 2}, // landmark 2 detection
114  {{+0.0, -1.0, 0.0}, 3}, // landmark 3 detection
115  });
116 
117  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
118  EXPECT_NEAR(expected_aggregate_probability({1.0, 1.0, 1.0, 1.0}), state_weighting_function(pose), 1e-02);
119 }
120 
121 TYPED_TEST(LandmarkSensorModelTests, OneStdInRange) {
122  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
123  // test case where the landmark is 1 std offset from the expected range
124  auto map = LandmarkMap(default_map_boundaries, {{{1.0, -11.0, 0.0}, 0}});
125  const auto sensor_model = TypeParam{get_default_model_params(), std::move(map)};
126  // baseline
127  {
128  auto state_weighting_function = sensor_model({{{10.0, 0.0, 0.0}, 0}});
129  EXPECT_NEAR(expected_aggregate_probability({1.0}), state_weighting_function(pose), 1e-02);
130  }
131  // 1 std default
132  {
133  auto state_weighting_function = sensor_model({{{9.0, 0.0, 0.0}, 0}});
134  EXPECT_NEAR(expected_aggregate_probability({0.6}), state_weighting_function(pose), 1e-02);
135  }
136  // 1 std excess
137  {
138  auto state_weighting_function = sensor_model({{{11.0, 0.0, 0.0}, 0}});
139  EXPECT_NEAR(expected_aggregate_probability({0.6}), state_weighting_function(pose), 1e-02);
140  }
141 }
142 
143 TYPED_TEST(LandmarkSensorModelTests, OneStdInBearing) {
144  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
145  // test case where the landmark is 1 std offset from the expected bearing
146  auto map = LandmarkMap(default_map_boundaries, {{{1.0, -11.0, 0.0}, 0}});
147  auto sensor_model = TypeParam{get_default_model_params(), std::move(map)};
148  // baseline
149  {
150  auto state_weighting_function = sensor_model({{{10.0, 0.0, 0.0}, 0}});
151  EXPECT_NEAR(expected_aggregate_probability({1.0}), state_weighting_function(pose), 1e-02);
152  }
153  // 1 std default
154  {
155  auto state_weighting_function = sensor_model({{{0.0, 10.0, 0.0}, 0}});
156  EXPECT_NEAR(expected_aggregate_probability({0.6}), state_weighting_function(pose), 1e-02);
157  }
158  // 1 std excess
159  {
160  auto state_weighting_function = sensor_model({{{0.0, -10.0, 0.0}, 0}});
161  EXPECT_NEAR(expected_aggregate_probability({0.6}), state_weighting_function(pose), 1e-02);
162  }
163 }
164 
165 TYPED_TEST(LandmarkSensorModelTests, NoSuchLandmark) {
166  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
167  // test case where there is not landmark in the map of the detected id
168  auto map = LandmarkMap(default_map_boundaries, {{{0.0, 1.0, 0.0}, 99}});
169  auto sensor_model = TypeParam{get_default_model_params(), std::move(map)};
170  auto state_weighting_function = sensor_model({{{0.0, 2.0, 0.0}, 88}});
171  EXPECT_NEAR(expected_aggregate_probability({0.0}), state_weighting_function(pose), 1e-02);
172 }
173 
174 } // namespace
175 
176 } // namespace beluga
Sophus::SO2
beluga::Sensor2D
beluga::BearingSensorModel2d< LandmarkMap > Sensor2D
Definition: test_bearing_sensor_model.cpp:39
beluga::TYPED_TEST_SUITE
TYPED_TEST_SUITE(SparseGridTests, SparseGridTestCases,)
landmark_sensor_model.hpp
Implementation of a discrete landmark sensor model.
so3.hpp
landmark_detection_types.hpp
Auxiliar types for landmark models.
beluga::LandmarkSensorModel
Generic landmark model for discrete detection sensors (both 2D and 3D).
Definition: landmark_sensor_model.hpp:63
se2.hpp
beluga::get_default_model_params
BearingModelParam get_default_model_params()
Definition: test_bearing_sensor_model.cpp:49
common.hpp
beluga::expected_aggregate_probability
double expected_aggregate_probability(std::vector< double > landmark_probs)
Definition: test_bearing_sensor_model.cpp:44
beluga::BearingModelParam::sigma_bearing
double sigma_bearing
Standard deviation of the bearing error.
Definition: bearing_sensor_model.hpp:43
Sophus::SE2
beluga::default_map_boundaries
LandmarkMapBoundaries default_map_boundaries
Definition: test_bearing_sensor_model.cpp:42
so2.hpp
Sophus::SE3
beluga::TYPED_TEST
TYPED_TEST(SparseGridTests, CanBeConstructedEmpty)
Definition: test_sparse_value_grid.cpp:46
Sophus::Constants::pi
static SOPHUS_FUNC Scalar pi()
beluga::get_robot_pose_in_world
T get_robot_pose_in_world()
Sophus::SO3::rotZ
static SOPHUS_FUNC SO3 rotZ(Scalar const &z)
Sophus::Constants
landmark_map.hpp
Landmark map datatype.
beluga::LandmarkMapBoundaries
Eigen::AlignedBox3d LandmarkMapBoundaries
Boundaries of a landmark map.
Definition: landmark_detection_types.hpp:36
beluga::Sensor3D
beluga::BearingSensorModel3d< LandmarkMap > Sensor3D
Definition: test_bearing_sensor_model.cpp:40
beluga
The main Beluga namespace.
Definition: 3d_embedding.hpp:21
se3.hpp


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