Files
allwpilib/wpimath
Gold856 2102a543d1 Change Java JSON to Avaje Jsonb (#8721)
Jackson is a very heavy library; it supports loads of features that we
don't need, and historically has caused issues due to long class loading
times (a little over 2 seconds to load AprilTagFieldLayout). This often
manifests as a help request in the form of "my robot disables when I do
X, but doesn't disable when doing X in subsequent attempts until code
restart." While SC has brought down Jackson loading times significantly,
with AprilTagFieldLayout loads taking only 330 milliseconds, that's
still a rather long delay, and while libraries should handle any JSON
loading ahead of time to prevent delays in auto/teleop, it would still
be good to make the worst case better to reduce user frustration.
Benchmarks indicate using [Avaje
Jsonb](https://github.com/avaje/avaje-jsonb) to load AprilTagFieldLayout
only takes ~70 ms, a fair chunk of which isn't actually in Avaje Jsonb
(~4 ms is spent on using getResourceAsStream to retrieve the JSON file,
~8 ms is spent on just loading the AprilTag class and its dependencies).

Note that all times listed are end-to-end, meaning nothing else was done
except for the operation being benchmarked, and doing arithmetic on them
can be flawed due to some classes being loaded twice, i.e.,
getResourceAsStream and `new AprilTag()` likely load some of the same
JDK classes and so subtracting both from the Avaje Jsonb load time is
likely slightly incorrect because class loading is being double counted.
For our purposes, it's likely accurate enough and is mostly just for
contextualization.

Benchmarks were run on a Raspberry Pi CM5 with 2 GB of RAM. Source code
for the
[results](https://github.com/user-attachments/files/26471452/benchmark.txt)
can be found in the "Fastjson2" commit
(2456d15ca8ebd17635e607cd40bf8816e77869a1).

Avaje Jsonb uses code generation via annotation processors to generate
the classes needed to do JSON serde and uses service providers to find
them, which will require downstream changes in robot projects, as the
different service providers in each library must be merged together for
Avaje Jsonb to function. We will use the Gradle shadow plugin, as its
already used by the installer and therefore adds zero additional
dependencies.
2026-04-10 23:21:00 -07:00
..
2025-09-08 17:26:22 -07:00

wpimath

wpimath contains utilities for robot control (feedforward/feedback), state estimation (filters, Kalman and otherwise), 2D/3D geometry, kinematics, trajectory generation, and trajectory optimization.

Implementation guidelines

A lot of wpimath features directly implement equations from books or papers. The following guidelines make that code easier to maintain and audit for correctness.

Citations

Cite source books/papers at the top of the function (e.g., See section 5.6 of "book name".). If multiple items from a given work are referenced, write a bibliography entry for the work to reference later.

Cite the equation numbers each line of code implements, if applicable. For example, See equation (#.#) of [1]. where [1] is a bibliography reference number.

Comments

Comment each line of code with its pretty-printed math equivalent.

// xₖ₊₁ = Axₖ + Buₖ
x = A * x + B * u;

Link to explanatory material where appropriate to explain background knowledge and/or notation choice.

Variable naming

Follow established mathematical convention where possible (e.g., use A, B, C, D for state-space notation instead of stateTransitionMatrix).

Use math symbols in variable names (see Unicodeit) to match source papers. This usually entails some Greek letters (α), but diacritics, superscripts, and subscripts need to be spelled out (x_dot, αₖ²α_k_sq) since compilers reject them, and the small features make variable names difficult to read.

Derivations

Put small derivations in comments within the function. Put large derivations in algorithms.md and link to them.

Unicodeit

When writing math expressions in documentation, use https://www.unicodeit.net/ to convert LaTeX to a Unicode equivalent that's easier to read. Not all expressions will translate (e.g., superscripts of superscripts) so focus on making it readable by someone who isn't familiar with LaTeX. If content on multiple lines needs to be aligned in Doxygen/Javadoc comments (e.g., integration/summation limits, matrices packed with square brackets and superscripts for them), put them in @verbatim/@endverbatim blocks in Doxygen or <pre> tags in Javadoc so they render with monospace font.

The LaTeX to Unicode conversions can also be done locally via the unicodeit Python package. To install it, execute:

pip install --user unicodeit

Here's example usage:

$ python -m unicodeit.cli 'x_{k+1} = Ax_k + Bu_k'
xₖ₊₁ = Axₖ + Buₖ

On Linux, this process can be streamlined further by adding the following Bash function to your .bashrc (requires wl-clipboard on Wayland or xclip on X11):

# Converts LaTeX to Unicode, prints the result, and copies it to the clipboard
uc() {
  if [ $WAYLAND_DISPLAY ]; then
    python -m unicodeit.cli $@ | tee >(wl-copy -n)
  else
    python -m unicodeit.cli $@ | tee >(xclip -sel)
  fi
}

Here's example usage:

$ uc 'x_{k+1} = Ax_k + Bu_k'
xₖ₊₁ = Axₖ + Buₖ