205 lines
5.9 KiB
C++
205 lines
5.9 KiB
C++
#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_;
|
|
};
|
|
}
|