CTRE Phoenix 6 C++ 26.70.0-alpha-2
Loading...
Searching...
No Matches
SwerveDrivetrainImpl.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
13
14#include <atomic>
15#include <span>
16#include <thread>
17
18namespace ctre {
19namespace phoenix6 {
20namespace swerve {
21namespace impl {
22
23/**
24 * \brief Swerve Drive class utilizing CTR Electronics Phoenix 6 API.
25 *
26 * This class handles the kinematics and odometry (but not configuration)
27 * of a swerve drive utilizing CTR Electronics devices. Users should
28 * create a high-level SwerveDrivetrain instead of using this directly.
29 */
31public:
32 /** \brief Performs swerve module updates in a separate thread to minimize latency. */
35
36 protected:
37 static constexpr int START_THREAD_PRIORITY = 1; // Testing shows 1 (minimum realtime) is sufficient for tighter
38 // odometry loops. If the odometry period is far away from the
39 // desired frequency, increasing this may help.
40
42
43 std::thread _thread;
44 std::mutex _threadMtx;
45 std::atomic<bool> _isRunning = false;
46
49
50 wpi::units::second_t _averageLoopTime{};
51 std::atomic<int32_t> _successfulDaqs{};
52 std::atomic<int32_t> _failedDaqs{};
53
56
57 public:
60 {
61 Stop();
62 }
63
64 /**
65 * \brief Starts the odometry thread.
66 */
67 void Start()
68 {
69 std::lock_guard<std::mutex> lock{_threadMtx};
70 if (!_thread.joinable()) {
71 _isRunning.store(true, std::memory_order_relaxed);
72 _thread = std::thread{[this] { Run(); }};
73 }
74 }
75
76 /**
77 * \brief Stops the odometry thread.
78 */
79 void Stop()
80 {
81 std::lock_guard<std::mutex> lock{_threadMtx};
82 if (_thread.joinable()) {
83 _isRunning.store(false, std::memory_order_relaxed);
84 _thread.join();
85 }
86 }
87
88 /**
89 * \brief Check if the odometry is currently valid.
90 *
91 * \returns True if odometry is valid
92 */
93 bool IsOdometryValid() const
94 {
95 return _successfulDaqs.load(std::memory_order_relaxed) > 2;
96 }
97
98 /**
99 * \brief Sets the odometry thread priority to a real time priority under the specified priority level
100 *
101 * \param priority Priority level to set the odometry thread to.
102 * This is a value between 0 and 99, with 99 indicating higher priority and 0 indicating lower priority.
103 */
104 void SetThreadPriority(int priority)
105 {
106 _threadPriorityToSet.store(priority, std::memory_order_relaxed);
107 }
108
109 protected:
110 void Run();
111 };
112
113 /**
114 * \brief Plain-Old-Data class holding the state of the swerve drivetrain.
115 * This encapsulates most data that is relevant for telemetry or
116 * decision-making from the Swerve Drive.
117 */
119 /** \brief The current pose of the robot */
120 Pose2d Pose;
121 /** \brief The current robot-centric velocity */
122 ChassisVelocities Velocity;
123 /** \brief The current module positions */
124 std::vector<SwerveModulePosition> ModulePositions;
125 /** \brief The current module velocities */
126 std::vector<SwerveModuleVelocity> ModuleVelocities;
127 /** \brief The target module velocities */
128 std::vector<SwerveModuleVelocity> ModuleTargets;
129 /** \brief The raw heading of the robot, unaffected by vision updates and odometry resets */
130 Rotation2d RawHeading;
131 /** \brief The timestamp of the state capture, in the timebase of utils#GetCurrentTime() */
132 wpi::units::second_t Timestamp;
133 /** \brief The measured odometry update period */
134 wpi::units::second_t OdometryPeriod;
135 /** \brief Number of successful data acquisitions */
137 /** \brief Number of failed data acquisitions */
138 int32_t FailedDaqs;
139 };
140
141 /**
142 * \brief Contains everything the control requests need to calculate the module state.
143 */
145 /** \brief The kinematics object used for control */
147 /** \brief The locations of the swerve modules */
148 Translation2d const *moduleLocations;
149 /** \brief The max speed of the robot at 12 V output */
150 wpi::units::meters_per_second_t kMaxSpeed;
151
152 /** \brief The forward direction from the operator perspective */
154 /** \brief The current robot-centric chassis velocity */
155 ChassisVelocities currentChassisVelocity;
156 /** \brief The current pose of the robot */
158 /** \brief The timestamp of the current control apply, in the timebase of utils#GetCurrentTime() */
159 wpi::units::second_t timestamp;
160 /** \brief The update period of control apply */
161 wpi::units::second_t updatePeriod;
162 };
163
164 using SwerveRequestFunc = std::function<ctre::phoenix::StatusCode(ControlParameters const &, std::span<std::unique_ptr<SwerveModuleImpl> const>)>;
165
166private:
167 friend class OdometryThread;
168
169 CANBus _canbus;
170
174
175 std::vector<std::unique_ptr<SwerveModuleImpl>> _modules;
176
177 std::vector<Translation2d> _moduleLocations;
178 std::vector<SwerveModulePosition> _modulePositions;
179 std::vector<SwerveModuleVelocity> _moduleVelocities;
180
181 SwerveDriveKinematics _kinematics;
182 SwerveDrivePoseEstimator _odometry;
183
184 Rotation2d _operatorForwardDirection{};
185
186 SwerveRequestFunc _requestToApply = [](auto&, auto) { return ctre::phoenix::StatusCode::OK; };
187 ControlParameters _requestParameters{};
188
189 mutable std::recursive_mutex _stateLock;
190 SwerveDriveState _cachedState{};
191 std::function<void(SwerveDriveState const &)> _telemetryFunction{};
192
193 bool kIsOnCANFD;
194 wpi::units::hertz_t _updateFrequency;
195
196 std::unique_ptr<OdometryThread> _odometryThread;
197
198public:
199 /**
200 * \brief Constructs a CTRE SwerveDrivetrainImpl using the specified constants.
201 *
202 * This constructs the underlying hardware devices, which can be accessed through
203 * getters in the classes.
204 *
205 * \param drivetrainConstants Drivetrain-wide constants for the swerve drive
206 * \param modules Constants for each specific module
207 */
208 template <
209 std::derived_from<configs::ParentConfiguration> DriveMotorConfigsT,
210 std::derived_from<configs::ParentConfiguration> SteerMotorConfigsT,
211 std::derived_from<configs::ParentConfiguration> EncoderConfigsT
212 >
214 SwerveDrivetrainConstants const &drivetrainConstants,
216 ) :
217 SwerveDrivetrainImpl{drivetrainConstants, 0_Hz, modules}
218 {}
219
220 /**
221 * \brief Constructs a CTRE SwerveDrivetrainImpl using the specified constants.
222 *
223 * This constructs the underlying hardware devices, which can be accessed through
224 * getters in the classes.
225 *
226 * \param drivetrainConstants Drivetrain-wide constants for the swerve drive
227 * \param odometryUpdateFrequency The frequency to run the odometry loop. If
228 * unspecified or set to 0 Hz, this is 250 Hz on
229 * CAN FD, and 100 Hz on CAN 2.0.
230 * \param modules Constants for each specific module
231 */
232 template <
233 std::derived_from<configs::ParentConfiguration> DriveMotorConfigsT,
234 std::derived_from<configs::ParentConfiguration> SteerMotorConfigsT,
235 std::derived_from<configs::ParentConfiguration> EncoderConfigsT
236 >
238 SwerveDrivetrainConstants const &drivetrainConstants,
239 wpi::units::hertz_t odometryUpdateFrequency,
241 ) :
242 SwerveDrivetrainImpl{drivetrainConstants, odometryUpdateFrequency, std::array{0.1, 0.1, 0.1}, std::array{0.9, 0.9, 0.9}, modules}
243 {}
244
245 /**
246 * \brief Constructs a CTRE SwerveDrivetrainImpl using the specified constants.
247 *
248 * This constructs the underlying hardware devices, which can be accessed through
249 * getters in the classes.
250 *
251 * \param drivetrainConstants Drivetrain-wide constants for the swerve drive
252 * \param odometryUpdateFrequency The frequency to run the odometry loop. If
253 * unspecified or set to 0 Hz, this is 250 Hz on
254 * CAN FD, and 100 Hz on CAN 2.0.
255 * \param odometryStandardDeviation The standard deviation for odometry calculation
256 * in the form [x, y, theta]ᵀ, with units in meters
257 * and radians
258 * \param visionStandardDeviation The standard deviation for vision calculation
259 * in the form [x, y, theta]ᵀ, with units in meters
260 * and radians
261 * \param modules Constants for each specific module
262 */
263 template <
264 std::derived_from<configs::ParentConfiguration> DriveMotorConfigsT,
265 std::derived_from<configs::ParentConfiguration> SteerMotorConfigsT,
266 std::derived_from<configs::ParentConfiguration> EncoderConfigsT
267 >
269 SwerveDrivetrainConstants const &drivetrainConstants,
270 wpi::units::hertz_t odometryUpdateFrequency,
271 std::array<double, 3> const &odometryStandardDeviation,
272 std::array<double, 3> const &visionStandardDeviation,
274 );
275
276 /**
277 * \brief Gets whether the drivetrain is on a CAN FD bus.
278 *
279 * \returns true if on CAN FD
280 */
281 bool IsOnCANFD() const { return kIsOnCANFD; }
282
283 /**
284 * \brief Gets the target odometry update frequency.
285 *
286 * \returns Target odometry update frequency
287 */
288 wpi::units::hertz_t GetOdometryFrequency() const { return _updateFrequency; }
289
290 /**
291 * \brief Gets a reference to the odometry thread.
292 *
293 * \returns Odometry thread
294 */
295 OdometryThread &GetOdometryThread() { return *_odometryThread; }
296
297 /**
298 * \brief Check if the odometry is currently valid.
299 *
300 * \returns True if odometry is valid
301 */
302 bool IsOdometryValid() const
303 {
304 return _odometryThread->IsOdometryValid();
305 }
306
307 /**
308 * \brief Gets a reference to the kinematics used for the drivetrain.
309 *
310 * \returns Swerve kinematics
311 */
312 SwerveDriveKinematics const &GetKinematics() const { return _kinematics; }
313
314 /**
315 * \brief Applies the specified control function to this swerve drivetrain.
316 *
317 * \param request Request function to apply
318 */
320 {
321 std::lock_guard<std::recursive_mutex> lock{_stateLock};
322 if (request) {
323 _requestToApply = std::move(request);
324 } else {
325 _requestToApply = [](auto&, auto) { return ctre::phoenix::StatusCode::OK; };
326 }
327 }
328
329 /**
330 * \brief Immediately runs the provided temporary control function.
331 *
332 * This is used to accelerate non-native swerve requests and
333 * can only be called from the odometry thread. Otherwise,
334 * SetControl should be used instead.
335 *
336 * \param request Request function to invoke
337 */
339 {
340 std::lock_guard<std::recursive_mutex> lock{_stateLock};
341 return request(_requestParameters, _modules);
342 }
343
344 /**
345 * \brief Gets the current state of the swerve drivetrain.
346 * This includes information such as the pose estimate,
347 * module states, and chassis velocity.
348 *
349 * \returns Current state of the drivetrain
350 */
352 {
353 std::lock_guard<std::recursive_mutex> lock{_stateLock};
354 return _cachedState;
355 }
356
357 /**
358 * \brief Register the specified lambda to be executed whenever the SwerveDriveState
359 * is updated in the odometry thread.
360 *
361 * It is imperative that this function is cheap, as it will be executed synchronously
362 * with the odometry call; if this takes a long time, it may negatively impact the
363 * odometry of this stack.
364 *
365 * This can also be used for logging data if the function performs logging instead of telemetry.
366 * Additionally, the SwerveDriveState object can be cloned and stored for later processing.
367 *
368 * \param telemetryFunction Function to call for telemetry or logging
369 */
370 void RegisterTelemetry(std::function<void(SwerveDriveState const &)> telemetryFunction)
371 {
372 std::lock_guard<std::recursive_mutex> lock{_stateLock};
373 _telemetryFunction = std::move(telemetryFunction);
374 }
375
376 /**
377 * \brief Configures the neutral mode to use for all modules' drive motors.
378 *
379 * \param neutralMode The drive motor neutral mode
380 * \param timeoutSeconds Maximum amount of time to wait when performing each configuration
381 * \returns Status code of the first failed config call, or OK if all succeeded
382 */
383 ctre::phoenix::StatusCode ConfigNeutralMode(signals::NeutralModeValue neutralMode, wpi::units::second_t timeoutSeconds = 0.100_s)
384 {
386 for (auto &module : _modules) {
387 auto status = module->ConfigNeutralMode(neutralMode, timeoutSeconds);
388 if (retval.IsOK()) {
389 retval = status;
390 }
391 }
392 return retval;
393 }
394
395 /**
396 * \brief Zeroes this swerve drive's odometry entirely. To quickly reset
397 * the pose of the robot, use #ResetPose instead.
398 *
399 * This will zero the entire odometry, placing the robot at (0 m, 0 m, 0 rad).
400 *
401 * This will wait up to 0.100 seconds (100ms) for each drive motor.
402 */
404 {
405 std::lock_guard<std::recursive_mutex> lock{_stateLock};
406
407 for (size_t i = 0; i < _modules.size(); ++i) {
408 _modules[i]->ResetPosition();
409 }
410 _odometryThread->_allSignals.WaitForAll(2.0 / _updateFrequency);
411
412 for (size_t i = 0; i < _modules.size(); ++i) {
413 _modulePositions[i] = _modules[i]->GetPosition(false);
414 _cachedState.ModulePositions[i] = _modulePositions[i];
415 }
416 _odometry.ResetPosition({_pigeonYaw.GetValue()}, _modulePositions, Pose2d{});
417 /* We need to update our cached pose immediately to prevent race conditions */
418 _cachedState.Pose = _odometry.GetEstimatedPosition();
419 }
420
421 /**
422 * \brief Resets the rotation of the robot pose to the given value
423 * from the requests#ForwardPerspectiveValue#OperatorPerspective
424 * perspective. This makes the current orientation of the robot minus
425 * `rotation` the X forward for field-centric maneuvers.
426 *
427 * This is equivalent to calling ResetRotation with `rotation +
428 * GetOperatorForwardDirection()`.
429 *
430 * \param rotation Rotation to make the current rotation
431 */
432 void SeedFieldCentric(Rotation2d const &rotation = Rotation2d{})
433 {
434 ResetRotation(rotation + _operatorForwardDirection);
435 }
436
437 /**
438 * \brief Resets the pose of the robot. The pose should be from the
439 * requests#ForwardPerspectiveValue#BlueAlliance perspective.
440 *
441 * \param pose Pose to make the current pose
442 */
443 void ResetPose(Pose2d const &pose)
444 {
445 std::lock_guard<std::recursive_mutex> lock{_stateLock};
446
447 _odometry.ResetPose(pose);
448 /* We need to update our cached pose immediately to prevent race conditions */
449 _cachedState.Pose = _odometry.GetEstimatedPosition();
450 }
451
452 /**
453 * \brief Resets the translation of the robot pose without affecting rotation.
454 * The translation should be from the requests#ForwardPerspectiveValue#BlueAlliance
455 * perspective.
456 *
457 * \param translation Translation to make the current translation
458 */
459 void ResetTranslation(Translation2d const &translation)
460 {
461 std::lock_guard<std::recursive_mutex> lock{_stateLock};
462
463 _odometry.ResetTranslation(translation);
464 /* We need to update our cached pose immediately to prevent race conditions */
465 _cachedState.Pose = _odometry.GetEstimatedPosition();
466 }
467
468 /**
469 * \brief Resets the rotation of the robot pose without affecting translation.
470 * The rotation should be from the requests#ForwardPerspectiveValue#BlueAlliance
471 * perspective.
472 *
473 * \param rotation Rotation to make the current rotation
474 */
475 void ResetRotation(Rotation2d const &rotation)
476 {
477 std::lock_guard<std::recursive_mutex> lock{_stateLock};
478
479 _odometry.ResetRotation(rotation);
480 /* We need to update our cached pose immediately to prevent race conditions */
481 _cachedState.Pose = _odometry.GetEstimatedPosition();
482 }
483
484 /**
485 * \brief Takes the requests#ForwardPerspectiveValue#BlueAlliance perpective
486 * direction and treats it as the forward direction for
487 * requests#ForwardPerspectiveValue#OperatorPerspective.
488 * This corresponds to the direction the operator is facing, not the robot.
489 *
490 * - If the operator is in the Blue Alliance Station, this should be 0 degrees.
491 *
492 * - If the operator is in the Red Alliance Station, this should be 180 degrees.
493 *
494 * This does not change the robot pose, which is in the
495 * requests#ForwardPerspectiveValue#BlueAlliance perspective.
496 * As a result, the robot pose may need to be reset using ResetPose.
497 *
498 * \param fieldDirection Heading indicating which direction is forward from
499 * the requests#ForwardPerspectiveValue#BlueAlliance perspective
500 */
501 void SetOperatorForwardDirection(Rotation2d const &fieldDirection)
502 {
503 std::lock_guard<std::recursive_mutex> lock{_stateLock};
504 _operatorForwardDirection = fieldDirection;
505 }
506
507 /**
508 * \brief Returns the requests#ForwardPerspectiveValue#BlueAlliance perpective
509 * direction that is treated as the forward direction for
510 * requests#ForwardPerspectiveValue#OperatorPerspective.
511 *
512 * If the operator is in the Blue Alliance Station, this should be 0 degrees.
513 * If the operator is in the Red Alliance Station, this should be 180 degrees.
514 *
515 * \returns Heading indicating which direction is forward from
516 * the requests#ForwardPerspectiveValue#BlueAlliance perspective
517 */
519 {
520 std::lock_guard<std::recursive_mutex> lock{_stateLock};
521 return _operatorForwardDirection;
522 }
523
524 /**
525 * \brief Adds a vision measurement to the Kalman Filter. This will correct the
526 * odometry pose estimate while still accounting for measurement noise.
527 *
528 * This method can be called as infrequently as you want, as long as you are
529 * calling impl#SwerveDrivePoseEstimator#Update every loop.
530 *
531 * To promote stability of the pose estimate and make it robust to bad vision
532 * data, we recommend only adding vision measurements that are already within
533 * one meter or so of the current pose estimate.
534 *
535 * \param visionRobotPose The pose of the robot as measured by the
536 * vision camera.
537 * \param timestamp The timestamp of the vision measurement in
538 * seconds. Note that if you don't use your
539 * own time source by calling
540 * impl#SwerveDrivePoseEstimator#UpdateWithTime,
541 * then you must use a timestamp with an epoch
542 * since system startup (i.e., the epoch of this
543 * timestamp is the same epoch as utils#GetCurrentTime).
544 * This means that you should use utils#GetCurrentTime
545 * as your time source in this case.
546 */
547 void AddVisionMeasurement(Pose2d visionRobotPose, wpi::units::second_t timestamp)
548 {
549 std::lock_guard<std::recursive_mutex> lock{_stateLock};
550 _odometry.AddVisionMeasurement(visionRobotPose, timestamp);
551 }
552
553 /**
554 * \brief Adds a vision measurement to the Kalman Filter. This will correct the
555 * odometry pose estimate while still accounting for measurement noise.
556 *
557 * This method can be called as infrequently as you want, as long as you are
558 * calling impl#SwerveDrivePoseEstimator#Update every loop.
559 *
560 * To promote stability of the pose estimate and make it robust to bad vision
561 * data, we recommend only adding vision measurements that are already within
562 * one meter or so of the current pose estimate.
563 *
564 * Note that the vision measurement standard deviations passed into this method
565 * will continue to apply to future measurements until a subsequent call to
566 * #SetVisionMeasurementStdDevs or this method.
567 *
568 * \param visionRobotPose The pose of the robot as measured by the
569 * vision camera.
570 * \param timestamp The timestamp of the vision measurement in
571 * seconds. Note that if you don't use your
572 * own time source by calling
573 * impl#SwerveDrivePoseEstimator#UpdateWithTime,
574 * then you must use a timestamp with an epoch
575 * since system startup (i.e., the epoch of this
576 * timestamp is the same epoch as utils#GetCurrentTime).
577 * This means that you should use utils#GetCurrentTime
578 * as your time source in this case.
579 * \param visionMeasurementStdDevs Standard deviations of the vision pose
580 * measurement (x position in meters, y position
581 * in meters, and heading in radians). Increase
582 * these numbers to trust the vision pose
583 * measurement less.
584 */
586 Pose2d visionRobotPose,
587 wpi::units::second_t timestamp,
588 std::array<double, 3> const &visionMeasurementStdDevs)
589 {
590 std::lock_guard<std::recursive_mutex> lock{_stateLock};
591 _odometry.AddVisionMeasurement(visionRobotPose, timestamp, visionMeasurementStdDevs);
592 }
593
594 /**
595 * \brief Sets the pose estimator's trust of global measurements. This might be used to
596 * change trust in vision measurements after the autonomous period, or to change
597 * trust as distance to a vision target increases.
598 *
599 * \param visionMeasurementStdDevs Standard deviations of the vision
600 * measurements. Increase these
601 * numbers to trust global measurements from
602 * vision less. This matrix is in the form [x,
603 * y, theta]ᵀ, with units in meters and radians.
604 */
605 void SetVisionMeasurementStdDevs(std::array<double, 3> const &visionMeasurementStdDevs)
606 {
607 std::lock_guard<std::recursive_mutex> lock{_stateLock};
608 _odometry.SetVisionMeasurementStdDevs(visionMeasurementStdDevs);
609 }
610
611 /**
612 * \brief Sets the pose estimator's trust in robot odometry. This might be used
613 * to change trust in odometry after an impact with the wall or traversing a bump.
614 *
615 * \param stateStdDevs Standard deviations of the pose estimate. Increase these
616 * numbers to trust your state estimate less. This matrix is
617 * in the form [x, y, theta]ᵀ, with units in meters and radians.
618 */
619 void SetStateStdDevs(std::array<double, 3> const &stateStdDevs)
620 {
621 std::lock_guard<std::recursive_mutex> lock{_stateLock};
622 _odometry.SetStateStdDevs(stateStdDevs);
623 }
624
625 /**
626 * \brief Return the pose at a given timestamp, if the buffer is not empty.
627 *
628 * \param timestamp The pose's timestamp. Note that if you don't use your
629 * own time source by calling
630 * impl#SwerveDrivePoseEstimator#UpdateWithTime,
631 * then you must use a timestamp with an epoch
632 * since system startup (i.e., the epoch of this
633 * timestamp is the same epoch as utils#GetCurrentTime).
634 * This means that you should use utils#GetCurrentTime
635 * as your time source in this case.
636 * \returns The pose at the given timestamp (or std::nullopt if the buffer is
637 * empty).
638 */
639 std::optional<Pose2d> SamplePoseAt(wpi::units::second_t timestamp) const
640 {
641 std::lock_guard<std::recursive_mutex> lock{_stateLock};
642 return _odometry.SampleAt(timestamp);
643 }
644
645 /**
646 * \brief Get a reference to the module at the specified index.
647 * The index corresponds to the module described in the constructor.
648 *
649 * \param index Which module to get
650 * \returns Reference to SwerveModuleImpl
651 */
652 SwerveModuleImpl &GetModule(size_t index) { return *_modules[index]; }
653 /**
654 * \brief Get a reference to the module at the specified index.
655 * The index corresponds to the module described in the constructor.
656 *
657 * \param index Which module to get
658 * \returns Reference to SwerveModuleImpl
659 */
660 SwerveModuleImpl const &GetModule(size_t index) const { return *_modules[index]; }
661 /**
662 * \brief Get a reference to the full array of modules.
663 * The indexes correspond to the module described in the constructor.
664 *
665 * \returns Reference to the SwerveModuleImpl array
666 */
667 std::span<std::unique_ptr<SwerveModuleImpl> const> GetModules() const { return _modules; }
668
669 /**
670 * \brief Gets the locations of the swerve modules.
671 *
672 * \returns Reference to the array of swerve module locations
673 */
674 std::vector<Translation2d> const &GetModuleLocations() const { return _moduleLocations; }
675
676 /**
677 * \brief Gets this drivetrain's Pigeon 2 reference.
678 *
679 * This should be used only to access signals and change configurations that the
680 * swerve drivetrain does not configure itself.
681 *
682 * \returns This drivetrain's Pigeon 2 reference
683 */
685 /**
686 * \brief Gets this drivetrain's Pigeon 2 reference.
687 *
688 * This should be used only to access signals and change configurations that the
689 * swerve drivetrain does not configure itself.
690 *
691 * \returns This drivetrain's Pigeon 2 reference
692 */
693 hardware::core::CorePigeon2 const &GetPigeon2() const { return _pigeon2; }
694};
695
696}
697}
698}
699}
Class for getting information about an available CAN bus.
Definition CANBus.hpp:142
Class to manage bulk refreshing device status signals.
Definition StatusSignalCollection.hpp:21
Represents a status signal with data of type T, and operations available to retrieve information abou...
Definition StatusSignal.hpp:523
Class for the Pigeon 2 IMU sensor that measures orientation.
Definition CorePigeon2.hpp:1058
Class that converts a chassis velocity (dx, dy, and dtheta components) into individual module states ...
Definition SwerveDriveKinematics.hpp:41
This class wraps Swerve Drive Odometry to fuse latency-compensated vision measurements with swerve dr...
Definition SwerveDrivePoseEstimator.hpp:143
Performs swerve module updates in a separate thread to minimize latency.
Definition SwerveDrivetrainImpl.hpp:33
std::thread _thread
Definition SwerveDrivetrainImpl.hpp:43
std::atomic< bool > _isRunning
Definition SwerveDrivetrainImpl.hpp:45
StatusSignalCollection _encSignals
Definition SwerveDrivetrainImpl.hpp:48
bool IsOdometryValid() const
Check if the odometry is currently valid.
Definition SwerveDrivetrainImpl.hpp:93
void Stop()
Stops the odometry thread.
Definition SwerveDrivetrainImpl.hpp:79
StatusSignalCollection _allSignals
Definition SwerveDrivetrainImpl.hpp:47
std::atomic< int > _threadPriorityToSet
Definition SwerveDrivetrainImpl.hpp:54
friend class SwerveDrivetrainImpl
Definition SwerveDrivetrainImpl.hpp:34
static constexpr int START_THREAD_PRIORITY
Definition SwerveDrivetrainImpl.hpp:37
std::atomic< int32_t > _failedDaqs
Definition SwerveDrivetrainImpl.hpp:52
void Start()
Starts the odometry thread.
Definition SwerveDrivetrainImpl.hpp:67
wpi::units::second_t _averageLoopTime
Definition SwerveDrivetrainImpl.hpp:50
SwerveDrivetrainImpl * _drivetrain
Definition SwerveDrivetrainImpl.hpp:41
void SetThreadPriority(int priority)
Sets the odometry thread priority to a real time priority under the specified priority level.
Definition SwerveDrivetrainImpl.hpp:104
std::atomic< int32_t > _successfulDaqs
Definition SwerveDrivetrainImpl.hpp:51
std::mutex _threadMtx
Definition SwerveDrivetrainImpl.hpp:44
int _lastThreadPriority
Definition SwerveDrivetrainImpl.hpp:55
void SetOperatorForwardDirection(Rotation2d const &fieldDirection)
Takes the requests::ForwardPerspectiveValue::BlueAlliance perpective direction and treats it as the f...
Definition SwerveDrivetrainImpl.hpp:501
void TareEverything()
Zeroes this swerve drive's odometry entirely.
Definition SwerveDrivetrainImpl.hpp:403
void SetControl(SwerveRequestFunc &&request)
Applies the specified control function to this swerve drivetrain.
Definition SwerveDrivetrainImpl.hpp:319
std::vector< Translation2d > const & GetModuleLocations() const
Gets the locations of the swerve modules.
Definition SwerveDrivetrainImpl.hpp:674
ctre::phoenix::StatusCode ConfigNeutralMode(signals::NeutralModeValue neutralMode, wpi::units::second_t timeoutSeconds=0.100_s)
Configures the neutral mode to use for all modules' drive motors.
Definition SwerveDrivetrainImpl.hpp:383
SwerveDriveState GetState() const
Gets the current state of the swerve drivetrain.
Definition SwerveDrivetrainImpl.hpp:351
SwerveDrivetrainImpl(SwerveDrivetrainConstants const &drivetrainConstants, wpi::units::hertz_t odometryUpdateFrequency, std::span< SwerveModuleConstants< DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT > const > modules)
Constructs a CTRE SwerveDrivetrainImpl using the specified constants.
Definition SwerveDrivetrainImpl.hpp:237
SwerveModuleImpl const & GetModule(size_t index) const
Get a reference to the module at the specified index.
Definition SwerveDrivetrainImpl.hpp:660
bool IsOdometryValid() const
Check if the odometry is currently valid.
Definition SwerveDrivetrainImpl.hpp:302
void ResetRotation(Rotation2d const &rotation)
Resets the rotation of the robot pose without affecting translation.
Definition SwerveDrivetrainImpl.hpp:475
hardware::core::CorePigeon2 & GetPigeon2()
Gets this drivetrain's Pigeon 2 reference.
Definition SwerveDrivetrainImpl.hpp:684
void RegisterTelemetry(std::function< void(SwerveDriveState const &)> telemetryFunction)
Register the specified lambda to be executed whenever the SwerveDriveState is updated in the odometry...
Definition SwerveDrivetrainImpl.hpp:370
void SetVisionMeasurementStdDevs(std::array< double, 3 > const &visionMeasurementStdDevs)
Sets the pose estimator's trust of global measurements.
Definition SwerveDrivetrainImpl.hpp:605
void SetStateStdDevs(std::array< double, 3 > const &stateStdDevs)
Sets the pose estimator's trust in robot odometry.
Definition SwerveDrivetrainImpl.hpp:619
std::span< std::unique_ptr< SwerveModuleImpl > const > GetModules() const
Get a reference to the full array of modules.
Definition SwerveDrivetrainImpl.hpp:667
SwerveDriveKinematics const & GetKinematics() const
Gets a reference to the kinematics used for the drivetrain.
Definition SwerveDrivetrainImpl.hpp:312
wpi::units::hertz_t GetOdometryFrequency() const
Gets the target odometry update frequency.
Definition SwerveDrivetrainImpl.hpp:288
SwerveModuleImpl & GetModule(size_t index)
Get a reference to the module at the specified index.
Definition SwerveDrivetrainImpl.hpp:652
std::function< ctre::phoenix::StatusCode(ControlParameters const &, std::span< std::unique_ptr< SwerveModuleImpl > const >)> SwerveRequestFunc
Definition SwerveDrivetrainImpl.hpp:164
Rotation2d GetOperatorForwardDirection() const
Returns the requests::ForwardPerspectiveValue::BlueAlliance perpective direction that is treated as t...
Definition SwerveDrivetrainImpl.hpp:518
OdometryThread & GetOdometryThread()
Gets a reference to the odometry thread.
Definition SwerveDrivetrainImpl.hpp:295
hardware::core::CorePigeon2 const & GetPigeon2() const
Gets this drivetrain's Pigeon 2 reference.
Definition SwerveDrivetrainImpl.hpp:693
bool IsOnCANFD() const
Gets whether the drivetrain is on a CAN FD bus.
Definition SwerveDrivetrainImpl.hpp:281
std::optional< Pose2d > SamplePoseAt(wpi::units::second_t timestamp) const
Return the pose at a given timestamp, if the buffer is not empty.
Definition SwerveDrivetrainImpl.hpp:639
void SeedFieldCentric(Rotation2d const &rotation=Rotation2d{})
Resets the rotation of the robot pose to the given value from the requests::ForwardPerspectiveValue::...
Definition SwerveDrivetrainImpl.hpp:432
ctre::phoenix::StatusCode RunTempRequest(SwerveRequestFunc &&request) const
Immediately runs the provided temporary control function.
Definition SwerveDrivetrainImpl.hpp:338
void AddVisionMeasurement(Pose2d visionRobotPose, wpi::units::second_t timestamp, std::array< double, 3 > const &visionMeasurementStdDevs)
Adds a vision measurement to the Kalman Filter.
Definition SwerveDrivetrainImpl.hpp:585
SwerveDrivetrainImpl(SwerveDrivetrainConstants const &drivetrainConstants, wpi::units::hertz_t odometryUpdateFrequency, std::array< double, 3 > const &odometryStandardDeviation, std::array< double, 3 > const &visionStandardDeviation, std::span< SwerveModuleConstants< DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT > const > modules)
Constructs a CTRE SwerveDrivetrainImpl using the specified constants.
void ResetPose(Pose2d const &pose)
Resets the pose of the robot.
Definition SwerveDrivetrainImpl.hpp:443
void AddVisionMeasurement(Pose2d visionRobotPose, wpi::units::second_t timestamp)
Adds a vision measurement to the Kalman Filter.
Definition SwerveDrivetrainImpl.hpp:547
void ResetTranslation(Translation2d const &translation)
Resets the translation of the robot pose without affecting rotation.
Definition SwerveDrivetrainImpl.hpp:459
SwerveDrivetrainImpl(SwerveDrivetrainConstants const &drivetrainConstants, std::span< SwerveModuleConstants< DriveMotorConfigsT, SteerMotorConfigsT, EncoderConfigsT > const > modules)
Constructs a CTRE SwerveDrivetrainImpl using the specified constants.
Definition SwerveDrivetrainImpl.hpp:213
Swerve Module class that encapsulates a swerve module powered by CTR Electronics devices.
Definition SwerveModuleImpl.hpp:61
Status codes reported by APIs, including OK, warnings, and errors.
Definition StatusCodes.h:28
static constexpr int OK
No Error.
Definition StatusCodes.h:35
constexpr bool IsOK() const
Definition StatusCodes.h:860
Definition SwerveDrivetrainImpl.hpp:21
Definition SwerveModule.hpp:28
Definition ExternalFeedbackConfigs.hpp:16
Definition motor_constants.h:14
The state of the motor controller bridge when output is neutral or disabled.
Definition SpnEnums.hpp:1499
Common constants for a swerve drivetrain.
Definition SwerveDrivetrainConstants.hpp:19
All constants for a swerve module.
Definition SwerveModuleConstants.hpp:152
Contains everything the control requests need to calculate the module state.
Definition SwerveDrivetrainImpl.hpp:144
wpi::units::second_t updatePeriod
The update period of control apply.
Definition SwerveDrivetrainImpl.hpp:161
ChassisVelocities currentChassisVelocity
The current robot-centric chassis velocity.
Definition SwerveDrivetrainImpl.hpp:155
wpi::units::meters_per_second_t kMaxSpeed
The max speed of the robot at 12 V output.
Definition SwerveDrivetrainImpl.hpp:150
impl::SwerveDriveKinematics * kinematics
The kinematics object used for control.
Definition SwerveDrivetrainImpl.hpp:146
Pose2d currentPose
The current pose of the robot.
Definition SwerveDrivetrainImpl.hpp:157
Rotation2d operatorForwardDirection
The forward direction from the operator perspective.
Definition SwerveDrivetrainImpl.hpp:153
Translation2d const * moduleLocations
The locations of the swerve modules.
Definition SwerveDrivetrainImpl.hpp:148
wpi::units::second_t timestamp
The timestamp of the current control apply, in the timebase of utils::GetCurrentTime().
Definition SwerveDrivetrainImpl.hpp:159
Plain-Old-Data class holding the state of the swerve drivetrain.
Definition SwerveDrivetrainImpl.hpp:118
wpi::units::second_t OdometryPeriod
The measured odometry update period.
Definition SwerveDrivetrainImpl.hpp:134
ChassisVelocities Velocity
The current robot-centric velocity.
Definition SwerveDrivetrainImpl.hpp:122
std::vector< SwerveModuleVelocity > ModuleVelocities
The current module velocities.
Definition SwerveDrivetrainImpl.hpp:126
int32_t SuccessfulDaqs
Number of successful data acquisitions.
Definition SwerveDrivetrainImpl.hpp:136
std::vector< SwerveModulePosition > ModulePositions
The current module positions.
Definition SwerveDrivetrainImpl.hpp:124
Pose2d Pose
The current pose of the robot.
Definition SwerveDrivetrainImpl.hpp:120
std::vector< SwerveModuleVelocity > ModuleTargets
The target module velocities.
Definition SwerveDrivetrainImpl.hpp:128
wpi::units::second_t Timestamp
The timestamp of the state capture, in the timebase of utils::GetCurrentTime().
Definition SwerveDrivetrainImpl.hpp:132
int32_t FailedDaqs
Number of failed data acquisitions.
Definition SwerveDrivetrainImpl.hpp:138
Rotation2d RawHeading
The raw heading of the robot, unaffected by vision updates and odometry resets.
Definition SwerveDrivetrainImpl.hpp:130