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