libstp
Robotics library for Botball
Loading...
Searching...
No Matches
localization.hpp
Go to the documentation of this file.
1#pragma once
2
6#include "hal/odometry.hpp"
8
9#include <Eigen/Core>
10#include <cstdint>
11#include <memory>
12#include <mutex>
13#include <optional>
14#include <random>
15#include <string>
16#include <vector>
17
19
21struct RecorderConfig;
22
30 enum class SurfaceKind : uint8_t {
31 Line = 0,
32 Wall = 1,
33 };
34
41
43 Eigen::Vector3d sigma{1e-3, 1e-3, 1e-3};
44 std::vector<SurfaceMeasurement> surface_measurements;
45};
46
58
77public:
78 Localization(std::shared_ptr<libstp::odometry::IOdometry> odometry,
79 LocalizationConfig config = {},
80 std::optional<libstp::map::WorldMap> tableMap = std::nullopt);
82
83 Localization(const Localization&) = delete;
87
89 [[nodiscard]] libstp::foundation::Pose getPose() const;
90
92 void observe(const Observation& obs);
93
95 void start();
96
98 void stop();
99
105
106private:
107 struct Particle {
109 double weight{1.0};
110 };
111
112 void initializeLocked(const libstp::foundation::Pose& anchorPose);
113 void initializeParticlesLocked(const libstp::foundation::Pose& anchorPose,
114 const Eigen::Vector3d& sigma);
115 void predictLocked(const libstp::foundation::Pose& odomDelta);
116 void integrateObservationLocked(const Observation& obs);
117 [[nodiscard]] double computeParticleLogWeight(const Particle& particle,
118 const Observation& obs) const;
119 void normalizeWeightsLocked();
120 void resampleLocked();
121 void updateEstimateLocked();
122 void tickLoop(libstp::threading::stop_token stop);
123
124 std::shared_ptr<libstp::odometry::IOdometry> m_odometry;
125 LocalizationConfig m_config;
126
127 mutable std::mutex m_mutex;
128 libstp::foundation::Pose m_worldPose{};
129 libstp::foundation::Pose m_lastOdom{};
130 std::vector<Particle> m_particles;
131 bool m_initialized{false};
132 std::mt19937 m_rng;
133 std::optional<libstp::map::WorldMap> m_tableMap;
134
135 // Post-run debug recorder. nullptr unless enableRecording() was called.
136 // Snapshots are produced under m_mutex from tickLoop; the recorder's
137 // own writer thread does the I/O.
138 std::unique_ptr<LocalizationRecorder> m_recorder;
139 // Pending observation snapshot for the next recorded frame. observe()
140 // appends, tickLoop drains. Mirrors the brief's contract: resync points
141 // are never lost to downsampling.
142 std::vector<Observation::SurfaceMeasurement> m_pendingObservations;
143 std::optional<libstp::foundation::Pose> m_pendingObservationPose;
144 std::optional<Eigen::Vector3d> m_pendingObservationSigma;
145 bool m_pendingObservationArrived{false};
146 bool m_pendingResampled{false};
147 std::optional<libstp::foundation::Pose> m_lastOdomDelta;
148
149 // Background worker routed through ThreadManager: dropping this handle
150 // requests stop on the libstp::threading::jthread and joins it. The destructor relies
151 // on that RAII contract; ``stop()`` calls it explicitly to keep the
152 // start()/stop() API idempotent.
154};
155
156} // namespace libstp::localization
void start()
Idempotent. The constructor already calls this; tests may re-call.
Localization & operator=(const Localization &)=delete
void observe(const Observation &obs)
Apply a sigma-weighted pose observation. Infinite-sigma axes are ignored.
void stop()
Idempotent. Joins the worker thread. The destructor calls this.
libstp::foundation::Pose getPose() const
Snapshot of the current world pose. Thread-safe.
Localization(Localization &&)=delete
Localization & operator=(Localization &&)=delete
bool enableRecording(RecorderConfig cfg)
Localization(std::shared_ptr< libstp::odometry::IOdometry > odometry, LocalizationConfig config={}, std::optional< libstp::map::WorldMap > tableMap=std::nullopt)
Localization(const Localization &)=delete
compat::stop_token stop_token
Position plus planar heading used by several motion-related modules.
Definition types.hpp:12
Sigma-weighted pose observation pushed by Resync-Steps.
std::vector< SurfaceMeasurement > surface_measurements
libstp::foundation::Pose pose