CTRE Phoenix 6 C++ 26.70.0-alpha-2
Loading...
Searching...
No Matches
HootAutoReplay.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#include <functional>
14
15namespace ctre {
16namespace phoenix6 {
17
18/**
19 * \brief Class for handling automatic logging and replay of custom signal inputs.
20 * Each subsystem typically creates a new instance of this class.
21 *
22 * Note that all StatusSignals are automatically logged and replayed, so they
23 * do not need to be registered with this class. Additionally, the SignalLogger
24 * must be separately started at the start of the robot program.
25 *
26 * \details "Inputs" are signals measured directly from devices that should be
27 * replayed unmodified. By comparison, a processed signal, such as a signal
28 * indicating that a mechanism has reached the target, is considered an "output".
29 * This class should only be used with inputs.
30 *
31 * Inputs are registered with a getter that returns a value to log and a setter
32 * that updates the value in your robot program. For example, a `Vision` class
33 * with a `Pose2d cameraPose` input would register the input using:
34 *
35 * ```
36 * HootAutoReplay autoReplay = HootAutoReplay{}
37 * .WithStruct<wpi::math::Pose2d>(
38 * "Vision/CameraPose",
39 * [this]() -> wpi::math::Pose2d const& { return cameraPose; },
40 * [this](SignalMeasurement<wpi::math::Pose2d> val) {
41 * cameraPose = val.value;
42 * }
43 * );
44 * ```
45 *
46 * After registering all relevant inputs, call #Update() periodically
47 * to perform the following:
48 *
49 * - In normal/simulated robot operation, registered inputs will be
50 * fetched from your robot code using the provided getter and then
51 * logged using the SignalLogger.
52 *
53 * - During Hoot Replay, registered inputs will be fetched from
54 * HootReplay and then updated in your robot code using the
55 * provided setter.
56 *
57 * Note that for non-primitive types, the getter function must return a
58 * reference to or std::span/std::string_view over the original data. As a
59 * result, it cannot return a temporary value. If a getter lambda must return
60 * a temporary value, capture a shared_ptr in the lambda, then modify and
61 * return the value stored in the shared_ptr.
62 */
64 std::vector<std::function<void(wpi::units::second_t)>> updates;
65
66public:
67 /**
68 * \brief Updates the state of the robot program by doing one of the following:
69 *
70 * - In normal/simulated robot operation, registered signals will be
71 * fetched from your robot code using the provided getter and then
72 * logged using the SignalLogger.
73 *
74 * - During Hoot Replay, registered signals will be fetched from
75 * HootReplay and then updated in your robot code using the
76 * provided setter.
77 *
78 * This should be called periodically, typically in the subsystem.
79 */
80 void Update() const
81 {
82 auto const timestamp = utils::GetCurrentTime();
83 for (auto const &update : updates) {
84 update(timestamp);
85 }
86 }
87
88#if (__has_include(<wpi/system/RobotController.hpp>) && __has_include(<wpi/system/Timer.hpp>)) || defined(_CTRE_DOCS_)
89 /**
90 * \brief Registers Timer::GetTimestamp() logging and playback with this
91 * instance. This should only be applied to one instance in the robot
92 * program.
93 *
94 * \returns this object
95 */
97#endif
98
99#if (__has_include(<wpi/driverstation/internal/DriverStationBackend.hpp>) && __has_include(<wpi/simulation/DriverStationSim.hpp>)) || defined(_CTRE_DOCS_)
100 /**
101 * \brief Registers Driver Station logging and playback with this instance,
102 * excluding joysticks and match info. This should only be applied to one
103 * instance in the robot program.
104 *
105 * The #Update() of this HootAutoReplay instance should be scheduled
106 * in the Robot constructor using AddPeriodic() with an offset of -1 ms:
107 * ```
108 * AddPeriodic([this] { autoReplay.Update(); }, DEFAULT_PERIOD, -1_ms);
109 * ```
110 *
111 * \returns this object
112 */
114
115 /**
116 * \brief Registers joystick logging and playback with this instance.
117 * This should only be applied to one instance in the robot program.
118 *
119 * To get joysticks to play back during Hoot Replay, "Turn off DS" must be
120 * checked in the simulation GUI (under "DS" at the top of the window).
121 *
122 * The #Update() of this HootAutoReplay instance should be scheduled
123 * in the Robot constructor using AddPeriodic() with an offset of -1 ms:
124 * ```
125 * AddPeriodic([this] { autoReplay.Update(); }, DEFAULT_PERIOD, -1_ms);
126 * ```
127 *
128 * \returns this object
129 */
131
132 /**
133 * \brief Registers match info logging and playback with this instance.
134 * This should only be applied to one instance in the robot program.
135 *
136 * The #Update() of this HootAutoReplay instance should be scheduled
137 * in the Robot constructor using AddPeriodic() with an offset of -1 ms:
138 * ```
139 * AddPeriodic([this] { autoReplay.Update(); }, DEFAULT_PERIOD, -1_ms);
140 * ```
141 *
142 * \returns this object
143 */
145#endif
146
147 /**
148 * \brief Registers the schema-serialized bytes as a Hoot-Replayed input.
149 *
150 * \param name Name of the signal in the log
151 * \param schemaName Name of the schema
152 * \param type Type of the schema, such as struct or protobuf
153 * \param schema Schema bytes to write
154 * \param getter Function that returns the current value of the input
155 * \param setter Function that sets the input to a new value
156 * \returns this object
157 */
159 std::string name, std::string schemaName,
160 HootSchemaType type, std::span<uint8_t const> schema,
161 std::function<std::span<uint8_t const>()> getter,
162 std::function<void(SignalMeasurement<std::vector<uint8_t>>)> setter
163 );
164
165 /**
166 * \brief Registers the schema-serialized bytes as a Hoot-Replayed input.
167 *
168 * \param name Name of the signal in the log
169 * \param schemaName Name of the schema
170 * \param type Type of the schema, such as struct or protobuf
171 * \param schema Schema string to write
172 * \param getter Function that returns the current value of the input
173 * \param setter Function that sets the input to a new value
174 * \returns this object
175 */
177 std::string name, std::string schemaName,
178 HootSchemaType type, std::string_view schema,
179 std::function<std::span<uint8_t const>()> getter,
180 std::function<void(SignalMeasurement<std::vector<uint8_t>>)> setter
181 );
182
183#if __has_include(<wpi/util/struct/Struct.hpp>) || defined(_CTRE_DOCS_)
184 /**
185 * \brief Registers the WPILib Struct as a Hoot-Replayed input.
186 *
187 * \tparam T Struct type
188 * \tparam I Struct info types
189 * \param name Name of the signal in the log
190 * \param info Optional struct type info
191 * \param getter Function that returns the current value of the input
192 * \param setter Function that sets the input to a new value
193 * \returns this object
194 */
195 template <typename T, typename... I>
196 requires wpi::util::StructSerializable<T, I...>
198 std::string name, I &&... info,
199 std::function<T const &()> getter,
200 std::function<void(SignalMeasurement<T>)> setter
201 ) {
202 if (utils::IsReplay()) {
203 updates.emplace_back([name=std::move(name), ... info=std::forward<I>(info), setter=std::move(setter)](auto) {
204 auto val = HootReplay::GetStruct<T>(name, info...);
205 if (val.status.IsOK() && val.value) {
207 std::move(val.name),
208 std::move(*val.value),
209 val.timestamp,
210 std::move(val.units),
211 val.status
212 };
213 setter(std::move(v));
214 }
215 });
216 } else {
217 updates.emplace_back([name=std::move(name), ... info=std::forward<I>(info), getter=std::move(getter)](auto timestamp) {
218 SignalLogger::WriteStruct(name, info..., getter(), timestamp);
219 });
220 }
221 return *this;
222 }
223
224 /**
225 * \brief Registers the array of WPILib Structs as a Hoot-Replayed input.
226 *
227 * \tparam T Struct type
228 * \tparam I Struct info types
229 * \param name Name of the signal in the log
230 * \param info Optional struct type info
231 * \param getter Function that returns the current value of the input
232 * \param setter Function that sets the input to a new value
233 * \returns this object
234 */
235 template <typename T, typename... I>
236 requires wpi::util::StructSerializable<T, I...>
238 std::string name, I &&... info,
239 std::function<std::span<T const>()> getter,
240 std::function<void(SignalMeasurement<std::vector<T>>)> setter
241 ) {
242 if (utils::IsReplay()) {
243 updates.emplace_back([name=std::move(name), ... info=std::forward<I>(info), setter=std::move(setter)](auto) {
244 auto val = HootReplay::GetStructArray<T>(name, info...);
245 if (val.status.IsOK() && val.value) {
247 std::move(val.name),
248 std::move(*val.value),
249 val.timestamp,
250 std::move(val.units),
251 val.status
252 };
253 setter(std::move(v));
254 }
255 });
256 } else {
257 updates.emplace_back([name=std::move(name), ... info=std::forward<I>(info), getter=std::move(getter)](auto timestamp) {
258 SignalLogger::WriteStructArray(name, info..., getter(), timestamp);
259 });
260 }
261 return *this;
262 }
263#endif
264
265#if __has_include(<wpi/util/protobuf/Protobuf.hpp>) || defined(_CTRE_DOCS_)
266 /**
267 * \brief Registers the protobuf as a Hoot-Replayed input.
268 *
269 * \tparam T Protobuf type
270 * \param name Name of the signal in the log
271 * \param getter Function that returns the current value of the input
272 * \param setter Function that sets the input to a new value
273 * \returns this object
274 */
275 template <wpi::util::ProtobufSerializable T>
277 std::string name,
278 std::function<T const &()> getter,
279 std::function<void(SignalMeasurement<T>)> setter
280 ) {
281 if (utils::IsReplay()) {
282 updates.emplace_back([name=std::move(name), setter=std::move(setter)](auto) {
283 auto val = HootReplay::GetProtobuf<T>(name);
284 if (val.status.IsOK() && val.value) {
286 std::move(val.name),
287 std::move(*val.value),
288 val.timestamp,
289 std::move(val.units),
290 val.status
291 };
292 setter(std::move(v));
293 }
294 });
295 } else {
296 updates.emplace_back([name=std::move(name), getter=std::move(getter)](auto timestamp) {
297 SignalLogger::WriteProtobuf(name, getter(), timestamp);
298 });
299 }
300 return *this;
301 }
302#endif
303
304 /**
305 * \brief Registers the raw data bytes as a Hoot-Replayed input.
306 *
307 * \param name Name of the signal in the log
308 * \param getter Function that returns the current value of the input
309 * \param setter Function that sets the input to a new value
310 * \returns this object
311 */
313 std::string name,
314 std::function<std::span<uint8_t const>()> getter,
315 std::function<void(SignalMeasurement<std::vector<uint8_t>>)> setter
316 );
317
318 /**
319 * \brief Registers the boolean as a Hoot-Replayed input.
320 *
321 * \param name Name of the signal in the log
322 * \param getter Function that returns the current value of the input
323 * \param setter Function that sets the input to a new value
324 * \returns this object
325 */
327 std::string name,
328 std::function<bool()> getter,
329 std::function<void(SignalMeasurement<bool>)> setter
330 );
331
332 /**
333 * \brief Registers the integer as a Hoot-Replayed input.
334 *
335 * \param name Name of the signal in the log
336 * \param getter Function that returns the current value of the input
337 * \param setter Function that sets the input to a new value
338 * \param units Units of the signal in the log
339 * \returns this object
340 */
342 std::string name,
343 std::function<int64_t()> getter,
344 std::function<void(SignalMeasurement<int64_t>)> setter,
345 std::string units = ""
346 );
347
348 /**
349 * \brief Registers the float as a Hoot-Replayed input.
350 *
351 * \param name Name of the signal in the log
352 * \param getter Function that returns the current value of the input
353 * \param setter Function that sets the input to a new value
354 * \param units Units of the signal in the log
355 * \returns this object
356 */
358 std::string name,
359 std::function<float()> getter,
360 std::function<void(SignalMeasurement<float>)> setter,
361 std::string units = ""
362 );
363
364 /**
365 * \brief Registers the double as a Hoot-Replayed input.
366 *
367 * \param name Name of the signal in the log
368 * \param getter Function that returns the current value of the input
369 * \param setter Function that sets the input to a new value
370 * \param units Units of the signal in the log
371 * \returns this object
372 */
374 std::string name,
375 std::function<double()> getter,
376 std::function<void(SignalMeasurement<double>)> setter,
377 std::string units = ""
378 );
379
380 /**
381 * \brief Registers the string as a Hoot-Replayed input.
382 *
383 * \param name Name of the signal in the log
384 * \param getter Function that returns the current value of the input
385 * \param setter Function that sets the input to a new value
386 * \returns this object
387 */
389 std::string name,
390 std::function<std::string_view()> getter,
391 std::function<void(SignalMeasurement<std::string>)> setter
392 );
393
394 /**
395 * \brief Registers the unit value as a Hoot-Replayed input.
396 *
397 * \tparam U Unit type
398 * \param name Name of the signal in the log
399 * \param getter Function that returns the current value of the input
400 * \param setter Function that sets the input to a new value
401 * \returns this object
402 */
403 template <typename U>
404 requires wpi::units::traits::is_unit_t_v<U>
406 std::string name,
407 std::function<U()> getter,
408 std::function<void(SignalMeasurement<U>)> setter
409 ) {
410 if (utils::IsReplay()) {
411 updates.emplace_back([name=std::move(name), setter=std::move(setter)](auto) {
412 auto val = HootReplay::GetValue<U>(name);
413 if (val.status.IsOK()) {
414 setter(std::move(val));
415 }
416 });
417 } else {
418 updates.emplace_back([name=std::move(name), getter=std::move(getter)](auto timestamp) {
419 SignalLogger::WriteValue(name, getter(), timestamp);
420 });
421 }
422 return *this;
423 }
424
425 /**
426 * \brief Registers the array of booleans as a Hoot-Replayed input.
427 *
428 * \param name Name of the signal in the log
429 * \param getter Function that returns the current value of the input
430 * \param setter Function that sets the input to a new value
431 * \returns this object
432 */
434 std::string name,
435 std::function<std::span<bool const>()> getter,
436 std::function<void(SignalMeasurement<std::vector<uint8_t>>)> setter
437 );
438
439 /**
440 * \brief Registers the array of booleans as a Hoot-Replayed input.
441 *
442 * \param name Name of the signal in the log
443 * \param getter Function that returns the current value of the input
444 * \param setter Function that sets the input to a new value
445 * \returns this object
446 */
448 std::string name,
449 std::function<std::span<uint8_t const>()> getter,
450 std::function<void(SignalMeasurement<std::vector<uint8_t>>)> setter
451 );
452
453 /**
454 * \brief Registers the array of integers as a Hoot-Replayed input.
455 *
456 * \param name Name of the signal in the log
457 * \param getter Function that returns the current value of the input
458 * \param setter Function that sets the input to a new value
459 * \param units Units of the signal in the log
460 * \returns this object
461 */
463 std::string name,
464 std::function<std::span<int64_t const>()> getter,
465 std::function<void(SignalMeasurement<std::vector<int64_t>>)> setter,
466 std::string units = ""
467 );
468
469 /**
470 * \brief Registers the array of floats as a Hoot-Replayed input.
471 *
472 * \param name Name of the signal in the log
473 * \param getter Function that returns the current value of the input
474 * \param setter Function that sets the input to a new value
475 * \param units Units of the signal in the log
476 * \returns this object
477 */
479 std::string name,
480 std::function<std::span<float const>()> getter,
481 std::function<void(SignalMeasurement<std::vector<float>>)> setter,
482 std::string units = ""
483 );
484
485 /**
486 * \brief Registers the array of doubles as a Hoot-Replayed input.
487 *
488 * \param name Name of the signal in the log
489 * \param getter Function that returns the current value of the input
490 * \param setter Function that sets the input to a new value
491 * \param units Units of the signal in the log
492 * \returns this object
493 */
495 std::string name,
496 std::function<std::span<double const>()> getter,
497 std::function<void(SignalMeasurement<std::vector<double>>)> setter,
498 std::string units = ""
499 );
500
501 /**
502 * \brief Registers the array of strings as a Hoot-Replayed input.
503 *
504 * \param name Name of the signal in the log
505 * \param getter Function that returns the current value of the input
506 * \param setter Function that sets the input to a new value
507 * \returns this object
508 */
510 std::string name,
511 std::function<std::span<std::string_view const>()> getter,
512 std::function<void(SignalMeasurement<std::vector<std::string>>)> setter
513 );
514
515 /**
516 * \brief Registers the array of strings as a Hoot-Replayed input.
517 *
518 * \param name Name of the signal in the log
519 * \param getter Function that returns the current value of the input
520 * \param setter Function that sets the input to a new value
521 * \returns this object
522 */
524 std::string name,
525 std::function<std::span<std::string const>()> getter,
526 std::function<void(SignalMeasurement<std::vector<std::string>>)> setter
527 );
528};
529
530}
531}
Class for handling automatic logging and replay of custom signal inputs.
Definition HootAutoReplay.hpp:63
HootAutoReplay & WithMatchInfoReplay()
Registers match info logging and playback with this instance.
HootAutoReplay & WithBooleanArray(std::string name, std::function< std::span< uint8_t const >()> getter, std::function< void(SignalMeasurement< std::vector< uint8_t > >)> setter)
Registers the array of booleans as a Hoot-Replayed input.
HootAutoReplay & WithFloatArray(std::string name, std::function< std::span< float const >()> getter, std::function< void(SignalMeasurement< std::vector< float > >)> setter, std::string units="")
Registers the array of floats as a Hoot-Replayed input.
HootAutoReplay & WithRaw(std::string name, std::function< std::span< uint8_t const >()> getter, std::function< void(SignalMeasurement< std::vector< uint8_t > >)> setter)
Registers the raw data bytes as a Hoot-Replayed input.
HootAutoReplay & WithSchemaValue(std::string name, std::string schemaName, HootSchemaType type, std::string_view schema, std::function< std::span< uint8_t const >()> getter, std::function< void(SignalMeasurement< std::vector< uint8_t > >)> setter)
Registers the schema-serialized bytes as a Hoot-Replayed input.
HootAutoReplay & WithTimestampReplay()
Registers Timer::GetTimestamp() logging and playback with this instance.
HootAutoReplay & WithDouble(std::string name, std::function< double()> getter, std::function< void(SignalMeasurement< double >)> setter, std::string units="")
Registers the double as a Hoot-Replayed input.
HootAutoReplay & WithValue(std::string name, std::function< U()> getter, std::function< void(SignalMeasurement< U >)> setter)
Registers the unit value as a Hoot-Replayed input.
Definition HootAutoReplay.hpp:405
HootAutoReplay & WithStringArray(std::string name, std::function< std::span< std::string const >()> getter, std::function< void(SignalMeasurement< std::vector< std::string > >)> setter)
Registers the array of strings as a Hoot-Replayed input.
HootAutoReplay & WithStringArray(std::string name, std::function< std::span< std::string_view const >()> getter, std::function< void(SignalMeasurement< std::vector< std::string > >)> setter)
Registers the array of strings as a Hoot-Replayed input.
HootAutoReplay & WithDoubleArray(std::string name, std::function< std::span< double const >()> getter, std::function< void(SignalMeasurement< std::vector< double > >)> setter, std::string units="")
Registers the array of doubles as a Hoot-Replayed input.
HootAutoReplay & WithBooleanArray(std::string name, std::function< std::span< bool const >()> getter, std::function< void(SignalMeasurement< std::vector< uint8_t > >)> setter)
Registers the array of booleans as a Hoot-Replayed input.
HootAutoReplay & WithJoystickReplay()
Registers joystick logging and playback with this instance.
HootAutoReplay & WithBoolean(std::string name, std::function< bool()> getter, std::function< void(SignalMeasurement< bool >)> setter)
Registers the boolean as a Hoot-Replayed input.
HootAutoReplay & WithStruct(std::string name, I &&... info, std::function< T const &()> getter, std::function< void(SignalMeasurement< T >)> setter)
Registers the WPILib Struct as a Hoot-Replayed input.
Definition HootAutoReplay.hpp:197
HootAutoReplay & WithString(std::string name, std::function< std::string_view()> getter, std::function< void(SignalMeasurement< std::string >)> setter)
Registers the string as a Hoot-Replayed input.
HootAutoReplay & WithFloat(std::string name, std::function< float()> getter, std::function< void(SignalMeasurement< float >)> setter, std::string units="")
Registers the float as a Hoot-Replayed input.
HootAutoReplay & WithInteger(std::string name, std::function< int64_t()> getter, std::function< void(SignalMeasurement< int64_t >)> setter, std::string units="")
Registers the integer as a Hoot-Replayed input.
void Update() const
Updates the state of the robot program by doing one of the following:
Definition HootAutoReplay.hpp:80
HootAutoReplay & WithIntegerArray(std::string name, std::function< std::span< int64_t const >()> getter, std::function< void(SignalMeasurement< std::vector< int64_t > >)> setter, std::string units="")
Registers the array of integers as a Hoot-Replayed input.
HootAutoReplay & WithDriverStationReplay()
Registers Driver Station logging and playback with this instance, excluding joysticks and match info.
HootAutoReplay & WithStructArray(std::string name, I &&... info, std::function< std::span< T const >()> getter, std::function< void(SignalMeasurement< std::vector< T > >)> setter)
Registers the array of WPILib Structs as a Hoot-Replayed input.
Definition HootAutoReplay.hpp:237
HootAutoReplay & WithProtobuf(std::string name, std::function< T const &()> getter, std::function< void(SignalMeasurement< T >)> setter)
Registers the protobuf as a Hoot-Replayed input.
Definition HootAutoReplay.hpp:276
HootAutoReplay & WithSchemaValue(std::string name, std::string schemaName, HootSchemaType type, std::span< uint8_t const > schema, std::function< std::span< uint8_t const >()> getter, std::function< void(SignalMeasurement< std::vector< uint8_t > >)> setter)
Registers the schema-serialized bytes as a Hoot-Replayed input.
static SignalMeasurement< std::optional< T > > GetStruct(std::string_view name, I const &... info)
Gets a WPILib Struct user signal.
Definition HootReplay.hpp:227
static SignalMeasurement< std::optional< std::vector< T > > > GetStructArray(std::string_view name, I const &... info)
Gets a WPILib Struct array user signal.
Definition HootReplay.hpp:262
static SignalMeasurement< U > GetValue(std::string_view name)
Gets a unit value user signal.
Definition HootReplay.hpp:382
static SignalMeasurement< std::optional< T > > GetProtobuf(std::string_view name)
Gets a Protobuf user signal.
Definition HootReplay.hpp:307
static ctre::phoenix::StatusCode WriteStructArray(std::string_view name, std::span< T const > values, I const &... info, wpi::units::second_t timestamp=utils::GetCurrentTime())
Writes the array of WPILib Structs to the log file.
Definition SignalLogger.hpp:236
static ctre::phoenix::StatusCode WriteStruct(std::string_view name, T const &value, I const &... info, wpi::units::second_t timestamp=utils::GetCurrentTime())
Writes the WPILib Struct to the log file.
Definition SignalLogger.hpp:189
static ctre::phoenix::StatusCode WriteProtobuf(std::string_view name, T const &value, wpi::units::second_t timestamp=utils::GetCurrentTime())
Writes the protobuf to the log file.
Definition SignalLogger.hpp:281
static ctre::phoenix::StatusCode WriteValue(std::string_view name, U value, wpi::units::second_t timestamp=utils::GetCurrentTime())
Writes the unit value to the log file.
Definition SignalLogger.hpp:397
CTREXPORT bool IsReplay()
Get whether the program is running in replay mode.
wpi::units::second_t GetCurrentTime()
Get the current timestamp.
Definition Utils.hpp:27
Definition ExternalFeedbackConfigs.hpp:16
HootSchemaType
Supported schema types for a hoot user signal.
Definition HootSchemaType.hpp:15
Definition motor_constants.h:14
Information from a single measurement of a status signal.
Definition SignalMeasurement.hpp:25