WPILibC++ 2025.1.1
Loading...
Searching...
No Matches
LEDPattern.h
Go to the documentation of this file.
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#pragma once
6
7#include <functional>
8#include <span>
9#include <utility>
10
11#include <units/frequency.h>
12#include <units/length.h>
13#include <units/time.h>
14#include <units/velocity.h>
15
16#include "frc/AddressableLED.h"
17#include "util/Color.h"
18
19namespace frc {
20
22 public:
23 /**
24 * A wrapper around a length and an arbitrary reader function that accepts an
25 * LED index and returns data for the LED at that index. This configuration
26 * allows us to abstract over different container types without templating.
27 */
28 class LEDReader {
29 public:
30 LEDReader(std::function<frc::AddressableLED::LEDData(int)> impl,
31 size_t size)
32 : m_impl{std::move(impl)}, m_size{size} {}
33
35 return m_impl(index);
36 }
37
38 size_t size() const { return m_size; }
39
40 private:
41 std::function<frc::AddressableLED::LEDData(int)> m_impl;
42 size_t m_size;
43 };
44
45 explicit LEDPattern(std::function<void(frc::LEDPattern::LEDReader,
46 std::function<void(int, frc::Color)>)>
47 impl);
48
49 void ApplyTo(LEDReader reader,
50 std::function<void(int, frc::Color)> writer) const;
51
52 /**
53 * Writes the pattern to an LED buffer. Dynamic animations should be called
54 * periodically (such as with a command or with a periodic method) to refresh
55 * the buffer over time.
56 *
57 * This method is intentionally designed to use separate objects for reading
58 * and writing data. By splitting them up, we can easily modify the behavior
59 * of some base pattern to make it scroll, blink, or breathe by intercepting
60 * the data writes to transform their behavior to whatever we like.
61 *
62 * @param data the current data of the LED strip
63 * @param writer data writer for setting new LED colors on the LED strip
64 */
65 void ApplyTo(std::span<frc::AddressableLED::LEDData> data,
66 std::function<void(int, frc::Color)> writer) const;
67
68 /**
69 * Writes the pattern to an LED buffer. Dynamic animations should be called
70 * periodically (such as with a command or with a periodic method) to refresh
71 * the buffer over time.
72 *
73 * This method is intentionally designed to use separate objects for reading
74 * and writing data. By splitting them up, we can easily modify the behavior
75 * of some base pattern to make it scroll, blink, or breathe by intercepting
76 * the data writes to transform their behavior to whatever we like.
77 *
78 * @param data the current data of the LED strip
79 */
80 void ApplyTo(std::span<frc::AddressableLED::LEDData> data) const;
81
82 /**
83 * Creates a pattern with remapped indices.
84 *
85 * @param indexMapper the index mapper
86 * @return the mapped pattern
87 */
88 [[nodiscard]]
89 LEDPattern MapIndex(std::function<size_t(size_t, size_t)> indexMapper);
90
91 /**
92 * Creates a pattern that displays this one in reverse. Scrolling patterns
93 * will scroll in the opposite direction (but at the same speed). It will
94 * treat the end of an LED strip as the start, and the start of the strip as
95 * the end. This can be useful for making ping-pong patterns that travel from
96 * one end of an LED strip to the other, then reverse direction and move back
97 * to the start. This can also be useful when working with LED strips
98 * connected in a serpentine pattern (where the start of one strip is
99 * connected to the end of the previous one).
100 *
101 * @return the reverse pattern
102 */
103 [[nodiscard]]
105
106 /**
107 * Creates a pattern that displays this one, but offset by a certain number of
108 * LEDs. The offset pattern will wrap around, if necessary.
109 *
110 * @param offset how many LEDs to offset by
111 * @return the offset pattern
112 */
113 [[nodiscard]]
114 LEDPattern OffsetBy(int offset);
115
116 /**
117 * Creates a pattern that plays this one scrolling up the buffer. The velocity
118 * controls how fast the pattern returns back to its original position, and is
119 * in terms of the length of the LED strip; scrolling across a segment that is
120 * 10 LEDs long will travel twice as fast as on a segment that's only 5 LEDs
121 * long (assuming equal LED density on both segments).
122 */
123 [[nodiscard]]
124 LEDPattern ScrollAtRelativeSpeed(units::hertz_t velocity);
125
126 /**
127 * Creates a pattern that plays this one scrolling up an LED strip. A negative
128 * velocity makes the pattern play in reverse.
129 *
130 * <p>For example, scrolling a pattern at 4 inches per second along an LED
131 * strip with 60 LEDs per meter:
132 *
133 * <pre>
134 * // LEDs per meter, a known value taken from the spec sheet of our
135 * particular LED strip units::meter_t LED_SPACING = units::meter_t{1 /60.0};
136 *
137 * frc::LEDPattern rainbow = frc::LEDPattern::Rainbow();
138 * frc::LEDPattern scrollingRainbow =
139 * rainbow.ScrollAtAbsoluteSpeed(units::feet_per_second_t{1 / 3.0},
140 * LED_SPACING);
141 * </pre>
142 *
143 * <p>Note that this pattern will scroll <i>faster</i> if applied to a less
144 * dense LED strip (such as 30 LEDs per meter), or <i>slower</i> if applied to
145 * a denser LED strip (such as 120 or 144 LEDs per meter).
146 *
147 * @param velocity how fast the pattern should move along a physical LED strip
148 * @param ledSpacing the distance between adjacent LEDs on the physical LED
149 * strip
150 * @return the scrolling pattern
151 */
152 [[nodiscard]]
153 LEDPattern ScrollAtAbsoluteSpeed(units::meters_per_second_t velocity,
154 units::meter_t ledSpacing);
155
156 /**
157 * Creates a pattern that switches between playing this pattern and turning
158 * the entire LED strip off.
159 *
160 * @param onTime how long the pattern should play for, per cycle
161 * @param offTime how long the pattern should be turned off for, per cycle
162 * @return the blinking pattern
163 */
164 [[nodiscard]]
165 LEDPattern Blink(units::second_t onTime, units::second_t offTime);
166
167 /**
168 * Like {@link LEDPattern::Blink(units::second_t)}, but where the
169 * "off" time is exactly equal to the "on" time.
170 *
171 * @param onTime how long the pattern should play for (and be turned off for),
172 * per cycle
173 * @return the blinking pattern
174 */
175 [[nodiscard]]
176 LEDPattern Blink(units::second_t onTime);
177
178 /**
179 * Creates a pattern that blinks this one on and off in sync with a true/false
180 * signal. The pattern will play while the signal outputs {@code true}, and
181 * will turn off while the signal outputs
182 * {@code false}.
183 *
184 * @param signal the signal to synchronize with
185 * @return the blinking pattern
186 */
187 [[nodiscard]]
188 LEDPattern SynchronizedBlink(std::function<bool()> signal);
189
190 /**
191 * Creates a pattern that brightens and dims this one over time. Brightness
192 * follows a sinusoidal pattern.
193 *
194 * @param period how fast the breathing pattern should complete a single cycle
195 * @return the breathing pattern
196 */
197 [[nodiscard]]
198 LEDPattern Breathe(units::second_t period);
199
200 /**
201 * Creates a pattern that plays this pattern overlaid on another. Anywhere
202 * this pattern sets an LED to off (or {@link frc::Color::kBlack}), the base
203 * pattern will be displayed instead.
204 *
205 * @param base the base pattern to overlay on top of
206 * @return the combined overlay pattern
207 */
208 [[nodiscard]]
210
211 /**
212 * Creates a pattern that displays outputs as a combination of this pattern
213 * and another. Color values are calculated as the average color of both
214 * patterns; if both patterns set the same LED to the same color, then it is
215 * set to that color, but if one pattern sets to one color and the other
216 * pattern sets it to off, then it will show the color of the first pattern
217 * but at approximately half brightness. This is different from {@link
218 * LEDPattern::OverlayOn(const LEDPattern&)}, which will show the base pattern
219 * at full brightness if the overlay is set to off at that position.
220 *
221 * @param other the pattern to blend with
222 * @return the blended pattern
223 */
224 [[nodiscard]]
226
227 /**
228 * Similar to {@link LEDPattern::Blend(const LEDPattern&)}, but performs a
229 * bitwise mask on each color channel rather than averaging the colors for
230 * each LED. This can be helpful for displaying only a portion of the base
231 * pattern by applying a mask that sets the desired area to white, and all
232 * other areas to black. However, it can also be used to display only certain
233 * color channels or hues; for example, masking with {@code
234 * LEDPattern.color(Color.kRed)} will turn off the green and blue channels on
235 * the output pattern, leaving only the red LEDs to be illuminated.
236 *
237 * @param mask the mask to apply
238 * @return the masked pattern
239 */
240 [[nodiscard]]
242
243 /**
244 * Creates a pattern that plays this one, but at a different brightness.
245 * Brightness multipliers are applied per-channel in the RGB space; no HSL or
246 * HSV conversions are applied. Multipliers are also uncapped, which may
247 * result in the original colors washing out and appearing less saturated or
248 * even just a bright white.
249 *
250 * <p>This method is predominantly intended for dimming LEDs to avoid
251 * painfully bright or distracting patterns from playing (apologies to the
252 * 2024 NE Greater Boston field staff).
253 *
254 * <p>For example, dimming can be done simply by adding a call to
255 * `atBrightness` at the end of a pattern:
256 *
257 * <pre>
258 * // Solid red, but at 50% brightness
259 * frc::LEDPattern::Solid(frc::Color::kRed).AtBrightness(0.5);
260 *
261 * // Solid white, but at only 10% (i.e. ~0.5V)
262 * frc::LEDPattern::Solid(frc:Color::kWhite).AtBrightness(0.1);
263 * </pre>
264 *
265 * @param relativeBrightness the multiplier to apply to all channels to modify
266 * brightness
267 * @return the input pattern, displayed at
268 */
269 [[nodiscard]]
270 LEDPattern AtBrightness(double relativeBrightness);
271
272 /** A pattern that turns off all LEDs. */
273 static LEDPattern Off();
274
275 /**
276 * Creates a pattern that displays a single static color along the entire
277 * length of the LED strip.
278 *
279 * @param color the color to display
280 * @return the pattern
281 */
283
284 /**
285 * Creates a pattern that works as a mask layer for {@link
286 * LEDPattern::Mask(const LEDPattern&)} that illuminates only the portion of
287 * the LED strip corresponding with some progress. The mask pattern will start
288 * from the base and set LEDs to white at a proportion equal to the progress
289 * returned by the function. Some usages for this could be for displaying
290 * progress of a flywheel to its target velocity, progress of a complex
291 * autonomous sequence, or the height of an elevator.
292 *
293 * <p>For example, creating a mask for displaying a red-to-blue gradient,
294 * starting from the red end, based on where an elevator is in its range of
295 * travel.
296 *
297 * <pre>
298 * frc::LEDPattern basePattern =
299 * frc::LEDPattern::Gradient(frc::Color::kRed, frc::Color::kBlue);
300 * frc::LEDPattern progressPattern =
301 * basePattern.Mask(frc::LEDPattern::ProgressMaskLayer([&]() {
302 * return elevator.GetHeight() / elevator.MaxHeight();
303 * });
304 * </pre>
305 *
306 * @param progressFunction the function to call to determine the progress.
307 * This should return values in the range [0, 1]; any values outside that
308 * range will be clamped.
309 * @return the mask pattern
310 */
311 static LEDPattern ProgressMaskLayer(std::function<double()> progressFunction);
312
313 /**
314 * Display a set of colors in steps across the length of the LED strip. No
315 * interpolation is done between colors. Colors are specified by the first LED
316 * on the strip to show that color. The last color in the map will be
317 * displayed all the way to the end of the strip. LEDs positioned before the
318 * first specified step will be turned off (you can think of this as if
319 * there's a 0 -> black step by default).
320 *
321 * @param steps a map of progress to the color to start displaying at that
322 * position along the LED strip
323 * @return a motionless step pattern
324 */
325 static LEDPattern Steps(std::span<const std::pair<double, Color>> steps);
326
327 /**
328 * Display a set of colors in steps across the length of the LED strip. No
329 * interpolation is done between colors. Colors are specified by the first LED
330 * on the strip to show that color. The last color in the map will be
331 * displayed all the way to the end of the strip. LEDs positioned before the
332 * first specified step will be turned off (you can think of this as if
333 * there's a 0 -> black step by default).
334 *
335 * @param steps a map of progress to the color to start displaying at that
336 * position along the LED strip
337 * @return a motionless step pattern
338 */
340 std::initializer_list<std::pair<double, Color>> steps);
341
342 /** Types of gradients. */
344 /**
345 * A continuous gradient, where the gradient wraps around to allow for
346 * seamless scrolling effects.
347 */
349 /**
350 * A discontinuous gradient, where the first pixel is set to the first color
351 * of the gradient and the final pixel is set to the last color of the
352 * gradient. There is no wrapping effect, so scrolling effects will display
353 * an obvious seam.
354 */
356 };
357
358 /**
359 * Creates a pattern that displays a non-animated gradient of colors across
360 * the entire length of the LED strip. Colors are evenly distributed along the
361 * full length of the LED strip. The gradient type is configured with the
362 * {@code type} parameter, allowing the gradient to be either continuous (no
363 * seams, good for scrolling effects) or discontinuous (a clear seam is
364 * visible, but the gradient applies to the full length of the LED strip
365 * without needing to use some space for wrapping).
366 *
367 * @param type the type of gradient (continuous or discontinuous)
368 * @param colors the colors to display in the gradient
369 * @return a motionless gradient pattern
370 */
371 static LEDPattern Gradient(GradientType type, std::span<const Color> colors);
372
373 /**
374 * Creates a pattern that displays a non-animated gradient of colors across
375 * the entire length of the LED strip. Colors are evenly distributed along the
376 * full length of the LED strip. The gradient type is configured with the
377 * {@code type} parameter, allowing the gradient to be either continuous (no
378 * seams, good for scrolling effects) or discontinuous (a clear seam is
379 * visible, but the gradient applies to the full length of the LED strip
380 * without needing to use some space for wrapping).
381 *
382 * @param type the type of gradient (continuous or discontinuous)
383 * @param colors the colors to display in the gradient
384 * @return a motionless gradient pattern
385 */
387 std::initializer_list<Color> colors);
388
389 /**
390 * Creates an LED pattern that displays a rainbow across the color wheel. The
391 * rainbow pattern will stretch across the entire length of the LED strip.
392 *
393 * @param saturation the saturation of the HSV colors, in [0, 255]
394 * @param value the value of the HSV colors, in [0, 255]
395 * @return the rainbow pattern
396 */
397 static LEDPattern Rainbow(int saturation, int value);
398
399 private:
400 std::function<void(frc::LEDPattern::LEDReader,
401 std::function<void(int, frc::Color)>)>
402 m_impl;
403};
404} // namespace frc
Definition AddressableLED.h:33
Represents colors that can be used with Addressable LEDs.
Definition Color.h:24
A wrapper around a length and an arbitrary reader function that accepts an LED index and returns data...
Definition LEDPattern.h:28
frc::AddressableLED::LEDData operator[](size_t index) const
Definition LEDPattern.h:34
LEDReader(std::function< frc::AddressableLED::LEDData(int)> impl, size_t size)
Definition LEDPattern.h:30
size_t size() const
Definition LEDPattern.h:38
Definition LEDPattern.h:21
LEDPattern Breathe(units::second_t period)
Creates a pattern that brightens and dims this one over time.
LEDPattern(std::function< void(frc::LEDPattern::LEDReader, std::function< void(int, frc::Color)>)> impl)
LEDPattern Blink(units::second_t onTime, units::second_t offTime)
Creates a pattern that switches between playing this pattern and turning the entire LED strip off.
LEDPattern MapIndex(std::function< size_t(size_t, size_t)> indexMapper)
Creates a pattern with remapped indices.
LEDPattern SynchronizedBlink(std::function< bool()> signal)
Creates a pattern that blinks this one on and off in sync with a true/false signal.
static LEDPattern Solid(const Color color)
Creates a pattern that displays a single static color along the entire length of the LED strip.
LEDPattern AtBrightness(double relativeBrightness)
Creates a pattern that plays this one, but at a different brightness.
LEDPattern Blend(const LEDPattern &other)
Creates a pattern that displays outputs as a combination of this pattern and another.
GradientType
Types of gradients.
Definition LEDPattern.h:343
@ kContinuous
A continuous gradient, where the gradient wraps around to allow for seamless scrolling effects.
Definition LEDPattern.h:348
@ kDiscontinuous
A discontinuous gradient, where the first pixel is set to the first color of the gradient and the fin...
Definition LEDPattern.h:355
static LEDPattern Gradient(GradientType type, std::span< const Color > colors)
Creates a pattern that displays a non-animated gradient of colors across the entire length of the LED...
static LEDPattern Gradient(GradientType type, std::initializer_list< Color > colors)
Creates a pattern that displays a non-animated gradient of colors across the entire length of the LED...
void ApplyTo(std::span< frc::AddressableLED::LEDData > data) const
Writes the pattern to an LED buffer.
void ApplyTo(std::span< frc::AddressableLED::LEDData > data, std::function< void(int, frc::Color)> writer) const
Writes the pattern to an LED buffer.
LEDPattern ScrollAtRelativeSpeed(units::hertz_t velocity)
Creates a pattern that plays this one scrolling up the buffer.
LEDPattern Mask(const LEDPattern &mask)
Similar to LEDPattern::Blend(const LEDPattern&), but performs a bitwise mask on each color channel ra...
LEDPattern Reversed()
Creates a pattern that displays this one in reverse.
static LEDPattern Rainbow(int saturation, int value)
Creates an LED pattern that displays a rainbow across the color wheel.
static LEDPattern Steps(std::span< const std::pair< double, Color > > steps)
Display a set of colors in steps across the length of the LED strip.
LEDPattern OverlayOn(const LEDPattern &base)
Creates a pattern that plays this pattern overlaid on another.
LEDPattern ScrollAtAbsoluteSpeed(units::meters_per_second_t velocity, units::meter_t ledSpacing)
Creates a pattern that plays this one scrolling up an LED strip.
static LEDPattern ProgressMaskLayer(std::function< double()> progressFunction)
Creates a pattern that works as a mask layer for LEDPattern::Mask(const LEDPattern&) that illuminates...
LEDPattern Blink(units::second_t onTime)
Like LEDPattern::Blink(units::second_t), but where the "off" time is exactly equal to the "on" time.
static LEDPattern Off()
A pattern that turns off all LEDs.
static LEDPattern Steps(std::initializer_list< std::pair< double, Color > > steps)
Display a set of colors in steps across the length of the LED strip.
LEDPattern OffsetBy(int offset)
Creates a pattern that displays this one, but offset by a certain number of LEDs.
void ApplyTo(LEDReader reader, std::function< void(int, frc::Color)> writer) const
Definition format.h:902
Definition CAN.h:11
Implement std::hash so that hash_code can be used in STL containers.
Definition PointerIntPair.h:280
color
Definition color.h:16