2020-12-26 14:12:05 -08: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.
|
2020-11-28 17:35:35 -05:00
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2021-05-26 00:09:36 -07:00
|
|
|
#include <wpi/numbers>
|
2020-11-28 17:35:35 -05:00
|
|
|
|
|
|
|
|
#include "Eigen/Core"
|
2021-01-01 16:22:00 -08:00
|
|
|
#include "frc/MathUtil.h"
|
2020-11-28 17:35:35 -05:00
|
|
|
|
|
|
|
|
namespace frc {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Subtracts a and b while normalizing the resulting value in the selected row
|
|
|
|
|
* as if it were an angle.
|
|
|
|
|
*
|
|
|
|
|
* @param a A vector to subtract from.
|
|
|
|
|
* @param b A vector to subtract with.
|
|
|
|
|
* @param angleStateIdx The row containing angles to be normalized.
|
|
|
|
|
*/
|
|
|
|
|
template <int States>
|
2021-08-19 00:23:48 -07:00
|
|
|
Eigen::Vector<double, States> AngleResidual(
|
|
|
|
|
const Eigen::Vector<double, States>& a,
|
|
|
|
|
const Eigen::Vector<double, States>& b, int angleStateIdx) {
|
|
|
|
|
Eigen::Vector<double, States> ret = a - b;
|
2021-01-01 16:22:00 -08:00
|
|
|
ret[angleStateIdx] =
|
2021-10-25 08:58:12 -07:00
|
|
|
AngleModulus(units::radian_t{ret[angleStateIdx]}).value();
|
2020-11-28 17:35:35 -05:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a function that subtracts two vectors while normalizing the resulting
|
|
|
|
|
* value in the selected row as if it were an angle.
|
|
|
|
|
*
|
|
|
|
|
* @param angleStateIdx The row containing angles to be normalized.
|
|
|
|
|
*/
|
|
|
|
|
template <int States>
|
2021-08-19 00:23:48 -07:00
|
|
|
std::function<Eigen::Vector<double, States>(
|
|
|
|
|
const Eigen::Vector<double, States>&, const Eigen::Vector<double, States>&)>
|
2020-11-28 17:35:35 -05:00
|
|
|
AngleResidual(int angleStateIdx) {
|
|
|
|
|
return [=](auto a, auto b) {
|
|
|
|
|
return AngleResidual<States>(a, b, angleStateIdx);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Adds a and b while normalizing the resulting value in the selected row as an
|
|
|
|
|
* angle.
|
|
|
|
|
*
|
|
|
|
|
* @param a A vector to add with.
|
|
|
|
|
* @param b A vector to add with.
|
|
|
|
|
* @param angleStateIdx The row containing angles to be normalized.
|
|
|
|
|
*/
|
|
|
|
|
template <int States>
|
2021-08-19 00:23:48 -07:00
|
|
|
Eigen::Vector<double, States> AngleAdd(const Eigen::Vector<double, States>& a,
|
|
|
|
|
const Eigen::Vector<double, States>& b,
|
|
|
|
|
int angleStateIdx) {
|
|
|
|
|
Eigen::Vector<double, States> ret = a + b;
|
2021-01-01 16:22:00 -08:00
|
|
|
ret[angleStateIdx] =
|
2021-05-26 00:09:36 -07:00
|
|
|
InputModulus(ret[angleStateIdx], -wpi::numbers::pi, wpi::numbers::pi);
|
2020-11-28 17:35:35 -05:00
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a function that adds two vectors while normalizing the resulting
|
|
|
|
|
* value in the selected row as an angle.
|
|
|
|
|
*
|
|
|
|
|
* @param angleStateIdx The row containing angles to be normalized.
|
|
|
|
|
*/
|
|
|
|
|
template <int States>
|
2021-08-19 00:23:48 -07:00
|
|
|
std::function<Eigen::Vector<double, States>(
|
|
|
|
|
const Eigen::Vector<double, States>&, const Eigen::Vector<double, States>&)>
|
2020-11-28 17:35:35 -05:00
|
|
|
AngleAdd(int angleStateIdx) {
|
|
|
|
|
return [=](auto a, auto b) { return AngleAdd<States>(a, b, angleStateIdx); };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Computes the mean of sigmas with the weights Wm while computing a special
|
|
|
|
|
* angle mean for a select row.
|
|
|
|
|
*
|
|
|
|
|
* @param sigmas Sigma points.
|
|
|
|
|
* @param Wm Weights for the mean.
|
|
|
|
|
* @param angleStateIdx The row containing the angles.
|
|
|
|
|
*/
|
|
|
|
|
template <int CovDim, int States>
|
2021-08-19 00:23:48 -07:00
|
|
|
Eigen::Vector<double, CovDim> AngleMean(
|
2020-11-28 17:35:35 -05:00
|
|
|
const Eigen::Matrix<double, CovDim, 2 * States + 1>& sigmas,
|
2021-08-19 00:23:48 -07:00
|
|
|
const Eigen::Vector<double, 2 * States + 1>& Wm, int angleStatesIdx) {
|
2020-11-28 17:35:35 -05:00
|
|
|
double sumSin = sigmas.row(angleStatesIdx)
|
|
|
|
|
.unaryExpr([](auto it) { return std::sin(it); })
|
|
|
|
|
.sum();
|
|
|
|
|
double sumCos = sigmas.row(angleStatesIdx)
|
|
|
|
|
.unaryExpr([](auto it) { return std::cos(it); })
|
|
|
|
|
.sum();
|
|
|
|
|
|
2021-08-19 00:23:48 -07:00
|
|
|
Eigen::Vector<double, CovDim> ret = sigmas * Wm;
|
2020-11-28 17:35:35 -05:00
|
|
|
ret[angleStatesIdx] = std::atan2(sumSin, sumCos);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a function that computes the mean of sigmas with the weights Wm while
|
|
|
|
|
* computing a special angle mean for a select row.
|
|
|
|
|
*
|
|
|
|
|
* @param angleStateIdx The row containing the angles.
|
|
|
|
|
*/
|
|
|
|
|
template <int CovDim, int States>
|
2021-08-19 00:23:48 -07:00
|
|
|
std::function<Eigen::Vector<double, CovDim>(
|
2020-11-28 17:35:35 -05:00
|
|
|
const Eigen::Matrix<double, CovDim, 2 * States + 1>&,
|
2021-08-19 00:23:48 -07:00
|
|
|
const Eigen::Vector<double, 2 * States + 1>&)>
|
2020-11-28 17:35:35 -05:00
|
|
|
AngleMean(int angleStateIdx) {
|
|
|
|
|
return [=](auto sigmas, auto Wm) {
|
|
|
|
|
return AngleMean<CovDim, States>(sigmas, Wm, angleStateIdx);
|
|
|
|
|
};
|
|
|
|
|
}
|
2021-01-01 16:22:00 -08:00
|
|
|
|
2020-11-28 17:35:35 -05:00
|
|
|
} // namespace frc
|