test_bearing_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 <cstdint>
19 #include <functional>
20 #include <numeric>
21 #include <tuple>
22 #include <utility>
23 #include <vector>
24 
25 // external
26 #include <range/v3/range/conversion.hpp>
27 #include <range/v3/view/transform.hpp>
28 
29 #include <sophus/common.hpp>
30 #include <sophus/se2.hpp>
31 
32 // project
36 
37 namespace beluga {
38 
41 
42 LandmarkMapBoundaries default_map_boundaries{Eigen::Vector3d{-10.0, -10.0, 0.0}, Eigen::Vector3d{10.0, 10.0, 0.0}};
43 
44 double expected_aggregate_probability(std::vector<double> landmark_probs) {
45  return std::transform_reduce(
46  landmark_probs.cbegin(), landmark_probs.cend(), 1.0, std::multiplies{}, [](const double v) { return v; });
47 }
48 
51  ret.sigma_bearing = Sophus::Constants<double>::pi() / 4.0; // 45 degrees
52  ret.sensor_pose_in_robot = Sophus::SE3d{Sophus::SO3d{}, Eigen::Vector3d{0.0, 0.0, 1.0}};
53  return ret;
54 }
55 
56 auto make_sensor_data(std::vector<std::tuple<double, double, double, uint32_t>> detections) {
57  const auto conversion_function = [](const auto& t) {
58  const auto [x, y, z, category] = t;
59  return LandmarkBearingDetection{Eigen::Vector3d{x, y, z}, category};
60  };
61  return detections | ranges::views::transform(conversion_function) | ranges::to<std::vector>;
62 }
63 
64 template <typename T>
66 
67 template <>
68 Sophus::SE2d get_robot_pose_in_world<Sophus::SE2d>() {
69  return Sophus::SE2d{Sophus::SO2d{-Sophus::Constants<double>::pi() / 2.0}, Eigen::Vector2d{1.0, -1.0}};
70 }
71 
72 template <>
73 Sophus::SE3d get_robot_pose_in_world<Sophus::SE3d>() {
74  return Sophus::SE3d{Sophus::SO3d::rotZ(-Sophus::Constants<double>::pi() / 2.0), Eigen::Vector3d{1.0, -1.0, 0.0}};
75 }
76 
77 template <typename T>
78 struct BearingSensorModelTests : public ::testing::Test {};
79 
80 using BearingSensorModelTestsTypes = ::testing::Types<Sensor2D, Sensor3D>;
81 
83 
85  auto sensor_model =
86  TypeParam{get_default_model_params(), LandmarkMap(default_map_boundaries, {{{1.0, -1.0, 1.0}, 0}})};
87 }
88 
89 TYPED_TEST(BearingSensorModelTests, BullsEyeDetection) {
90  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
91  // test case where the landmark is exactly where we expected it
92  auto map = LandmarkMap(default_map_boundaries, {{{1.0, -2.0, 1.0}, 0}});
93  auto sensor_model = TypeParam{get_default_model_params(), std::move(map)};
94  auto state_weighting_function = sensor_model({{{1.0, 0.0, 0.0}, 0}});
95  EXPECT_NEAR(expected_aggregate_probability({1.0}), state_weighting_function(pose), 1e-02);
96 }
97 
99  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
100  // test calls to the update_map function
101  auto map_1 = LandmarkMap(default_map_boundaries, {});
102  auto map_2 = LandmarkMap(default_map_boundaries, {{{1.0, -2.0, 1.0}, 0}});
103  auto sensor_model = TypeParam{get_default_model_params(), std::move(map_1)};
104  auto state_weighting_function = sensor_model({{{1.0, 0.0, 0.0}, 0}});
105  EXPECT_NEAR(expected_aggregate_probability({0.0}), state_weighting_function(pose), 1e-02);
106  ASSERT_NO_THROW(sensor_model.update_map(std::move(map_2)));
107  EXPECT_NEAR(expected_aggregate_probability({1.0}), state_weighting_function(pose), 1e-02);
108 }
109 
110 TYPED_TEST(BearingSensorModelTests, MultipleBullsEyeDetections) {
111  // Test multiple detections of with different ids, all perfectly matching
112  const auto sensor_model = TypeParam{
114  LandmarkMap( //
116  {
117  {{1.0, -2.0, 0.0}, 0}, // landmark 0
118  {{1.0, -2.0, 1.0}, 1}, // landmark 1
119  {{1.0, -2.0, 2.0}, 2}, // landmark 2
120  })};
121 
122  const auto state_weighting_function = sensor_model({
123  {{+1.0, +0.0, -1.0}, 0}, // landmark 0 detection
124  {{+1.0, +0.0, +0.0}, 1}, // landmark 1 detection
125  {{+1.0, +0.0, +1.0}, 2}, // landmark 2 detection
126  });
127 
128  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
129  EXPECT_NEAR(expected_aggregate_probability({1.0, 1.0, 1.0}), state_weighting_function(pose), 1e-02);
130 }
131 
133  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
134  // test case where the landmark is 1 std offset from the expected bearing
135  auto map = LandmarkMap(default_map_boundaries, {{{1.0, -2.0, 1.0}, 0}});
136  auto sensor_model = TypeParam{get_default_model_params(), std::move(map)};
137  // baseline
138  {
139  auto state_weighting_function = sensor_model({{{1.0, 0.0, 0.0}, 0}});
140  EXPECT_NEAR(expected_aggregate_probability({1.0}), state_weighting_function(pose), 1e-02);
141  }
142  // 1 std left
143  {
144  auto state_weighting_function = sensor_model({{{1.0, 1.0, 0.0}, 0}});
145  EXPECT_NEAR(expected_aggregate_probability({0.6}), state_weighting_function(pose), 1e-02);
146  }
147  // 1 std right
148  {
149  auto state_weighting_function = sensor_model({{{1.0, -1.0, 0.0}, 0}});
150  EXPECT_NEAR(expected_aggregate_probability({0.6}), state_weighting_function(pose), 1e-02);
151  }
152  // 1 std up
153  {
154  auto state_weighting_function = sensor_model({{{1.0, 0.0, 1.0}, 0}});
155  EXPECT_NEAR(expected_aggregate_probability({0.6}), state_weighting_function(pose), 1e-02);
156  }
157  // 1 std down
158  {
159  auto state_weighting_function = sensor_model({{{1.0, 0.0, -1.0}, 0}});
160  EXPECT_NEAR(expected_aggregate_probability({0.6}), state_weighting_function(pose), 1e-02);
161  }
162 }
163 
165  // perfect bearing measurement
166  auto map = LandmarkMap(default_map_boundaries, {{{1.0, -1.0, 1.0}, 0}});
167  const auto sensor_model = TypeParam{get_default_model_params(), std::move(map)};
168  const auto state_weighting_function = sensor_model({{{1.0, 0.0, 0.0}, 99}});
169  const auto pose = get_robot_pose_in_world<typename TypeParam::state_type>();
170  EXPECT_NEAR(expected_aggregate_probability({0.0}), state_weighting_function(pose), 1e-02);
171 }
172 
173 } // namespace beluga
Sophus::SO2
beluga::BearingSensorModelTestsTypes
::testing::Types< Sensor2D, Sensor3D > BearingSensorModelTestsTypes
Definition: test_bearing_sensor_model.cpp:80
Sophus::SO3
beluga::TYPED_TEST_SUITE
TYPED_TEST_SUITE(SparseGridTests, SparseGridTestCases,)
beluga::LandmarkBearingDetection
Landmark bearing detection data.
Definition: landmark_detection_types.hpp:45
landmark_detection_types.hpp
Auxiliar types for landmark models.
beluga::make_sensor_data
auto make_sensor_data(std::vector< std::tuple< double, double, double, uint32_t >> detections)
Definition: test_bearing_sensor_model.cpp:56
beluga::BearingModelParam
Parameters used to construct a BearingSensorModel instance.
Definition: bearing_sensor_model.hpp:42
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
bearing_sensor_model.hpp
Implementation of a discrete landmark bearing sensor model.
Sophus::SE3
beluga::TYPED_TEST
TYPED_TEST(SparseGridTests, CanBeConstructedEmpty)
Definition: test_sparse_value_grid.cpp:46
beluga::LandmarkMap
Basic 3D landmark map datatype.
Definition: landmark_map.hpp:39
Sophus::Constants::pi
static SOPHUS_FUNC Scalar pi()
beluga::BearingSensorModelTests
Definition: test_bearing_sensor_model.cpp:78
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
beluga::BearingModelParam::sensor_pose_in_robot
Sophus::SE3d sensor_pose_in_robot
Pose of the sensor in the robot reference frame.
Definition: bearing_sensor_model.hpp:44
landmark_map.hpp
Landmark map datatype.
beluga::BearingSensorModel
Generic bearing sensor model, for both 2D and 3D state types.
Definition: bearing_sensor_model.hpp:60
beluga::LandmarkMapBoundaries
Eigen::AlignedBox3d LandmarkMapBoundaries
Boundaries of a landmark map.
Definition: landmark_detection_types.hpp:36
beluga
The main Beluga namespace.
Definition: 3d_embedding.hpp:21


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