librmb 1.0
Rambunction 4330 Utility Library
Loading...
Searching...
No Matches
SwerveDrive.inl
1#pragma once
2
3#include "frc/geometry/Pose2d.h"
4#include "pathplanner/lib/path/PathConstraints.h"
5#include "pathplanner/lib/path/PathPlannerPath.h"
6#include "pathplanner/lib/util/HolonomicPathFollowerConfig.h"
7#include "pathplanner/lib/util/PIDConstants.h"
8#include "pathplanner/lib/util/ReplanningConfig.h"
9#include "rmb/drive/BaseDrive.h"
10#include "units/acceleration.h"
11#include "units/angle.h"
12#include "units/angular_velocity.h"
13#include "units/base.h"
14#include "units/length.h"
15#include "units/math.h"
16#include "units/time.h"
17#include "units/velocity.h"
18
19#include "frc/controller/HolonomicDriveController.h"
20#include "frc/estimator/SwerveDrivePoseEstimator.h"
21#include "frc/geometry/Rotation2d.h"
22#include "frc/interfaces/Gyro.h"
23#include "frc/kinematics/ChassisSpeeds.h"
24#include "frc/kinematics/SwerveDriveKinematics.h"
25#include "frc/kinematics/SwerveModulePosition.h"
26#include "frc/kinematics/SwerveModuleState.h"
27
28#include "frc/geometry/Translation2d.h"
29
30#include "frc2/command//SwerveControllerCommand.h"
31#include "frc2/command/CommandPtr.h"
32#include "frc2/command/Commands.h"
33#include "frc2/command/Subsystem.h"
34#include "networktables/NetworkTable.h"
35#include "networktables/NetworkTableInstance.h"
36#include "rmb/drive/SwerveDrive.h"
37#include "rmb/drive/SwerveModule.h"
38#include "rmb/motorcontrol/feedforward/Feedforward.h"
39#include "units/angle.h"
40#include "units/angular_velocity.h"
41#include "units/length.h"
42#include "units/math.h"
43#include "units/velocity.h"
44#include "wpi/array.h"
45#include "wpi/sendable/SendableRegistry.h"
46
47#include <array>
48#include <cstddef>
49#include <functional>
50#include <initializer_list>
51#include <iostream>
52
53#include <Eigen/Core>
54#include <memory>
55
56#include "pathplanner/lib/commands/FollowPathHolonomic.h"
57#include "pathplanner/lib/commands/PathfindHolonomic.h"
58#include "pathplanner/lib/path/PathConstraints.h"
59#include "pathplanner/lib/util/HolonomicPathFollowerConfig.h"
60#include "pathplanner/lib/util/ReplanningConfig.h"
61#include <mutex>
62
63namespace rmb {
64
65template <size_t NumModules>
67 std::array<SwerveModule, NumModules> modules,
68 std::shared_ptr<const rmb::Gyro> gyro,
69 frc::HolonomicDriveController holonomicController, std::string visionTable,
70 units::meters_per_second_t maxModuleSpeed, const frc::Pose2d &initialPose)
71 : modules(std::move(modules)), gyro(gyro),
72 kinematics(std::array<frc::Translation2d, NumModules>{}),
73 holonomicController(holonomicController),
74 poseEstimator(frc::SwerveDrivePoseEstimator<NumModules>(
75 kinematics, gyro->getRotation(), getModulePositions(), initialPose)),
76 maxModuleSpeed(maxModuleSpeed) {
77 std::array<frc::Translation2d, NumModules> translations;
78 for (size_t i = 0; i < NumModules; i++) {
79 translations[i] = modules[i].getModuleTranslation();
80 }
81 nt::NetworkTableInstance ntInstance = nt::NetworkTableInstance::GetDefault();
82 std::shared_ptr<nt::NetworkTable> table = ntInstance.GetTable("swervedrive");
83
84 ntPositionTopics = table->GetDoubleArrayTopic("mod_positions").Publish();
85 ntVelocityTopics = table->GetDoubleArrayTopic("mod_velocities").Publish();
86
87 ntPositionErrorTopics =
88 table->GetDoubleArrayTopic("mod_position_errors").Publish();
89 ntVelocityErrorTopics =
90 table->GetDoubleArrayTopic("mod_velocity_errors").Publish();
91
92 ntTargetPositionTopics =
93 table->GetDoubleArrayTopic("mod_position_targets").Publish();
94 ntTargetVelocityTopics =
95 table->GetDoubleArrayTopic("mod_velocity_targets").Publish();
96
97 units::meter_t maxDistance = 0.0_m;
98 for (SwerveModule &module : this->modules) {
99 auto &translation = module.getModuleTranslation();
100 units::meter_t distance =
101 translation.Distance(frc::Translation2d(0.0_m, 0.0_m));
102
103 maxDistance = units::math::max(distance, maxDistance);
104 }
105
106 largestModuleDistance = maxDistance;
107}
108
109template <size_t NumModules>
111 std::array<SwerveModule, NumModules> modules,
112 std::shared_ptr<const rmb::Gyro> gyro,
113 frc::HolonomicDriveController holonomicController,
114 units::meters_per_second_t maxModuleSpeed, const frc::Pose2d &initialPose)
115 : SwerveDrive(std::move(modules), gyro, holonomicController, "",
116 maxModuleSpeed, initialPose) {}
117
118template <size_t NumModules>
119std::array<frc::SwerveModulePosition, NumModules>
121 std::array<frc::SwerveModulePosition, NumModules> states;
122 for (size_t i = 0; i < NumModules; i++) {
123 states[i] = modules[i].getPosition();
124 }
125
126 return states;
127}
128
129template <size_t NumModules>
130std::array<frc::SwerveModuleState, NumModules>
131SwerveDrive<NumModules>::getModuleStates() const {
132 std::array<frc::SwerveModuleState, NumModules> states;
133 for (size_t i = 0; i < NumModules; i++) {
134 states[i] = modules[i].getState();
135 }
136
137 return states;
138}
139
140template <size_t NumModules>
141void SwerveDrive<NumModules>::driveCartesian(double xSpeed, double ySpeed,
142 double zRotation,
143 bool fieldOriented) {
144
145 Eigen::Vector2d robotRelativeVXY = Eigen::Vector2d(xSpeed, ySpeed);
146
147 if (fieldOriented) {
148 units::radian_t vXYRotationAngle = -gyro->getRotation().Radians();
149
150 Eigen::Matrix2d vXYRotation{
151 {std::cos(vXYRotationAngle()), -std::sin(vXYRotationAngle())},
152 {std::sin(vXYRotationAngle()), std::cos(vXYRotationAngle())}};
153
154 robotRelativeVXY = vXYRotation * robotRelativeVXY;
155 }
156
172 std::array<SwerveModulePower, NumModules> powers;
173 double largestPower = 1.0;
174
175 for (size_t i = 0; i < modules.size(); i++) {
176 SwerveModule &module = modules[i];
177
178 double output_x =
179 robotRelativeVXY.x() +
180 zRotation * module.getModuleTranslation().Y() / largestModuleDistance;
181
182 double output_y =
183 robotRelativeVXY.y() +
184 zRotation * -module.getModuleTranslation().X() / largestModuleDistance;
185
186 frc::Rotation2d moduleRotation{output_x, output_y};
187 double modulePower = std::sqrt(output_x * output_x + output_y * output_y);
188
189 powers[i] = SwerveModulePower{modulePower, moduleRotation};
190
191 if (modulePower > largestPower) {
192 largestPower = modulePower;
193 }
194 }
195
196 // Normalize
197 for (SwerveModulePower &power : powers) {
198 power.power /= largestPower;
199 }
200
201 // Optimize
202 for (size_t i = 0; i < modules.size(); i++) {
203 powers[i] =
204 SwerveModulePower::Optimize(powers[i], modules[i].getState().angle);
205 }
206
207 driveModulePowers(powers);
208}
209
210template <size_t NumModules>
212 std::array<frc::SwerveModuleState, NumModules> states) {
213 for (size_t i = 0; i < NumModules; i++) {
214 modules[i].setState(states[i]);
215 }
216}
217
218template <size_t NumModules>
219void SwerveDrive<NumModules>::drivePolar(double speed,
220 const frc::Rotation2d &angle,
221 double zRotation, bool fieldOriented) {
222 double vx = speed * angle.Cos();
223 double vy = speed * angle.Sin();
224
225 driveCartesian(vx, vy, zRotation, fieldOriented);
226}
227
228template <size_t NumModules>
229void SwerveDrive<NumModules>::driveModulePowers(
230 std::array<SwerveModulePower, NumModules> powers) {
231 // std::cout << "powers: ";
232 for (size_t i = 0; i < NumModules; i++) {
233 modules[i].setPower(powers[i]);
234 }
235}
236
237template <size_t NumModules>
239 frc::ChassisSpeeds chassisSpeeds) {
240 auto states = kinematics.ToSwerveModuleStates(chassisSpeeds);
241 kinematics.DesaturateWheelSpeeds(&states, maxModuleSpeed);
242 driveModuleStates(states);
243}
244
245template <size_t NumModules>
247 return kinematics.ToChassisSpeeds(
248 wpi::array<frc::SwerveModuleState, NumModules>(getModuleStates()));
249}
250
251template <size_t NumModules>
253 std::lock_guard<std::mutex> lock(visionThreadMutex);
254 return poseEstimator.GetEstimatedPosition();
255}
256
257template <size_t NumModules> frc::Pose2d SwerveDrive<NumModules>::updatePose() {
258 std::lock_guard<std::mutex> lock(visionThreadMutex);
259 return poseEstimator.Update(
260 frc::Rotation2d((units::radian_t)gyro->getZRotation()),
261 getModulePositions());
262}
263
264template <size_t NumModules>
265void SwerveDrive<NumModules>::updateNTDebugInfo(bool openLoopVelocity) {
266 std::array<double, NumModules> velocityErrors;
267 for (size_t i = 0; i < NumModules; i++) {
268 units::meters_per_second_t error = 0.0_mps;
269 if (!openLoopVelocity) {
270 error = modules[i].getTargetState().speed - modules[i].getState().speed;
271 } else {
272
273 velocityErrors[i] = error();
274 }
275 ntVelocityErrorTopics.Set(velocityErrors);
276
277 std::array<double, NumModules> positionErrors;
278 for (size_t i = 0; i < NumModules; i++) {
279 units::turn_t error = modules[i].getTargetRotation().Degrees() -
280 modules[i].getState().angle.Degrees();
281
282 positionErrors[i] = error();
283 }
284 ntPositionErrorTopics.Set(positionErrors);
285
286 std::array<double, NumModules> velocityTargets;
287 for (size_t i = 0; i < NumModules; i++) {
288 double target = 0.0;
289
290 if (!openLoopVelocity) {
291 target = modules[i].getTargetVelocity()();
292 } else {
293 target = modules[i].getPower().power;
294 }
295
296 velocityTargets[i] = target;
297 }
298 ntTargetVelocityTopics.Set(velocityTargets);
299
300 std::array<double, NumModules> positionTargets;
301 for (size_t i = 0; i < NumModules; i++) {
302 units::degree_t target = modules[i].getTargetRotation().Degrees();
303
304 positionTargets[i] = target();
305 }
306 ntTargetPositionTopics.Set(positionTargets);
307
308 std::array<double, NumModules> positions;
309 for (size_t i = 0; i < NumModules; i++) {
310 units::turn_t position = modules[i].getState().angle.Degrees();
311
312 positions[i] = position();
313 }
314 ntPositionTopics.Set(positions);
315
316 std::array<double, NumModules> velocities;
317 for (size_t i = 0; i < NumModules; i++) {
318 units::meters_per_second_t velocity = modules[i].getState().speed;
319
320 velocities[i] = velocity();
321 }
322 ntVelocityTopics.Set(velocities);
323 }
324}
325
326template <size_t NumModules>
327std::array<frc::SwerveModuleState, NumModules>
328SwerveDrive<NumModules>::getTargetModuleStates() const {
329 std::array<frc::SwerveModuleState, NumModules> targetStates;
330 for (size_t i = 0; i < NumModules; i++) {
331 targetStates[i] = modules[i].getTargetState();
332 }
333
334 return targetStates;
335}
336
337template <size_t NumModules>
338void SwerveDrive<NumModules>::resetPose(const frc::Pose2d &pose) {
339 std::lock_guard<std::mutex> lock(visionThreadMutex);
340 poseEstimator.ResetPosition(gyro->getRotation(), getModulePositions(), pose);
341}
342
343template <size_t NumModules>
345 const frc::Pose2d &poseEstimate, units::second_t time) {
346 std::lock_guard<std::mutex> lock(visionThreadMutex);
347 poseEstimator.AddVisionMeasurement(poseEstimate, time);
348}
349
350template <size_t NumModules>
352 wpi::array<double, 3> standardDevs) {
353 std::lock_guard<std::mutex> lock(visionThreadMutex);
354 poseEstimator.SetVisionMeasurementStdDevs(standardDevs);
355}
356
357template <size_t NumModules>
359 frc::Trajectory trajectory,
360 std::initializer_list<frc2::Subsystem *> driveRequirements) {
361
362 return frc2::SwerveControllerCommand<NumModules>(
363 trajectory, [this]() { return getPose(); }, kinematics,
364 holonomicController,
365 [this](std::array<frc::SwerveModuleState, NumModules> states) {
366 driveModuleStates(states);
367 },
368 driveRequirements)
369 .ToPtr();
370}
371
372template <size_t NumModules>
374 std::shared_ptr<pathplanner::PathPlannerPath> path,
375 std::initializer_list<frc2::Subsystem *> driveRequirements) {
376
377 pathplanner::ReplanningConfig replanningConfig;
378 units::second_t period;
379 pathplanner::HolonomicPathFollowerConfig holonomicPathFollowerConfig(
380 maxModuleSpeed, largestModuleDistance, replanningConfig, period);
381
382 return pathplanner::FollowPathHolonomic(
383 path, [this]() { return getPose(); },
384 [this]() { return getChassisSpeeds(); },
385 [this](frc::ChassisSpeeds chassisSpeeds) {
386 driveChassisSpeeds(chassisSpeeds);
387 },
388 holonomicPathFollowerConfig, []() { return true; },
389 driveRequirements)
390 .ToPtr();
391}
392
393template <size_t NumModules>
395 frc::Pose2d targetPose, pathplanner::PathConstraints contraints,
396 std::initializer_list<frc2::Subsystem *> driveRequirements) {
397
398 pathplanner::ReplanningConfig replanningConfig;
399 units::second_t period;
400 pathplanner::HolonomicPathFollowerConfig holonomicPathFollowerConfig(
401 maxModuleSpeed, largestModuleDistance, replanningConfig, period);
402 units::meter_t rotationDelayDistance = 0_m;
403
404 return pathplanner::PathfindHolonomic(
405 targetPose, contraints, [this]() { return getPose(); },
406 [this]() { return getChassisSpeeds(); },
407 [this](frc::ChassisSpeeds chassisSpeeds) {
408 driveChassisSpeeds(chassisSpeeds);
409 },
410 holonomicPathFollowerConfig, driveRequirements,
411 rotationDelayDistance)
412 .ToPtr();
413}
414
415template <size_t NumModules> void SwerveDrive<NumModules>::stop() {
416 for (auto &module : modules) {
417 module.stop();
418 }
419}
420
421} // namespace rmb
Definition SwerveDrive.h:54
void driveCartesian(double xSpeed, double ySpeed, double zRotation, bool fieldOriented)
Definition SwerveDrive.inl:141
void driveChassisSpeeds(frc::ChassisSpeeds chassisSpeeds) override
Definition SwerveDrive.inl:238
frc::Pose2d updatePose() override
Definition SwerveDrive.inl:257
frc::Pose2d getPose() const override
Definition SwerveDrive.inl:252
frc2::CommandPtr followPPPath(std::shared_ptr< pathplanner::PathPlannerPath > path, std::initializer_list< frc2::Subsystem * > driveRequirements) override
Definition SwerveDrive.inl:373
void resetPose(const frc::Pose2d &pose=frc::Pose2d()) override
Definition SwerveDrive.inl:338
void setVisionSTDevs(wpi::array< double, 3 > standardDevs) override
Definition SwerveDrive.inl:351
void addVisionMeasurments(const frc::Pose2d &poseEstimate, units::second_t time) override
Definition SwerveDrive.inl:344
frc2::CommandPtr followWPILibTrajectory(frc::Trajectory trajectory, std::initializer_list< frc2::Subsystem * > driveRequirements) override
Definition SwerveDrive.inl:358
frc::ChassisSpeeds getChassisSpeeds() const override
Definition SwerveDrive.inl:246
Definition SwerveModule.h:52
the master namespace of librmb
Definition LogitechGamepad.h:9
Definition SwerveModule.h:30
static SwerveModulePower Optimize(const SwerveModulePower &desiredPower, const frc::Rotation2d &currentAngle)