2022-04-24 07:21:40 -07:00
|
|
|
|
// Copyright (c) FIRST and other WPILib contributors.
|
|
|
|
|
|
// Open Source Software; you can modify and/or share it under the terms of
|
|
|
|
|
|
// the WPILib BSD license file in the root directory of this project.
|
|
|
|
|
|
|
|
|
|
|
|
#include "frc/controller/DifferentialDriveAccelerationLimiter.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include <utility>
|
|
|
|
|
|
|
2023-08-28 15:13:34 -07:00
|
|
|
|
#include <Eigen/QR>
|
2022-04-24 07:21:40 -07:00
|
|
|
|
|
|
|
|
|
|
using namespace frc;
|
|
|
|
|
|
|
|
|
|
|
|
DifferentialDriveAccelerationLimiter::DifferentialDriveAccelerationLimiter(
|
|
|
|
|
|
LinearSystem<2, 2, 2> system, units::meter_t trackwidth,
|
|
|
|
|
|
units::meters_per_second_squared_t maxLinearAccel,
|
|
|
|
|
|
units::radians_per_second_squared_t maxAngularAccel)
|
2022-10-10 11:57:37 -04:00
|
|
|
|
: DifferentialDriveAccelerationLimiter(system, trackwidth, -maxLinearAccel,
|
|
|
|
|
|
maxLinearAccel, maxAngularAccel) {}
|
|
|
|
|
|
|
|
|
|
|
|
DifferentialDriveAccelerationLimiter::DifferentialDriveAccelerationLimiter(
|
|
|
|
|
|
LinearSystem<2, 2, 2> system, units::meter_t trackwidth,
|
|
|
|
|
|
units::meters_per_second_squared_t minLinearAccel,
|
|
|
|
|
|
units::meters_per_second_squared_t maxLinearAccel,
|
|
|
|
|
|
units::radians_per_second_squared_t maxAngularAccel)
|
2022-04-24 07:21:40 -07:00
|
|
|
|
: m_system{std::move(system)},
|
|
|
|
|
|
m_trackwidth{trackwidth},
|
2022-10-10 11:57:37 -04:00
|
|
|
|
m_minLinearAccel{minLinearAccel},
|
2022-04-24 07:21:40 -07:00
|
|
|
|
m_maxLinearAccel{maxLinearAccel},
|
2022-10-10 11:57:37 -04:00
|
|
|
|
m_maxAngularAccel{maxAngularAccel} {
|
|
|
|
|
|
if (minLinearAccel > maxLinearAccel) {
|
|
|
|
|
|
throw std::invalid_argument(
|
|
|
|
|
|
"maxLinearAccel must be greater than minLinearAccel");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2022-04-24 07:21:40 -07:00
|
|
|
|
|
2022-05-01 11:01:20 -07:00
|
|
|
|
DifferentialDriveWheelVoltages DifferentialDriveAccelerationLimiter::Calculate(
|
2022-04-24 07:21:40 -07:00
|
|
|
|
units::meters_per_second_t leftVelocity,
|
|
|
|
|
|
units::meters_per_second_t rightVelocity, units::volt_t leftVoltage,
|
|
|
|
|
|
units::volt_t rightVoltage) {
|
2022-04-29 22:29:20 -07:00
|
|
|
|
Vectord<2> u{leftVoltage.value(), rightVoltage.value()};
|
2022-04-24 07:21:40 -07:00
|
|
|
|
|
|
|
|
|
|
// Find unconstrained wheel accelerations
|
2022-04-29 22:29:20 -07:00
|
|
|
|
Vectord<2> x{leftVelocity.value(), rightVelocity.value()};
|
|
|
|
|
|
Vectord<2> dxdt = m_system.A() * x + m_system.B() * u;
|
2022-04-24 07:21:40 -07:00
|
|
|
|
|
2022-07-01 06:43:57 -07:00
|
|
|
|
// Convert from wheel accelerations to linear and angular accelerations
|
|
|
|
|
|
//
|
|
|
|
|
|
// a = (dxdt(0) + dx/dt(1)) / 2
|
|
|
|
|
|
// = 0.5 dxdt(0) + 0.5 dxdt(1)
|
|
|
|
|
|
//
|
|
|
|
|
|
// α = (dxdt(1) - dxdt(0)) / trackwidth
|
|
|
|
|
|
// = -1/trackwidth dxdt(0) + 1/trackwidth dxdt(1)
|
|
|
|
|
|
//
|
|
|
|
|
|
// [a] = [ 0.5 0.5][dxdt(0)]
|
|
|
|
|
|
// [α] [-1/trackwidth 1/trackwidth][dxdt(1)]
|
|
|
|
|
|
//
|
|
|
|
|
|
// accels = M dxdt where M = [0.5, 0.5; -1/trackwidth, 1/trackwidth]
|
2022-04-29 22:29:20 -07:00
|
|
|
|
Matrixd<2, 2> M{{0.5, 0.5},
|
|
|
|
|
|
{-1.0 / m_trackwidth.value(), 1.0 / m_trackwidth.value()}};
|
|
|
|
|
|
Vectord<2> accels = M * dxdt;
|
2022-07-01 06:43:57 -07:00
|
|
|
|
|
|
|
|
|
|
// Constrain the linear and angular accelerations
|
2022-04-24 07:21:40 -07:00
|
|
|
|
if (accels(0) > m_maxLinearAccel.value()) {
|
|
|
|
|
|
accels(0) = m_maxLinearAccel.value();
|
2022-10-10 11:57:37 -04:00
|
|
|
|
} else if (accels(0) < m_minLinearAccel.value()) {
|
|
|
|
|
|
accels(0) = m_minLinearAccel.value();
|
2022-04-24 07:21:40 -07:00
|
|
|
|
}
|
|
|
|
|
|
if (accels(1) > m_maxAngularAccel.value()) {
|
|
|
|
|
|
accels(1) = m_maxAngularAccel.value();
|
|
|
|
|
|
} else if (accels(1) < -m_maxAngularAccel.value()) {
|
|
|
|
|
|
accels(1) = -m_maxAngularAccel.value();
|
|
|
|
|
|
}
|
2022-07-01 06:43:57 -07:00
|
|
|
|
|
|
|
|
|
|
// Convert the constrained linear and angular accelerations back to wheel
|
|
|
|
|
|
// accelerations
|
2022-04-24 07:21:40 -07:00
|
|
|
|
dxdt = M.householderQr().solve(accels);
|
|
|
|
|
|
|
|
|
|
|
|
// Find voltages for the given wheel accelerations
|
2022-07-01 06:43:57 -07:00
|
|
|
|
//
|
2022-04-24 07:21:40 -07:00
|
|
|
|
// dx/dt = Ax + Bu
|
|
|
|
|
|
// u = B⁻¹(dx/dt - Ax)
|
|
|
|
|
|
u = m_system.B().householderQr().solve(dxdt - m_system.A() * x);
|
|
|
|
|
|
|
|
|
|
|
|
return {units::volt_t{u(0)}, units::volt_t{u(1)}};
|
|
|
|
|
|
}
|