CTRE Phoenix 6 C++ 26.70.0-alpha-2
Loading...
Searching...
No Matches
LinearPath.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) Cross The Road Electronics.  All rights reserved.
3 * License information can be found in CTRE_LICENSE.txt
4 * For support and suggestions contact support@ctr-electronics.com or file
5 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
6 */
7#pragma once
8
10#include <wpi/math/trajectory/TrapezoidProfile.hpp>
11
12namespace ctre {
13namespace phoenix6 {
14namespace swerve {
15
16/**
17 * \brief A linear path for a holonomic drivetrain (i.e. swerve or mechanum).
18 * This generates profiled setpoints for the robot along a straight line
19 * based on trapezoidal velocity constraints (using wpi#math#TrapezoidProfile).
20 *
21 * Initialization:
22 * \code{.cpp}
23 * LinearPath path{
24 * TrapezoidProfile::Constraints{kMaxV, kMaxA},
25 * TrapezoidProfile::Constraints{kMaxOmega, kMaxAlpha}
26 * };
27 * LinearPath::State current{initialPose, initialFieldSpeeds};
28 * \endcode
29 *
30 * Run on update:
31 * \code{.cpp}
32 * current = path.Calculate(timeSincePreviousUpdate, current, targetPose);
33 * \endcode
34 */
36public:
37 /** \brief Path state. */
38 struct State {
39 /** \brief The pose at this state. */
40 Pose2d pose{};
41 /** \brief The field-centric velocity at this state. */
42 ChassisVelocities velocity{};
43
44 constexpr bool operator==(State const &) const = default;
45 };
46
47private:
48 wpi::math::TrapezoidProfile<wpi::units::meters> linearProfile;
49 wpi::math::TrapezoidProfile<wpi::units::radians> angularProfile;
50
51 Pose2d initialPose{};
52 Rotation2d heading{};
53
54 wpi::math::TrapezoidProfile<wpi::units::meters>::State linearGoal{};
55 wpi::math::TrapezoidProfile<wpi::units::meters>::State linearStart{};
56
57 wpi::math::TrapezoidProfile<wpi::units::radians>::State angularGoal{};
58 wpi::math::TrapezoidProfile<wpi::units::radians>::State angularStart{};
59
60 /**
61 * \brief Calculates the component of the velocity in the direction of travel.
62 *
63 * \param velocity The field-centric chassis velocity
64 * \param heading The heading of the direction of travel
65 * \returns Component of velocity in the direction of the heading
66 */
67 static constexpr wpi::units::meters_per_second_t CalculateVelocityAtHeading(ChassisVelocities const &velocity, Rotation2d const &heading)
68 {
69 // vel = <vx, vy> ⋅ <cos(heading), sin(heading)>
70 // vel = vx * cos(heading) + vy * sin(heading)
71 return velocity.vx * heading.Cos() + velocity.vy * heading.Sin();
72 }
73
74 /**
75 * \brief Sets the current and goal states of the linear path.
76 *
77 * \param current The current state
78 * \param goal The desired pose when the path is complete
79 */
80 constexpr void SetState(State const &current, Pose2d const &goal)
81 {
82 initialPose = current.pose;
83
84 {
85 // pull out the translation from our initial pose to the target
86 auto const translation = goal.Translation() - initialPose.Translation();
87 // pull out distance and heading to the target
88 auto const distance = translation.Norm();
89 heading = translation.Angle().value_or(Rotation2d{});
90
91 linearGoal = wpi::math::TrapezoidProfile<wpi::units::meters>::State{distance, 0_mps};
92 }
93
94 {
95 // start at current velocity in the direction of travel
96 auto const vel = CalculateVelocityAtHeading(current.velocity, heading);
97 linearStart = wpi::math::TrapezoidProfile<wpi::units::meters>::State{0_m, vel};
98 }
99
100 angularStart = wpi::math::TrapezoidProfile<wpi::units::radians>::State{
101 current.pose.Rotation().Radians(),
102 current.velocity.omega
103 };
104 // wrap the angular goal so we take the shortest path
105 angularGoal = wpi::math::TrapezoidProfile<wpi::units::radians>::State{
106 current.pose.Rotation().Radians() +
107 (goal.Rotation() - current.pose.Rotation()).Radians(),
108 0_rad_per_s
109 };
110 }
111
112 /**
113 * \brief Calculates the pose and velocity of the path at a time t where
114 * the current state is at t = 0.
115 *
116 * \param t How long to advance from the current state to the desired state
117 * \returns The pose and velocity of the profile at time t
118 */
119 constexpr State Calculate(wpi::units::second_t t)
120 {
121 // calculate our new distance and velocity in the desired direction of travel
122 auto const linearState = linearProfile.Calculate(t, linearStart, linearGoal);
123 // calculate our new heading and rotational rate
124 auto const angularState = angularProfile.Calculate(t, angularStart, angularGoal);
125
126 // x is m_state * cos(heading), y is m_state * sin(heading)
127 Pose2d pose{
128 initialPose.X() + linearState.position * heading.Cos(),
129 initialPose.Y() + linearState.position * heading.Sin(),
130 {angularState.position}
131 };
132 ChassisVelocities velocity{
133 linearState.velocity * heading.Cos(),
134 linearState.velocity * heading.Sin(),
135 angularState.velocity
136 };
137 return {std::move(pose), std::move(velocity)};
138 }
139
140public:
141 /**
142 * \brief Constructs a linear path.
143 *
144 * \param linear The constraints on the profile linear motion
145 * \param angular The constraints on the profile angular motion
146 */
147 constexpr LinearPath(
148 wpi::math::TrapezoidProfile<wpi::units::meters>::Constraints linear,
149 wpi::math::TrapezoidProfile<wpi::units::radians>::Constraints angular
150 ) :
151 linearProfile{std::move(linear)},
152 angularProfile{std::move(angular)}
153 {}
154
155 /**
156 * \brief Calculates the pose and velocity of the path at a time t where
157 * the current state is at t = 0.
158 *
159 * \param t How long to advance from the current state to the desired state
160 * \param current The current state
161 * \param goal The desired pose when the path is complete
162 * \returns The pose and velocity of the profile at time t
163 */
164 constexpr State Calculate(wpi::units::second_t t, State const &current, Pose2d const &goal)
165 {
166 SetState(current, goal);
167 return Calculate(t);
168 }
169
170 /**
171 * \brief Returns the duration of the path.
172 *
173 * \returns The duration of the path
174 */
175 constexpr wpi::units::second_t Duration() const
176 {
177 return wpi::units::math::max(
178 linearProfile.Duration(),
179 angularProfile.Duration()
180 );
181 }
182
183 /**
184 * \brief Returns true if the profile has reached the goal.
185 *
186 * The profile has reached the goal if the time since the profile
187 * started has exceeded the profile's total time.
188 *
189 * \param t The time since the beginning of the profile
190 * \returns true if the profile has reached the goal
191 */
192 constexpr bool IsFinished(wpi::units::second_t t) const
193 {
194 return t >= Duration();
195 }
196};
197
198}
199}
200}
constexpr LinearPath(wpi::math::TrapezoidProfile< wpi::units::meters >::Constraints linear, wpi::math::TrapezoidProfile< wpi::units::radians >::Constraints angular)
Constructs a linear path.
Definition LinearPath.hpp:147
constexpr wpi::units::second_t Duration() const
Returns the duration of the path.
Definition LinearPath.hpp:175
constexpr bool IsFinished(wpi::units::second_t t) const
Returns true if the profile has reached the goal.
Definition LinearPath.hpp:192
constexpr State Calculate(wpi::units::second_t t, State const &current, Pose2d const &goal)
Calculates the pose and velocity of the path at a time t where the current state is at t = 0.
Definition LinearPath.hpp:164
Definition SwerveModule.hpp:28
Definition ExternalFeedbackConfigs.hpp:16
Definition motor_constants.h:14
Path state.
Definition LinearPath.hpp:38
constexpr bool operator==(State const &) const =default
ChassisVelocities velocity
The field-centric velocity at this state.
Definition LinearPath.hpp:42
Pose2d pose
The pose at this state.
Definition LinearPath.hpp:40