CTRE Phoenix 6 C++ 26.0.0-beta-1
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 "frc/trajectory/TrapezoidProfile.h"
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 frc#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 speeds at this state. */
42 ChassisSpeeds speeds{};
43
44 constexpr bool operator==(State const &) const = default;
45 };
46
47private:
48 frc::TrapezoidProfile<units::meters> linearProfile;
49 frc::TrapezoidProfile<units::radians> angularProfile;
50
51 Pose2d initialPose{};
52 Rotation2d heading{};
53
54 frc::TrapezoidProfile<units::meters>::State linearGoal{};
55 frc::TrapezoidProfile<units::meters>::State linearStart{};
56
57 frc::TrapezoidProfile<units::radians>::State angularGoal{};
58 frc::TrapezoidProfile<units::radians>::State angularStart{};
59
60 /**
61 * \brief Calculates the component of the velocity in the direction of travel.
62 *
63 * \param speeds The field-centric chassis speeds
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 units::meters_per_second_t CalculateVelocityAtHeading(ChassisSpeeds const &speeds, Rotation2d const &heading)
68 {
69 // vel = <vx, vy> ⋅ <cos(heading), sin(heading)>
70 // vel = vx * cos(heading) + vy * sin(heading)
71 return speeds.vx * heading.Cos() + speeds.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 if (distance > 1e-6_m) {
90 heading = translation.Angle();
91 } else {
92 heading = {};
93 }
94
95 linearGoal = frc::TrapezoidProfile<units::meters>::State{distance, 0_mps};
96 }
97
98 {
99 // start at current velocity in the direction of travel
100 auto const vel = CalculateVelocityAtHeading(current.speeds, heading);
101 linearStart = frc::TrapezoidProfile<units::meters>::State{0_m, vel};
102 }
103
104 angularStart = frc::TrapezoidProfile<units::radians>::State{
105 current.pose.Rotation().Radians(),
106 current.speeds.omega
107 };
108 // wrap the angular goal so we take the shortest path
109 angularGoal = frc::TrapezoidProfile<units::radians>::State{
110 current.pose.Rotation().Radians() +
111 (goal.Rotation() - current.pose.Rotation()).Radians(),
112 0_rad_per_s
113 };
114 }
115
116 /**
117 * \brief Calculates the pose and speeds of the path at a time t where
118 * the current state is at t = 0.
119 *
120 * \param t How long to advance from the current state to the desired state
121 * \returns The pose and speeds of the profile at time t
122 */
123 constexpr State Calculate(units::second_t t)
124 {
125 // calculate our new distance and velocity in the desired direction of travel
126 auto const linearState = linearProfile.Calculate(t, linearStart, linearGoal);
127 // calculate our new heading and rotational rate
128 auto const angularState = angularProfile.Calculate(t, angularStart, angularGoal);
129
130 // x is m_state * cos(heading), y is m_state * sin(heading)
131 Pose2d pose{
132 initialPose.X() + linearState.position * heading.Cos(),
133 initialPose.Y() + linearState.position * heading.Sin(),
134 {angularState.position}
135 };
136 ChassisSpeeds speeds{
137 linearState.velocity * heading.Cos(),
138 linearState.velocity * heading.Sin(),
139 angularState.velocity
140 };
141 return {std::move(pose), std::move(speeds)};
142 }
143
144public:
145 /**
146 * \brief Constructs a linear path.
147 *
148 * \param linear The constraints on the profile linear motion
149 * \param angular The constraints on the profile angular motion
150 */
151 constexpr LinearPath(
152 frc::TrapezoidProfile<units::meters>::Constraints linear,
153 frc::TrapezoidProfile<units::radians>::Constraints angular
154 ) :
155 linearProfile{std::move(linear)},
156 angularProfile{std::move(angular)}
157 {}
158
159 /**
160 * \brief Calculates the pose and speeds of the path at a time t where
161 * the current state is at t = 0.
162 *
163 * \param t How long to advance from the current state to the desired state
164 * \param current The current state
165 * \param goal The desired pose when the path is complete
166 * \returns The pose and speeds of the profile at time t
167 */
168 constexpr State Calculate(units::second_t t, State const &current, Pose2d const &goal)
169 {
170 SetState(current, goal);
171 return Calculate(t);
172 }
173
174 /**
175 * \brief Returns the total time the profile takes to reach the goal.
176 *
177 * \returns The total time the profile takes to reach the goal
178 */
179 constexpr units::second_t TotalTime() const
180 {
181 return units::math::max(
182 linearProfile.TotalTime(),
183 angularProfile.TotalTime()
184 );
185 }
186
187 /**
188 * \brief Returns true if the profile has reached the goal.
189 *
190 * The profile has reached the goal if the time since the profile
191 * started has exceeded the profile's total time.
192 *
193 * \param t The time since the beginning of the profile
194 * \returns true if the profile has reached the goal
195 */
196 constexpr bool IsFinished(units::second_t t) const
197 {
198 return t >= TotalTime();
199 }
200};
201
202}
203}
204}
A linear path for a holonomic drivetrain (i.e.
Definition LinearPath.hpp:35
constexpr LinearPath(frc::TrapezoidProfile< units::meters >::Constraints linear, frc::TrapezoidProfile< units::radians >::Constraints angular)
Constructs a linear path.
Definition LinearPath.hpp:151
constexpr units::second_t TotalTime() const
Returns the total time the profile takes to reach the goal.
Definition LinearPath.hpp:179
constexpr State Calculate(units::second_t t, State const &current, Pose2d const &goal)
Calculates the pose and speeds of the path at a time t where the current state is at t = 0.
Definition LinearPath.hpp:168
constexpr bool IsFinished(units::second_t t) const
Returns true if the profile has reached the goal.
Definition LinearPath.hpp:196
Definition motor_constants.h:14
Path state.
Definition LinearPath.hpp:38
constexpr bool operator==(State const &) const =default
ChassisSpeeds speeds
The field-centric speeds at this state.
Definition LinearPath.hpp:42
Pose2d pose
The pose at this state.
Definition LinearPath.hpp:40