WPILibC++ 2025.2.1
Loading...
Searching...
No Matches
CubicHermiteSpline.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <wpi/SymbolExports.h>
8#include <wpi/array.h>
9
10#include "frc/EigenCore.h"
11#include "frc/spline/Spline.h"
12
13namespace frc {
14/**
15 * Represents a hermite spline of degree 3.
16 */
18 public:
19 /**
20 * Constructs a cubic hermite spline with the specified control vectors. Each
21 * control vector contains info about the location of the point and its first
22 * derivative.
23 *
24 * @param xInitialControlVector The control vector for the initial point in
25 * the x dimension.
26 * @param xFinalControlVector The control vector for the final point in
27 * the x dimension.
28 * @param yInitialControlVector The control vector for the initial point in
29 * the y dimension.
30 * @param yFinalControlVector The control vector for the final point in
31 * the y dimension.
32 */
34 wpi::array<double, 2> xFinalControlVector,
35 wpi::array<double, 2> yInitialControlVector,
36 wpi::array<double, 2> yFinalControlVector)
37 : m_initialControlVector{xInitialControlVector, yInitialControlVector},
38 m_finalControlVector{xFinalControlVector, yFinalControlVector} {
39 const auto hermite = MakeHermiteBasis();
40 const auto x =
41 ControlVectorFromArrays(xInitialControlVector, xFinalControlVector);
42 const auto y =
43 ControlVectorFromArrays(yInitialControlVector, yFinalControlVector);
44
45 // Populate first two rows with coefficients.
46 m_coefficients.template block<1, 4>(0, 0) = hermite * x;
47 m_coefficients.template block<1, 4>(1, 0) = hermite * y;
48
49 // Populate Row 2 and Row 3 with the derivatives of the equations above.
50 // Then populate row 4 and 5 with the second derivatives.
51 for (int i = 0; i < 4; i++) {
52 // Here, we are multiplying by (3 - i) to manually take the derivative.
53 // The power of the term in index 0 is 3, index 1 is 2 and so on. To find
54 // the coefficient of the derivative, we can use the power rule and
55 // multiply the existing coefficient by its power.
56 m_coefficients.template block<2, 1>(2, i) =
57 m_coefficients.template block<2, 1>(0, i) * (3 - i);
58 }
59
60 for (int i = 0; i < 3; i++) {
61 // Here, we are multiplying by (2 - i) to manually take the derivative.
62 // The power of the term in index 0 is 2, index 1 is 1 and so on. To find
63 // the coefficient of the derivative, we can use the power rule and
64 // multiply the existing coefficient by its power.
65 m_coefficients.template block<2, 1>(4, i) =
66 m_coefficients.template block<2, 1>(2, i) * (2 - i);
67 }
68 }
69
70 /**
71 * Returns the coefficients matrix.
72 * @return The coefficients matrix.
73 */
74 Matrixd<6, 3 + 1> Coefficients() const override { return m_coefficients; }
75
76 /**
77 * Returns the initial control vector that created this spline.
78 *
79 * @return The initial control vector that created this spline.
80 */
81 const ControlVector& GetInitialControlVector() const override {
82 return m_initialControlVector;
83 }
84
85 /**
86 * Returns the final control vector that created this spline.
87 *
88 * @return The final control vector that created this spline.
89 */
90 const ControlVector& GetFinalControlVector() const override {
91 return m_finalControlVector;
92 }
93
94 private:
95 Matrixd<6, 4> m_coefficients = Matrixd<6, 4>::Zero();
96
97 ControlVector m_initialControlVector;
98 ControlVector m_finalControlVector;
99
100 /**
101 * Returns the hermite basis matrix for cubic hermite spline interpolation.
102 * @return The hermite basis matrix for cubic hermite spline interpolation.
103 */
104 static constexpr Eigen::Matrix4d MakeHermiteBasis() {
105 // Given P(i), P'(i), P(i+1), P'(i+1), the control vectors, we want to find
106 // the coefficients of the spline P(t) = a₃t³ + a₂t² + a₁t + a₀.
107 //
108 // P(i) = P(0) = a₀
109 // P'(i) = P'(0) = a₁
110 // P(i+1) = P(1) = a₃ + a₂ + a₁ + a₀
111 // P'(i+1) = P'(1) = 3a₃ + 2a₂ + a₁
112 //
113 // [P(i) ] = [0 0 0 1][a₃]
114 // [P'(i) ] = [0 0 1 0][a₂]
115 // [P(i+1) ] = [1 1 1 1][a₁]
116 // [P'(i+1)] = [3 2 1 0][a₀]
117 //
118 // To solve for the coefficients, we can invert the 4x4 matrix and move it
119 // to the other side of the equation.
120 //
121 // [a₃] = [ 2 1 -2 1][P(i) ]
122 // [a₂] = [-3 -2 3 -1][P'(i) ]
123 // [a₁] = [ 0 1 0 0][P(i+1) ]
124 // [a₀] = [ 1 0 0 0][P'(i+1)]
125 return Eigen::Matrix4d{{+2.0, +1.0, -2.0, +1.0},
126 {-3.0, -2.0, +3.0, -1.0},
127 {+0.0, +1.0, +0.0, +0.0},
128 {+1.0, +0.0, +0.0, +0.0}};
129 }
130
131 /**
132 * Returns the control vector for each dimension as a matrix from the
133 * user-provided arrays in the constructor.
134 *
135 * @param initialVector The control vector for the initial point.
136 * @param finalVector The control vector for the final point.
137 *
138 * @return The control vector matrix for a dimension.
139 */
140 static constexpr Eigen::Vector4d ControlVectorFromArrays(
141 wpi::array<double, 2> initialVector, wpi::array<double, 2> finalVector) {
142 return Eigen::Vector4d{{initialVector[0]},
143 {initialVector[1]},
144 {finalVector[0]},
145 {finalVector[1]}};
146 }
147};
148} // namespace frc
149
#define WPILIB_DLLEXPORT
Definition SymbolExports.h:36
Represents a hermite spline of degree 3.
Definition CubicHermiteSpline.h:17
const ControlVector & GetInitialControlVector() const override
Returns the initial control vector that created this spline.
Definition CubicHermiteSpline.h:81
Matrixd< 6, 3+1 > Coefficients() const override
Returns the coefficients matrix.
Definition CubicHermiteSpline.h:74
CubicHermiteSpline(wpi::array< double, 2 > xInitialControlVector, wpi::array< double, 2 > xFinalControlVector, wpi::array< double, 2 > yInitialControlVector, wpi::array< double, 2 > yFinalControlVector)
Constructs a cubic hermite spline with the specified control vectors.
Definition CubicHermiteSpline.h:33
const ControlVector & GetFinalControlVector() const override
Returns the final control vector that created this spline.
Definition CubicHermiteSpline.h:90
Represents a two-dimensional parametric spline that interpolates between two points.
Definition Spline.h:27
This class is a wrapper around std::array that does compile time size checking.
Definition array.h:26
Definition CAN.h:11
Eigen::Matrix< double, Rows, Cols, Options, MaxRows, MaxCols > Matrixd
Definition EigenCore.h:21