|
LightLib
PROS library for VEX V5: EKF/MCL localization, RAMSETE path following, high-level chassis API
|
This tutorial covers the on-brain UI — the LVGL screen that lets you pick an auton, watch live odom, and tweak PID gains without rebuilding. You won't touch its internals often; what matters is knowing what each panel shows and how the selector you populate in auton_config.cpp ends up on the screen.
The light::AutonSelector singleton is the default LightLib brain screen. It's built once during initialize() and stays alive for the entire match. It has three jobs:
light::auton_selector.add(...) becomes a button on the left side of the screen.x, y, and theta updating in real time — useful for sanity-checking pose resets and tracking drift before a match.A fourth view — the run screen — takes over the whole display while the selected auton runs, then drops back to the picker when it finishes.
add(...).x, y, theta readout, refreshed by an LVGL timer.Every brain-screen button comes from one add(...) call in src/auton_config.cpp:
Three arguments:
void() function. Must be declared in autons.hpp first (or be a lambda).There's a four-arg overload that takes an lv_img_dsc_t* banner image — the picker scrolls it inside the button. Use it sparingly; images live in flash and bloat your build.
Buttons appear in registration order. The first add(...) call ends up selected by default on boot. Put your most likely competition auton first — if you forget to pick before the match starts, that's what runs.
Each add() is one button on the screen, and the selector cycles by tap, not by some safety mechanism. If you leave Tune: Drive registered and accidentally tap it before a match, your robot ramps full forward at the wall. Wrap tuning entries in #ifdef TUNING or just comment them out before the event:
The PID tab reads the current gains from the chassis at boot (so whatever default_constants() set is what you see), then lets you nudge each value with the +/- buttons. Pressing Apply writes the displayed values back into the chassis via the same pid_*_constants_set() calls you'd use in code.
This is the fastest way to tune by hand:
drive_test(48)).When you've found values you like, transcribe them into default_constants() in src/autons.cpp. The panel is a scratchpad — its values reset on the next reboot.
The auto-tune routines (
Tune: Drive, etc.) write their results straight into the live chassis the same way the panel does — same caveat: copy them intodefault_constants()to make them permanent.
x, y, theta come straight from chassis.odom_x_get() and friends, sampled by an LVGL timer (~100 ms). Two things to check before a match:
x and y stay at zero while you shove it across the field, your tracking wheels are dead or miswired.The display caches its own last-rendered text and skips lv_label_set_text when nothing changed — so if a value is visibly frozen, the underlying number is genuinely not moving (it's not a UI glitch).
When light::auton_selector.run() is called from autonomous(), the UI swaps to a full-screen view that:
You don't configure this screen; it inherits whatever description and banner you passed to add(...). The toggle button on the run screen flips between the image view and the live odom view, mid-match — handy if you want to see where the robot thinks it is while it's driving.
The full UI lifecycle, end to end:
So the only file you touch for UI config is src/auton_config.cpp. Everything else is plumbing that's already correct.
autons.hpp and wrote it in autons.cpp, but forgot to add(...) it in auton_config.cpp. The selector is opt-in.default_constants().register_autons() was never called, or the function body is empty. Confirm initialize() calls it.lv_img_dsc_t arrays are unforgiving — wrong size or stride will hard-fault LVGL. Generate them with the LVGL image converter; don't hand-author.