[wpimath] Add geometry classes for Rectangle2d and Ellipse2d (#6555)

Co-authored-by: Tyler Veness <calcmogul@gmail.com>
This commit is contained in:
Brendan Raykoff
2024-06-04 21:27:32 -04:00
committed by GitHub
parent afaf7e2c3f
commit 8def7b2222
41 changed files with 3042 additions and 26 deletions

View File

@@ -0,0 +1,57 @@
// 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/geometry/Ellipse2d.h"
#include <sleipnir/optimization/OptimizationProblem.hpp>
#include "geometry2d.pb.h"
using namespace frc;
units::meter_t Ellipse2d::Distance(const Translation2d& point) const {
return FindNearestPoint(point).Distance(point);
}
Translation2d Ellipse2d::FindNearestPoint(const Translation2d& point) const {
// Check if already in ellipse
if (Contains(point)) {
return point;
}
// Rotate the point by the inverse of the ellipse's rotation
auto rotPoint =
point.RotateAround(m_center.Translation(), -m_center.Rotation());
// Find nearest point
{
namespace slp = sleipnir;
sleipnir::OptimizationProblem problem;
// Point on ellipse
auto x = problem.DecisionVariable();
x.SetValue(rotPoint.X().value());
auto y = problem.DecisionVariable();
y.SetValue(rotPoint.Y().value());
problem.Minimize(slp::pow(x - rotPoint.X().value(), 2) +
slp::pow(y - rotPoint.Y().value(), 2));
// (x x_c)²/a² + (y y_c)²/b² = 1
problem.SubjectTo(slp::pow(x - m_center.X().value(), 2) /
(m_xSemiAxis.value() * m_xSemiAxis.value()) +
slp::pow(y - m_center.Y().value(), 2) /
(m_ySemiAxis.value() * m_ySemiAxis.value()) ==
1);
problem.Solve();
rotPoint = frc::Translation2d{units::meter_t{x.Value()},
units::meter_t{y.Value()}};
}
// Undo rotation
return rotPoint.RotateAround(m_center.Translation(), m_center.Rotation());
}