CTRE Phoenix 6 C++ 26.70.0-alpha-2
Loading...
Searching...
No Matches
StatusSignal.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#include <array>
15#include <functional>
16#include <map>
17#include <ostream>
18#include <span>
19#include <sstream>
20#include <string>
21#include <wpi/units/frequency.hpp>
22#include <wpi/units/math.hpp>
23#include <wpi/units/time.hpp>
24
25namespace ctre {
26namespace phoenix6 {
27
28 namespace hardware {
29 class ParentDevice;
30 }
31
32 template <typename T>
33 class StatusSignal;
34
35 /**
36 * \brief Class that provides operations to
37 * retrieve information about a status signal.
38 */
40 private:
41 hardware::DeviceIdentifier deviceIdentifier;
42 uint16_t spn;
43 std::string name;
44 std::function<void()> _checkFirmVersFunction;
45
46 std::map<uint16_t, std::string> _unitStrings{};
47 uint16_t _unitsKey;
48
49 wpi::units::second_t _lastTimestamp{0_s};
50
51 double baseValue = 0;
52 std::string units;
54 AllTimestamps timestamps{};
55
56 protected:
58 hardware::DeviceIdentifier deviceIdentifier,
59 uint16_t spn,
60 std::string signalName,
61 std::function<void()> checkFirmVersFunction,
62 std::function<std::map<uint16_t, std::string>()> const &unitsGenerator = {}
63 ) :
64 deviceIdentifier{std::move(deviceIdentifier)},
65 spn{spn},
66 name{std::move(signalName)},
67 _checkFirmVersFunction{std::move(checkFirmVersFunction)},
68 _unitsKey{spn},
69 units{Status_GetUnits(spn)}
70 {
71 if (unitsGenerator) {
72 _unitStrings = unitsGenerator();
73 for (auto &unitString : _unitStrings) {
74 unitString.second = Status_GetUnits(unitString.first);
75 }
76 }
77 }
78
79 /* Constructor for an invalid BaseStatusSignal */
81 BaseStatusSignal{{}, 0, "Invalid", [] {}}
82 {
83 this->error = error;
84 }
85
86 static std::string Status_GetUnits(uint32_t signal);
87
88 ctre::phoenix::StatusCode Status_Get(bool bWaitForUpdate, double timeoutSeconds);
90 std::span<BaseStatusSignal* const> signals,
91 double timeoutSeconds);
92
93 ctre::phoenix::StatusCode Status_SetUpdateFrequency(double frequencyHz, double timeoutSeconds) const;
96 std::span<BaseStatusSignal* const> signals,
97 double frequencyHz,
98 double timeoutSeconds);
99
101 char const *location,
102 wpi::units::second_t timeoutSeconds,
103 bool reportError,
104 std::span<BaseStatusSignal* const> signals);
105
106 void RefreshValue(bool waitForUpdate, wpi::units::second_t timeout, bool reportError);
107 void UpdateUnits(uint16_t unitsKey);
108
109 public:
110 virtual ~BaseStatusSignal() = 0; // Declare virtual destructor to make this class abstract
111
112 /**
113 * \brief Gets the name of this signal.
114 *
115 * \returns Name of this signal
116 */
117 std::string const &GetName() const { return name; }
118 /**
119 * \brief Gets the value of this signal as a double.
120 *
121 * \return Value of this signal as a double instead of the generic type
122 */
123 double GetValueAsDouble() const { return baseValue; }
124 /**
125 * \brief Gets the units for this signal.
126 *
127 * \returns String representation of units for this signal
128 */
129 std::string const &GetUnits() const { return units; }
130 /**
131 * \brief Gets the timestamps of this signals.
132 *
133 * \returns All timestamps for this signal
134 */
135 AllTimestamps const &GetAllTimestamps() const { return timestamps; }
136 /**
137 * \brief Gets the most accurate timestamp available for this signal.
138 *
139 * \details The timestamp sources from most to least accurate are:
140 *
141 * - Timestamp#TimestampSource#Device
142 * - Timestamp#TimestampSource#CANivore
143 * - Timestamp#TimestampSource#System
144 *
145 * Note that some of these sources may not be available.
146 *
147 * \returns The most accurate timestamp available for this signal
148 */
149 Timestamp const &GetTimestamp() const { return timestamps.GetBestTimestamp(); }
150 /**
151 * \brief Gets the status code of the last time this signal was refreshed.
152 *
153 * \returns Status code of the last time this signal was refreshed
154 */
155 ctre::phoenix::StatusCode GetStatus() const { return error; }
156
157 /**
158 * \brief Checks whether the signal has been updated since the last check.
159 *
160 * Note that the signal must be refreshed before calling this routine.
161 *
162 * \returns true if the signal has updated since the previous call of this routine
163 */
165 {
166 bool retval = false;
167 /* did we receive an update */
168 auto const &timestamp = GetAllTimestamps().GetSystemTimestamp();
169 if (timestamp.IsValid()) {
170 /* if the update timestamp is new, then a new frame was sent */
171 if (_lastTimestamp != timestamp.GetTime()) {
172 _lastTimestamp = timestamp.GetTime();
173 retval = true;
174 }
175 }
176 return retval;
177 }
178
179 /**
180 * \brief Sets the rate at which the device will publish this signal.
181 *
182 * A frequency of 0 Hz will turn off the signal. Otherwise, the minimum supported signal
183 * frequency is 4 Hz, and the maximum is 1000 Hz. Additionally, some update frequencies are
184 * not supported and will be promoted up to the next highest supported frequency.
185 *
186 * If other StatusSignals in the same status frame have been set to an update frequency,
187 * the fastest requested update frequency will be applied to the frame.
188 *
189 * \param frequencyHz Rate to publish the signal in Hz.
190 * \param timeoutSeconds Maximum amount of time to wait when performing the action
191 * \returns Status code of setting the update frequency
192 */
193 ctre::phoenix::StatusCode SetUpdateFrequency(wpi::units::hertz_t frequencyHz, wpi::units::second_t timeoutSeconds = 100_ms)
194 {
195 return Status_SetUpdateFrequency(frequencyHz.value(), timeoutSeconds.value());
196 }
197
198 /**
199 * \brief Gets the rate at which the device will publish this signal.
200 *
201 * This is typically the last value passed into #SetUpdateFrequency. The returned value
202 * may be higher if another StatusSignal in the same status frame has been set to a higher
203 * update frequency.
204 *
205 * \returns Applied update frequency of the signal in Hz
206 */
207 wpi::units::hertz_t GetAppliedUpdateFrequency() const
208 {
209 return wpi::units::hertz_t{Status_GetAppliedUpdateFrequency()};
210 }
211
212 /**
213 * \brief Performs latency compensation on signal using the signalSlope and signal's latency to determine
214 * the magnitude of compensation. The caller must refresh these StatusSignals beforehand;
215 * this function only does the math required for latency compensation.
216 *
217 * \details Example usage:
218 * \code
219 * wpi::units::turn_t compensatedTurns = BaseStatusSignal::GetLatencyCompensatedValue(fx.GetPosition(), fx.GetVelocity());
220 * \endcode
221 *
222 * \tparam U Underlying type of signal
223 * \tparam U_PER_SEC Underlying type of signalSlope, which must be the time derivative of U
224 * \param signal Signal to be latency compensated. Caller must make sure this signal is up to date
225 * either by calling \c Refresh() or \c WaitForUpdate().
226 * \param signalSlope Derivative of signal that informs compensation magnitude. Caller must make sure this
227 * signal is up to date either by calling \c Refresh() or \c WaitForUpdate().
228 * \param maxLatencySeconds The maximum amount of latency to compensate for in seconds. A negative or zero
229 * value disables the max latency cap. This is used to cap the contribution of
230 * latency compensation for stale signals, such as after the device has been
231 * disconnected from the CAN bus.
232 * \returns Latency compensated value from the signal StatusSignal.
233 */
234 template <typename U, typename U_PER_SEC>
235 requires wpi::units::traits::is_unit_t_v<U> && wpi::units::traits::is_unit_t_v<U_PER_SEC> &&
236 wpi::units::traits::is_convertible_unit_v<
237 typename wpi::units::traits::unit_t_traits<U>::unit_type,
238 wpi::units::compound_unit<typename wpi::units::traits::unit_t_traits<U_PER_SEC>::unit_type, wpi::units::seconds>
239 >
240 static U GetLatencyCompensatedValue(StatusSignal<U> const &signal, StatusSignal<U_PER_SEC> const &signalSlope, wpi::units::second_t maxLatencySeconds = 0.300_s)
241 {
242 wpi::units::second_t latency = signal.GetTimestamp().GetLatency();
243 if (maxLatencySeconds > 0_s && latency > maxLatencySeconds) {
244 latency = maxLatencySeconds;
245 }
246 return signal.GetValue() + (signalSlope.GetValue() * latency);
247 }
248
249 /**
250 * \brief Waits for new data on all provided signals up to timeout.
251 * This API is typically used with CANivore Bus signals as they will be synced using the
252 * CANivore Timesync feature and arrive simultaneously. Signals on a non-CANivore bus cannot
253 * be synced and may require a significantly longer blocking call to receive all signals.
254 *
255 * Note that CANivore Timesync requires Phoenix Pro.
256 *
257 * This can also be used with a timeout of zero to refresh many signals at once, which
258 * is faster than calling Refresh() on every signal. This is equivalent to calling #RefreshAll.
259 *
260 * If a signal arrives multiple times while waiting, such as when *not* using CANivore
261 * Timesync, the newest signal data is fetched. Additionally, if this function times out,
262 * the newest signal data is fetched for all signals (when possible). We recommend checking
263 * the individual status codes using GetStatus() when this happens.
264 *
265 * \param timeoutSeconds Maximum time to wait for all the signals to arrive.
266 * Pass zero to refresh all signals without blocking.
267 * \param signals Signals to wait on, passed as a comma-separated list of signal references.
268 * \return InvalidNetwork if any signal is on a CAN bus that does not support WaitForAll,
269 * RxTimeout if it took longer than timeoutSeconds to receive all the signals,
270 * An OK status code means that all signals arrived within timeoutSeconds and they are all OK.
271 *
272 * Any other value represents the StatusCode of the first failed signal.
273 * Call GetStatus() on each signal to determine which ones failed.
274 */
275 template <std::derived_from<BaseStatusSignal>... Signals>
276 static ctre::phoenix::StatusCode WaitForAll(wpi::units::second_t timeoutSeconds, Signals &... signals)
277 {
278 return WaitForAll(timeoutSeconds, true, signals...);
279 }
280 /**
281 * \brief Waits for new data on all provided signals up to timeout.
282 * This API is typically used with CANivore Bus signals as they will be synced using the
283 * CANivore Timesync feature and arrive simultaneously. Signals on a non-CANivore bus cannot
284 * be synced and may require a significantly longer blocking call to receive all signals.
285 *
286 * Note that CANivore Timesync requires Phoenix Pro.
287 *
288 * This can also be used with a timeout of zero to refresh many signals at once, which
289 * is faster than calling Refresh() on every signal. This is equivalent to calling #RefreshAll.
290 *
291 * If a signal arrives multiple times while waiting, such as when *not* using CANivore
292 * Timesync, the newest signal data is fetched. Additionally, if this function times out,
293 * the newest signal data is fetched for all signals (when possible). We recommend checking
294 * the individual status codes using GetStatus() when this happens.
295 *
296 * \param timeoutSeconds Maximum time to wait for all the signals to arrive.
297 * Pass zero to refresh all signals without blocking.
298 * \param signals Signals to wait on, passed as a span of signal pointers.
299 * \return InvalidNetwork if any signal is on a CAN bus that does not support WaitForAll,
300 * RxTimeout if it took longer than timeoutSeconds to receive all the signals,
301 * An OK status code means that all signals arrived within timeoutSeconds and they are all OK.
302 *
303 * Any other value represents the StatusCode of the first failed signal.
304 * Call GetStatus() on each signal to determine which ones failed.
305 */
306 static ctre::phoenix::StatusCode WaitForAll(wpi::units::second_t timeoutSeconds, std::span<BaseStatusSignal* const> signals)
307 {
308 return WaitForAll(timeoutSeconds, true, signals);
309 }
310
311 /**
312 * \brief Waits for new data on all provided signals up to timeout.
313 * This API is typically used with CANivore Bus signals as they will be synced using the
314 * CANivore Timesync feature and arrive simultaneously. Signals on a roboRIO bus cannot
315 * be synced and may require a significantly longer blocking call to receive all signals.
316 *
317 * Note that CANivore Timesync requires Phoenix Pro.
318 *
319 * This can also be used with a timeout of zero to refresh many signals at once, which
320 * is faster than calling Refresh() on every signal. This is equivalent to calling #RefreshAll.
321 *
322 * If a signal arrives multiple times while waiting, such as when *not* using CANivore
323 * Timesync, the newest signal data is fetched. Additionally, if this function times out,
324 * the newest signal data is fetched for all signals (when possible). We recommend checking
325 * the individual status codes using GetStatus() when this happens.
326 *
327 * \param timeoutSeconds Maximum time to wait for all the signals to arrive.
328 * Pass zero to refresh all signals without blocking.
329 * \param reportError Whether to report any errors to the Driver Station/stderr, defaults to true
330 * \param signals Signals to wait on, passed as a comma-separated list of signal references.
331 * \return InvalidNetwork if any signal is on a CAN bus that does not support WaitForAll,
332 * RxTimeout if it took longer than timeoutSeconds to receive all the signals,
333 * An OK status code means that all signals arrived within timeoutSeconds and they are all OK.
334 *
335 * Any other value represents the StatusCode of the first failed signal.
336 * Call GetStatus() on each signal to determine which ones failed.
337 */
338 template <std::derived_from<BaseStatusSignal>... Signals>
339 static ctre::phoenix::StatusCode WaitForAll(wpi::units::second_t timeoutSeconds, bool reportError, Signals &... signals)
340 {
341 return WaitForAll(
342 timeoutSeconds,
343 reportError,
344 std::array<BaseStatusSignal *, sizeof...(Signals)>{(&signals)...}
345 );
346 }
347 /**
348 * \brief Waits for new data on all provided signals up to timeout.
349 * This API is typically used with CANivore Bus signals as they will be synced using the
350 * CANivore Timesync feature and arrive simultaneously. Signals on a roboRIO bus cannot
351 * be synced and may require a significantly longer blocking call to receive all signals.
352 *
353 * Note that CANivore Timesync requires Phoenix Pro.
354 *
355 * This can also be used with a timeout of zero to refresh many signals at once, which
356 * is faster than calling Refresh() on every signal. This is equivalent to calling #RefreshAll.
357 *
358 * If a signal arrives multiple times while waiting, such as when *not* using CANivore
359 * Timesync, the newest signal data is fetched. Additionally, if this function times out,
360 * the newest signal data is fetched for all signals (when possible). We recommend checking
361 * the individual status codes using GetStatus() when this happens.
362 *
363 * \param timeoutSeconds Maximum time to wait for all the signals to arrive.
364 * Pass zero to refresh all signals without blocking.
365 * \param reportError Whether to report any errors to the Driver Station/stderr, defaults to true
366 * \param signals Signals to wait on, passed as a span of signal pointers.
367 * \return InvalidNetwork if any signal is on a CAN bus that does not support WaitForAll,
368 * RxTimeout if it took longer than timeoutSeconds to receive all the signals,
369 * An OK status code means that all signals arrived within timeoutSeconds and they are all OK.
370 *
371 * Any other value represents the StatusCode of the first failed signal.
372 * Call GetStatus() on each signal to determine which ones failed.
373 */
374 static ctre::phoenix::StatusCode WaitForAll(wpi::units::second_t timeoutSeconds, bool reportError, std::span<BaseStatusSignal* const> signals)
375 {
376 static constexpr char kLocation[] = "ctre::phoenix6::BaseStatusSignal::WaitForAll";
377 return WaitForAllImpl(kLocation, timeoutSeconds, reportError, signals);
378 }
379
380 /**
381 * \brief Performs a non-blocking refresh on all provided signals.
382 *
383 * This provides a performance improvement over separately calling Refresh() on each signal.
384 *
385 * \param signals Signals to refresh, passed as a comma-separated list of signal references.
386 * \return An OK status code means that all signals are OK.
387 * Any other value represents the StatusCode of the first failed signal.
388 * Call GetStatus() on each signal to determine which ones failed.
389 */
390 template <std::derived_from<BaseStatusSignal>... Signals>
392 {
393 return RefreshAll(true, signals...);
394 }
395 /**
396 * \brief Performs a non-blocking refresh on all provided signals.
397 *
398 * This provides a performance improvement over separately calling Refresh() on each signal.
399 *
400 * \param signals Signals to refresh, passed as a span of signal pointers.
401 * \return An OK status code means that all signals are OK.
402 * Any other value represents the StatusCode of the first failed signal.
403 * Call GetStatus() on each signal to determine which ones failed.
404 */
405 static ctre::phoenix::StatusCode RefreshAll(std::span<BaseStatusSignal* const> signals)
406 {
407 return RefreshAll(true, signals);
408 }
409
410 /**
411 * \brief Performs a non-blocking refresh on all provided signals.
412 *
413 * This provides a performance improvement over separately calling Refresh() on each signal.
414 *
415 * \param reportError Whether to report any errors to the Driver Station/stderr, defaults to true
416 * \param signals Signals to refresh, passed as a comma-separated list of signal references.
417 * \return An OK status code means that all signals are OK.
418 * Any other value represents the StatusCode of the first failed signal.
419 * Call GetStatus() on each signal to determine which ones failed.
420 */
421 template <std::derived_from<BaseStatusSignal>... Signals>
422 static ctre::phoenix::StatusCode RefreshAll(bool reportError, Signals &... signals)
423 {
424 return RefreshAll(reportError, std::array<BaseStatusSignal *, sizeof...(Signals)>{(&signals)...});
425 }
426 /**
427 * \brief Performs a non-blocking refresh on all provided signals.
428 *
429 * This provides a performance improvement over separately calling Refresh() on each signal.
430 *
431 * \param reportError Whether to report any errors to the Driver Station/stderr, defaults to true
432 * \param signals Signals to refresh, passed as a span of signal pointers.
433 * \return An OK status code means that all signals are OK.
434 * Any other value represents the StatusCode of the first failed signal.
435 * Call GetStatus() on each signal to determine which ones failed.
436 */
437 static ctre::phoenix::StatusCode RefreshAll(bool reportError, std::span<BaseStatusSignal* const> signals)
438 {
439 static constexpr char kLocation[] = "ctre::phoenix6::BaseStatusSignal::RefreshAll";
440 return WaitForAllImpl(kLocation, 0_s, reportError, signals);
441 }
442
443 /**
444 * \brief Checks if all signals have an OK error code.
445 *
446 * \param signals Signals to check error code of, passed as a comma-separated list of signal references.
447 * \returns True if all signals are OK, false otherwise
448 */
449 template <std::derived_from<BaseStatusSignal>... Signals>
450 static bool IsAllGood(Signals const &... signals)
451 {
452 return IsAllGood(std::array<BaseStatusSignal const *, sizeof...(Signals)>{(&signals)...});
453 }
454 /**
455 * \brief Checks if all signals have an OK error code.
456 *
457 * \param signals Signals to check error code of, passed as a span of signal pointers.
458 * \returns True if all signals are OK, false otherwise
459 */
460 static bool IsAllGood(std::span<BaseStatusSignal const *const> signals)
461 {
462 for (auto signal : signals) {
463 if (!signal->GetStatus().IsOK()) {
464 return false;
465 }
466 }
467 return true;
468 }
469
470 /**
471 * \brief Sets the update frequency of all specified status signals to the provided common frequency.
472 *
473 * A frequency of 0 Hz will turn off the signal. Otherwise, the minimum supported signal frequency
474 * is 4 Hz, and the maximum is 1000 Hz. Additionally, some update frequencies are not supported and
475 * will be promoted up to the next highest supported frequency.
476 *
477 * If other StatusSignals in the same status frame have been set to an update frequency,
478 * the fastest requested update frequency will be applied to the frame.
479 *
480 * This will wait up to 0.100 seconds (100ms) for each signal.
481 *
482 * \param frequencyHz Rate to publish the signal in Hz.
483 * \param signals Signals to apply the update frequency to, passed as a comma-separated list of signal references.
484 * \returns Status code of the first failed update frequency set call, or OK if all succeeded
485 */
486 template <std::derived_from<BaseStatusSignal>... Signals>
487 static ctre::phoenix::StatusCode SetUpdateFrequencyForAll(wpi::units::hertz_t frequencyHz, Signals &... signals)
488 {
489 return SetUpdateFrequencyForAll(frequencyHz, std::array<BaseStatusSignal *, sizeof...(Signals)>{(&signals)...});
490 }
491 /**
492 * \brief Sets the update frequency of all specified status signals to the provided common frequency.
493 *
494 * A frequency of 0 Hz will turn off the signal. Otherwise, the minimum supported signal frequency
495 * is 4 Hz, and the maximum is 1000 Hz. Additionally, some update frequencies are not supported and
496 * will be promoted up to the next highest supported frequency.
497 *
498 * If other StatusSignals in the same status frame have been set to an update frequency,
499 * the fastest requested update frequency will be applied to the frame.
500 *
501 * This will wait up to 0.100 seconds (100ms) for each signal.
502 *
503 * \param frequencyHz Rate to publish the signal in Hz.
504 * \param signals Signals to apply the update frequency to, passed as a span of signal pointers.
505 * \returns Status code of the first failed update frequency set call, or OK if all succeeded
506 */
507 static ctre::phoenix::StatusCode SetUpdateFrequencyForAll(wpi::units::hertz_t frequencyHz, std::span<BaseStatusSignal* const> signals)
508 {
509 return Status_SetUpdateFrequencyForAll(signals, frequencyHz.value(), 0.100);
510 }
511
512 void RegisterAlerts(AlertableCollection &collection) override;
513 };
514
515 /**
516 * \brief Represents a status signal with data of type T,
517 * and operations available to retrieve information about
518 * the signal.
519 *
520 * \tparam T Type of the signal
521 */
522 template <typename T>
523 class StatusSignal : public BaseStatusSignal {
525
526 StatusSignal(
527 hardware::DeviceIdentifier deviceIdentifier,
528 uint16_t spn,
529 std::string signalName,
530 std::function<void()> checkFirmVersFunction,
531 std::function<std::map<uint16_t, std::string>()> const &unitsGenerator = {}
532 ) :
534 std::move(deviceIdentifier),
535 spn, std::move(signalName),
536 std::move(checkFirmVersFunction),
537 unitsGenerator
538 }
539 {}
540
541 /* Constructor for an invalid StatusSignal */
542 StatusSignal(ctre::phoenix::StatusCode error) :
543 BaseStatusSignal{error}
544 {}
545
546 public:
547 /**
548 * \brief Gets the cached value from this status signal.
549 *
550 * \details Gets the cached value. To make sure the value is up-to-date
551 * call \c Refresh() or \c WaitForUpdate()
552 *
553 * \returns Cached value
554 */
555 T GetValue() const
556 {
557 if constexpr(wpi::units::traits::is_unit_t_v<T>) {
558 return wpi::units::make_unit<T>(GetValueAsDouble());
559 } else {
560 return static_cast<T>(GetValueAsDouble());
561 }
562 }
563
564 /**
565 * \brief Refreshes the value of this status signal.
566 *
567 * If the user application caches this StatusSignal object
568 * instead of periodically fetching it from the hardware device,
569 * this function must be called to fetch fresh data.
570 *
571 * \details This performs a non-blocking refresh operation. If
572 * you want to wait until you receive the signal, call
573 * \c WaitForUpdate() instead.
574 *
575 * \param reportError Whether to report any errors to the Driver Station/stderr
576 * \returns Reference to itself
577 */
578 StatusSignal<T> &Refresh(bool reportError = true)
579 {
580 RefreshValue(false, 0_s, reportError); // Don't block and error if signal is older than a default timeout
581 return *this;
582 }
583 /**
584 * \brief Waits up to timeoutSec to get the up-to-date status signal value.
585 *
586 * \details This performs a blocking refresh operation. If
587 * you want to non-blocking refresh the signal, call
588 * \c Refresh() instead.
589 *
590 * \param timeoutSec Maximum time to wait for the signal to update
591 * \param reportError Whether to report any errors to the Driver Station/stderr
592 * \returns Reference to itself
593 */
594 StatusSignal<T> &WaitForUpdate(wpi::units::second_t timeoutSec, bool reportError = true)
595 {
596 RefreshValue(true, timeoutSec, reportError);
597 return *this;
598 }
599
600 /**
601 * \brief Checks whether the signal is near a target value within the
602 * given tolerance.
603 *
604 * \param target The target value of the signal
605 * \param tolerance The error tolerance between the target and measured values
606 * \returns Whether the signal is near the target value
607 */
608 bool IsNear(T target, T tolerance) const
609 requires (std::same_as<T, double>)
610 {
611 return fabs(GetValue() - target) <= tolerance;
612 }
613
614 /**
615 * \brief Checks whether the signal is near a target value within the
616 * given tolerance.
617 *
618 * \param target The target value of the signal
619 * \param tolerance The error tolerance between the target and measured values
620 * \returns Whether the signal is near the target value
621 */
622 bool IsNear(T target, T tolerance) const
623 requires (wpi::units::traits::is_unit_t_v<T>)
624 {
625 return wpi::units::math::abs(GetValue() - target) <= tolerance;
626 }
627
628 /**
629 * \brief Get a basic data-only container with a copy of the current signal data.
630 *
631 * If looking for Phoenix 6 logging features, see the SignalLogger class instead.
632 *
633 * \returns Basic structure with all relevant information
634 */
636 {
638 toRet.name = GetName();
639 toRet.value = GetValue();
640 toRet.timestamp = GetTimestamp().GetTime();
641 toRet.units = GetUnits();
642 toRet.status = GetStatus();
643 return toRet;
644 }
645
646 /**
647 * \brief Returns a lambda that calls #Refresh and #GetValue on this object. This is useful for command-based programming.
648 *
649 * \returns std::function<T()> that calls #Refresh and returns this signal's value.
650 */
651 std::function<T()> AsSupplier()
652 {
653 return [this]() { return Refresh().GetValue(); };
654 }
655
656 friend std::ostream &operator<<(std::ostream &os, StatusSignal<T> const &data)
657 {
658 if constexpr(wpi::units::traits::is_unit_t_v<T>) {
659 os << data.GetValue().value() << " " << data.GetUnits();
660 } else {
661 os << data.GetValue() << " " << data.GetUnits();
662 }
663 return os;
664 }
665 std::string ToString() const
666 {
667 std::stringstream ss;
668 ss << *this;
669 return ss.str();
670 }
671 };
672
673}
674}
Collection of objects that can report alerts.
Definition Alertable.hpp:109
A collection of timestamps for a received signal.
Definition Timestamp.hpp:123
Class that provides operations to retrieve information about a status signal.
Definition StatusSignal.hpp:39
ctre::phoenix::StatusCode SetUpdateFrequency(wpi::units::hertz_t frequencyHz, wpi::units::second_t timeoutSeconds=100_ms)
Sets the rate at which the device will publish this signal.
Definition StatusSignal.hpp:193
void RefreshValue(bool waitForUpdate, wpi::units::second_t timeout, bool reportError)
static ctre::phoenix::StatusCode WaitForAll(wpi::units::second_t timeoutSeconds, bool reportError, std::span< BaseStatusSignal *const > signals)
Waits for new data on all provided signals up to timeout.
Definition StatusSignal.hpp:374
static U GetLatencyCompensatedValue(StatusSignal< U > const &signal, StatusSignal< U_PER_SEC > const &signalSlope, wpi::units::second_t maxLatencySeconds=0.300_s)
Performs latency compensation on signal using the signalSlope and signal's latency to determine the m...
Definition StatusSignal.hpp:240
AllTimestamps const & GetAllTimestamps() const
Gets the timestamps of this signals.
Definition StatusSignal.hpp:135
static ctre::phoenix::StatusCode WaitForAll(wpi::units::second_t timeoutSeconds, bool reportError, Signals &... signals)
Waits for new data on all provided signals up to timeout.
Definition StatusSignal.hpp:339
static ctre::phoenix::StatusCode WaitForAll(wpi::units::second_t timeoutSeconds, std::span< BaseStatusSignal *const > signals)
Waits for new data on all provided signals up to timeout.
Definition StatusSignal.hpp:306
static std::string Status_GetUnits(uint32_t signal)
static ctre::phoenix::StatusCode RefreshAll(std::span< BaseStatusSignal *const > signals)
Performs a non-blocking refresh on all provided signals.
Definition StatusSignal.hpp:405
static ctre::phoenix::StatusCode WaitForAllImpl(char const *location, wpi::units::second_t timeoutSeconds, bool reportError, std::span< BaseStatusSignal *const > signals)
std::string const & GetName() const
Gets the name of this signal.
Definition StatusSignal.hpp:117
ctre::phoenix::StatusCode GetStatus() const
Gets the status code of the last time this signal was refreshed.
Definition StatusSignal.hpp:155
wpi::units::hertz_t GetAppliedUpdateFrequency() const
Gets the rate at which the device will publish this signal.
Definition StatusSignal.hpp:207
static bool IsAllGood(Signals const &... signals)
Checks if all signals have an OK error code.
Definition StatusSignal.hpp:450
bool HasUpdated()
Checks whether the signal has been updated since the last check.
Definition StatusSignal.hpp:164
static ctre::phoenix::StatusCode RefreshAll(bool reportError, std::span< BaseStatusSignal *const > signals)
Performs a non-blocking refresh on all provided signals.
Definition StatusSignal.hpp:437
BaseStatusSignal(ctre::phoenix::StatusCode error)
Definition StatusSignal.hpp:80
static ctre::phoenix::StatusCode SetUpdateFrequencyForAll(wpi::units::hertz_t frequencyHz, std::span< BaseStatusSignal *const > signals)
Sets the update frequency of all specified status signals to the provided common frequency.
Definition StatusSignal.hpp:507
std::string const & GetUnits() const
Gets the units for this signal.
Definition StatusSignal.hpp:129
static ctre::phoenix::StatusCode SetUpdateFrequencyForAll(wpi::units::hertz_t frequencyHz, Signals &... signals)
Sets the update frequency of all specified status signals to the provided common frequency.
Definition StatusSignal.hpp:487
static ctre::phoenix::StatusCode RefreshAll(Signals &... signals)
Performs a non-blocking refresh on all provided signals.
Definition StatusSignal.hpp:391
static ctre::phoenix::StatusCode WaitForAll(wpi::units::second_t timeoutSeconds, Signals &... signals)
Waits for new data on all provided signals up to timeout.
Definition StatusSignal.hpp:276
static ctre::phoenix::StatusCode RefreshAll(bool reportError, Signals &... signals)
Performs a non-blocking refresh on all provided signals.
Definition StatusSignal.hpp:422
ctre::phoenix::StatusCode Status_SetUpdateFrequency(double frequencyHz, double timeoutSeconds) const
double GetValueAsDouble() const
Gets the value of this signal as a double.
Definition StatusSignal.hpp:123
static ctre::phoenix::StatusCode Status_WaitForAll(std::span< BaseStatusSignal *const > signals, double timeoutSeconds)
static bool IsAllGood(std::span< BaseStatusSignal const *const > signals)
Checks if all signals have an OK error code.
Definition StatusSignal.hpp:460
ctre::phoenix::StatusCode Status_Get(bool bWaitForUpdate, double timeoutSeconds)
Timestamp const & GetTimestamp() const
Gets the most accurate timestamp available for this signal.
Definition StatusSignal.hpp:149
BaseStatusSignal(hardware::DeviceIdentifier deviceIdentifier, uint16_t spn, std::string signalName, std::function< void()> checkFirmVersFunction, std::function< std::map< uint16_t, std::string >()> const &unitsGenerator={})
Definition StatusSignal.hpp:57
void UpdateUnits(uint16_t unitsKey)
void RegisterAlerts(AlertableCollection &collection) override
Registers all alerts for this type to the provided collection.
double Status_GetAppliedUpdateFrequency() const
static ctre::phoenix::StatusCode Status_SetUpdateFrequencyForAll(std::span< BaseStatusSignal *const > signals, double frequencyHz, double timeoutSeconds)
Interface for all types that can report a Phoenix alert.
Definition Alertable.hpp:21
Represents a status signal with data of type T, and operations available to retrieve information abou...
Definition StatusSignal.hpp:523
std::string ToString() const
Definition StatusSignal.hpp:665
StatusSignal< T > & Refresh(bool reportError=true)
Refreshes the value of this status signal.
Definition StatusSignal.hpp:578
T GetValue() const
Gets the cached value from this status signal.
Definition StatusSignal.hpp:555
friend std::ostream & operator<<(std::ostream &os, StatusSignal< T > const &data)
Definition StatusSignal.hpp:656
bool IsNear(T target, T tolerance) const
Checks whether the signal is near a target value within the given tolerance.
Definition StatusSignal.hpp:622
StatusSignal< T > & WaitForUpdate(wpi::units::second_t timeoutSec, bool reportError=true)
Waits up to timeoutSec to get the up-to-date status signal value.
Definition StatusSignal.hpp:594
SignalMeasurement< T > GetDataCopy() const
Get a basic data-only container with a copy of the current signal data.
Definition StatusSignal.hpp:635
std::function< T()> AsSupplier()
Returns a lambda that calls Refresh and GetValue on this object.
Definition StatusSignal.hpp:651
bool IsNear(T target, T tolerance) const
Checks whether the signal is near a target value within the given tolerance.
Definition StatusSignal.hpp:608
Information about the timestamp of a signal.
Definition Timestamp.hpp:17
wpi::units::second_t GetLatency() const
Gets the latency of this timestamp compared to now.
Definition Timestamp.hpp:114
The unique identifier for a device.
Definition DeviceIdentifier.hpp:19
Parent class for all devices.
Definition ParentDevice.hpp:25
Status codes reported by APIs, including OK, warnings, and errors.
Definition StatusCodes.h:28
static constexpr int SigNotUpdated
No new response to update signal.
Definition StatusCodes.h:420
Definition ExternalFeedbackConfigs.hpp:17
Definition SpnEnums.hpp:16
Definition ExternalFeedbackConfigs.hpp:16
Definition motor_constants.h:14
Information from a single measurement of a status signal.
Definition SignalMeasurement.hpp:25
T value
The value of the signal.
Definition SignalMeasurement.hpp:33
wpi::units::second_t timestamp
Timestamp of when the data point was taken.
Definition SignalMeasurement.hpp:37
std::string units
The units of the signal measurement.
Definition SignalMeasurement.hpp:41
ctre::phoenix::StatusCode status
Status code response of getting the data.
Definition SignalMeasurement.hpp:45
std::string_view name
The name of the signal.
Definition SignalMeasurement.hpp:29