This commit is contained in:
Duong Vu
2026-07-22 10:42:09 +07:00
parent 4bb8ef9a2b
commit e1cce6e0ea
65 changed files with 3803 additions and 0 deletions

View File

@@ -0,0 +1,204 @@
#pragma once
#include <cstdint>
#include <math.h>
#include <boost/accumulators/accumulators.hpp>
#include <boost/accumulators/statistics/stats.hpp>
#include <boost/accumulators/statistics/rolling_mean.hpp>
#include <boost/function.hpp>
namespace differential
{
namespace bacc = boost::accumulators;
/**
* \brief The Odometry class handles odometry readings
* (2D pose and velocity with related timestamp)
*/
class Odometry
{
public:
/// Integration function, used to integrate the odometry:
typedef boost::function<void(double, double)> IntegrationFunction;
/**
* \brief Constructor
* Timestamp will get the current time value
* Value will be set to zero
* \param velocity_rolling_window_size Rolling window size used to compute the velocity mean
*/
Odometry(size_t velocity_rolling_window_size = 10);
/**
* \brief Initialize the odometry
* \param time Current time
*/
void init(const double &time);
/**
* \brief Updates the odometry class with latest wheel angular velocities
* \param left_vel Left wheel angular velocity [rad/s]
* \param right_vel Right wheel angular velocity [rad/s]
* \param time Current time
* \return true if the odometry is actually updated
*/
bool updateWheel(double left_vel, double right_vel, const double &time);
/**
* \brief Updates odometry from cumulative encoder tick counts
*
* Converts tick deltas to wheel arc lengths, then integrates pose with the
* same exact/RK2 path as updateWheel. The first call after init() only
* seeds the previous tick counts and returns false.
*
* Caller should unwrap hardware counter overflow into a monotonic int64
* cumulative count before calling.
*
* \param left_ticks Cumulative left wheel ticks (after gearbox, wheel side)
* \param right_ticks Cumulative right wheel ticks (after gearbox, wheel side)
* \param time Current time [s]
* \return true if the odometry is actually updated
*/
bool updateTicks(std::int64_t left_ticks, std::int64_t right_ticks, const double &time);
/**
* \brief Updates the odometry class with latest velocity command
* \param linear Linear velocity [m/s]
* \param angular Angular velocity [rad/s]
* \param time Current time
*/
void updateOdom(double linear, double angular, const double &time);
/**
* \brief heading getter
* \return heading [rad]
*/
double getHeading() const
{
return heading_;
}
/**
* \brief x position getter
* \return x position [m]
*/
double getX() const
{
return x_;
}
/**
* \brief y position getter
* \return y position [m]
*/
double getY() const
{
return y_;
}
/**
* \brief linear velocity getter
* \return linear velocity [m/s]
*/
double getLinear() const
{
return linear_;
}
/**
* \brief angular velocity getter
* \return angular velocity [rad/s]
*/
double getAngular() const
{
return angular_;
}
/**
* \brief Sets the wheel parameters: radius and separation
* \param wheel_separation Separation between left and right wheels [m]
* \param left_wheel_radius Left wheel radius [m]
* \param right_wheel_radius Right wheel radius [m]
*/
void setWheelParams(double wheel_separation, double left_wheel_radius, double right_wheel_radius);
/**
* \brief Sets encoder resolution for both wheels (same CPR)
* \param ticks_per_revolution Ticks per wheel revolution (wheel side)
*/
void setEncoderParams(double ticks_per_revolution);
/**
* \brief Sets encoder resolution per wheel
* \param left_ticks_per_revolution Left wheel ticks per revolution
* \param right_ticks_per_revolution Right wheel ticks per revolution
*/
void setEncoderParams(double left_ticks_per_revolution, double right_ticks_per_revolution);
/**
* \brief Velocity rolling window size setter
* \param velocity_rolling_window_size Velocity rolling window size
*/
void setVelocityRollingWindowSize(size_t velocity_rolling_window_size);
private:
/// Rolling mean accumulator and window:
typedef bacc::accumulator_set<double, bacc::stats<bacc::tag::rolling_mean> > RollingMeanAcc;
typedef bacc::tag::rolling_window RollingWindow;
/**
* \brief Integrates the velocities (linear and angular) using 2nd order Runge-Kutta
* \param linear Linear displacement [m]
* \param angular Angular displacement [rad]
*/
void integrateRungeKutta2(double linear, double angular);
/**
* \brief Integrates the velocities (linear and angular) using exact method
* \param linear Linear displacement [m]
* \param angular Angular displacement [rad]
*/
void integrateExact(double linear, double angular);
/**
* \brief Reset linear and angular accumulators
*/
void resetAccumulators();
/// Current timestamp:
double timestamp_;
/// Current pose:
double x_; // [m]
double y_; // [m]
double heading_; // [rad]
/// Current velocity:
double linear_; // [m/s]
double angular_; // [rad/s]
/// Wheel kinematic parameters [m]:
double wheel_separation_;
double left_wheel_radius_;
double right_wheel_radius_;
/// Encoder resolution [ticks / wheel revolution]:
double left_ticks_per_revolution_;
double right_ticks_per_revolution_;
/// Previous cumulative tick counts for delta computation:
bool ticks_initialized_;
std::int64_t left_ticks_prev_;
std::int64_t right_ticks_prev_;
/// Rolling mean accumulators for the linear and angular velocities:
size_t velocity_rolling_window_size_;
RollingMeanAcc linear_acc_;
RollingMeanAcc angular_acc_;
/// Integration function, used to integrate the odometry:
IntegrationFunction integrate_fun_;
};
}