blob: 2ac3e627671a082b2c8eb569229fe4032babe843 [file] [log] [blame]
#include "frc971/control_loops/drivetrain/distance_spline.h"
#include "frc971/control_loops/drivetrain/spline.h"
namespace frc971 {
namespace control_loops {
namespace drivetrain {
DistanceSpline::DistanceSpline(const Spline &spline, int num_alpha)
: spline_(spline) {
distances_.push_back(0.0);
const double dalpha = 1.0 / static_cast<double>(num_alpha - 1);
double last_alpha = 0.0;
for (int i = 1; i < num_alpha; ++i) {
const double alpha = dalpha * i;
distances_.push_back(
distances_.back() +
GaussianQuadrature5(
[this](double alpha) { return this->spline_.DPoint(alpha).norm(); },
last_alpha, alpha));
last_alpha = alpha;
}
}
::Eigen::Matrix<double, 2, 1> DistanceSpline::DDXY(double distance) const {
const double alpha = DistanceToAlpha(distance);
const ::Eigen::Matrix<double, 2, 1> dspline_point = spline_.DPoint(alpha);
const ::Eigen::Matrix<double, 2, 1> ddspline_point = spline_.DDPoint(alpha);
const double squared_norm = dspline_point.squaredNorm();
return ddspline_point / squared_norm -
dspline_point * (dspline_point(0) * ddspline_point(0) +
dspline_point(1) * ddspline_point(1)) /
::std::pow(squared_norm, 2);
}
double DistanceSpline::DDTheta(double distance) const {
const double alpha = DistanceToAlpha(distance);
// TODO(austin): We are re-computing DPoint here even worse
const ::Eigen::Matrix<double, 2, 1> dspline_point = spline_.DPoint(alpha);
const ::Eigen::Matrix<double, 2, 1> ddspline_point = spline_.DDPoint(alpha);
const double dtheta = spline_.DTheta(alpha);
const double ddtheta = spline_.DDTheta(alpha);
const double squared_norm = dspline_point.squaredNorm();
return ddtheta / squared_norm -
dtheta * (dspline_point(0) * ddspline_point(0) +
dspline_point(1) * ddspline_point(1)) /
::std::pow(squared_norm, 2);
}
double DistanceSpline::DistanceToAlpha(double distance) const {
if (distance <= 0.0) {
return 0.0;
}
if (distance >= length()) {
return 1.0;
}
// Find the distance right below our number using a binary search.
size_t after = ::std::distance(
distances_.begin(),
::std::lower_bound(distances_.begin(), distances_.end(), distance));
size_t before = after - 1;
const double distance_step_size =
(1.0 / static_cast<double>(distances_.size() - 1));
return (distance - distances_[before]) /
(distances_[after] - distances_[before]) * distance_step_size +
static_cast<double>(before) * distance_step_size;
}
} // namespace drivetrain
} // namespace control_loops
} // namespace frc971