Program Listing for File amcl.hpp
↰ Return to documentation for file (include/beluga_ros/amcl.hpp)
// Copyright 2024 Ekumen, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef BELUGA_ROS_AMCL_HPP
#define BELUGA_ROS_AMCL_HPP
#include <optional>
#include <utility>
#include <variant>
#include <range/v3/range/conversion.hpp>
#include <range/v3/view/take_exactly.hpp>
#include <sophus/se2.hpp>
#include <beluga/algorithm/spatial_hash.hpp>
#include <beluga/algorithm/thrun_recovery_probability_estimator.hpp>
#include <beluga/containers.hpp>
#include <beluga/motion.hpp>
#include <beluga/policies.hpp>
#include <beluga/random.hpp>
#include <beluga/sensor.hpp>
#include <beluga/views/sample.hpp>
#include <beluga_ros/laser_scan.hpp>
#include <beluga_ros/occupancy_grid.hpp>
namespace beluga_ros {
struct AmclParams {
double update_min_d = 0.25;
double update_min_a = 0.2;
std::size_t resample_interval = 1UL;
bool selective_resampling = false;
std::size_t min_particles = 500UL;
std::size_t max_particles = 2000UL;
double alpha_slow = 0.001;
double alpha_fast = 0.1;
double kld_epsilon = 0.05;
double kld_z = 3.0;
double spatial_resolution_x = 0.5;
double spatial_resolution_y = 0.5;
double spatial_resolution_theta = 10 * Sophus::Constants<double>::pi() / 180;
};
class Amcl {
public:
using particle_type = std::tuple<Sophus::SE2d, beluga::Weight>;
using motion_model_variant = std::variant<
beluga::DifferentialDriveModel2d, //
beluga::OmnidirectionalDriveModel, //
beluga::StationaryModel>;
using sensor_model_variant = std::variant<
beluga::LikelihoodFieldModel<beluga_ros::OccupancyGrid>, //
beluga::BeamSensorModel<beluga_ros::OccupancyGrid>>;
using execution_policy_variant = std::variant<std::execution::sequenced_policy, std::execution::parallel_policy>;
Amcl(
beluga_ros::OccupancyGrid map,
motion_model_variant motion_model,
sensor_model_variant sensor_model,
const AmclParams& params,
execution_policy_variant execution_policy);
[[nodiscard]] const auto& particles() const { return particles_; }
template <class Distribution>
void initialize(Distribution distribution) {
particles_ = beluga::views::sample(std::move(distribution)) | //
ranges::views::transform(beluga::make_from_state<particle_type>) | //
ranges::views::take_exactly(params_.max_particles) | //
ranges::to<beluga::TupleVector>;
force_update_ = true;
}
void initialize(Sophus::SE2d pose, Sophus::Matrix3d covariance) {
initialize(beluga::MultivariateNormalDistribution{pose, covariance});
}
void initialize_from_map() { initialize(std::ref(map_distribution_)); }
void update_map(beluga_ros::OccupancyGrid map);
auto update(Sophus::SE2d base_pose_in_odom, beluga_ros::LaserScan laser_scan)
-> std::optional<std::pair<Sophus::SE2d, Sophus::Matrix3d>>;
void force_update() { force_update_ = true; }
private:
beluga::TupleVector<particle_type> particles_;
AmclParams params_;
beluga::MultivariateUniformDistribution<Sophus::SE2d, beluga_ros::OccupancyGrid> map_distribution_;
motion_model_variant motion_model_;
sensor_model_variant sensor_model_;
execution_policy_variant execution_policy_;
beluga::spatial_hash<Sophus::SE2d> spatial_hasher_;
beluga::ThrunRecoveryProbabilityEstimator random_probability_estimator_;
beluga::any_policy<Sophus::SE2d> update_policy_;
beluga::any_policy<decltype(particles_)> resample_policy_;
beluga::RollingWindow<Sophus::SE2d, 2> control_action_window_;
bool force_update_{true};
};
} // namespace beluga_ros
#endif // BELUGA_ROS_AMCL_HPP