PX4 controller-parameter changelog (demo)
· b492664 · 1 watched files, +5/−3

Code changes in src/ (1 file).

  • Most activity in src/ (+5/−3).

Full analysis → Summary: automatic analysis

Changed values

None.

Post text

No post: no meaningful change.

Modules touched

ModuleAddedModifiedRemovedLines +Lines −
src010+5−3

Watched files (1)

Show file list

Commit message

fix(mc_nn_control): correct errors and add the first unit tests (#28433)

* fix(mc_nn_control): use single precision sqrt and correct two parameter/comment errors

Three small corrections in the neural network controller, none of which
change the commanded thrust for a valid configuration:

- RescaleActions() called sqrt() rather than sqrtf(), promoting to double
  in a loop that runs once per angular velocity sample. On an FPU without
  double precision that is a software routine, four times per cycle, in
  the path whose execution time the module exists to measure.

- MC_NN_THRST_COEF declared a minimum of 0.0, but the value is used as a
  divisor in RescaleActions(). Zero is therefore an in-range setting that
  makes the motor scaling non-finite. Raise the minimum off zero.

- The comment above PopulateInputTensor() gives the observation order as
  [pos_err(3), lin_vel(3), att(6), ang_vel(3)], but the code below it,
  NeuralControl.msg and the module usage text all use
  [pos_err(3), att(6), lin_vel(3), ang_vel(3)]. Attitude and linear
  velocity are transposed in the comment only.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>

* refactor(mc_nn_control): extract the action rescaling into a testable header

The mapping from network action to motor command lived inside a private
member operating on the TFLM output tensor, so it could not be unit
tested. Move the per element math into a dependency free header
function. Behaviour is unchanged.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>

* fix(mc_nn_control): keep motor commands between idle and full scale

The action to motor command mapping ran past both ends of the motor. On
the shipped defaults action -1 mapped to -0.0077, which the motor output
treats as a stopped motor while the other three keep thrusting, and every
action above 0.61 mapped past full scale. With a minimum rpm above a ninth
of the maximum the last stage also ran backwards for the first few
thousandths of the range. All three come from normalizing the rpm against
limits the thrust coefficient does not reach. Reported in #28417.

Bound the normalized rpm between the limits, so a thrust below what the
minimum rpm gives idles the motor and one above the maximum runs it at
full scale, and write the thrust curve compensation as a x^2 + (1 - a) x
so idle is exactly 0 and full scale exactly 1. The curve inside the
limits is unchanged.

Validate the three parameters at start and on every parameter update:
finite, the coefficient above zero, the minimum at least zero and below
the maximum, and a part of the action range wider than float resolution
reaching the motor, so rounding cannot pass a window with no action
inside it. Raw parameter writes are not bounded by the metadata, so this
is checked in code. The mapping only ever uses a set that passed. An invalid set is
reported as an error event, repeated while it stands, and the arming
check for the mode is refused until it is corrected, so the commander
neither arms into the mode nor keeps flying it. The mapping keeps the
last valid set meanwhile, so the write itself never steps the motors. A
valid set that covers less than the whole action range is reported as a
warning naming what it does cover, when it changes and again when the
mode is entered.

The arming check reply was not zero initialized, which left two mode
requirement fields to whatever was on the stack. Also from #28417: the
loop performance counter was left open on the two early returns after
inference, and actuator_motors.timestamp_sample was never set.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>

* test(mc_nn_control): add the module's first unit tests

The action to motor command mapping had no tests. These assert the
properties it has to keep rather than any particular output value:
actions beyond the boundary clamp, every command stays between 0 and 1,
the lowest action idles the motor and the highest runs it at full scale,
the mapping never decreases and rises inside the achievable range,
actions outside that range sit on the bounds, the output stays finite
for every normal action and across the documented parameter ranges, a
non finite action gives no command, and invalid limits are rejected.

Every threshold comes from the mapping's own achievable range, and each
property is checked for the shipped defaults, a smaller motor, and a
motor whose limits cover the whole action range, so a change to the
defaults only fails them when a property is broken.

Assisted-by: Claude:claude-fable-5
Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>

* ci(tests): run the mc_nn_control unit tests in the neural configuration

make tests builds px4_sitl_test, which does not enable MC_NN_CONTROL, so
the unit tests the module registers were never built or run upstream. The
only configuration that enables the module is px4_sitl_neural.

Add a tests_neural target that builds that configuration with testing on
and runs the module's tests, the same shape as tests_daa_crosstrack and
tests_vtest_moving, and run it from the Unit Tests job.

Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>

---------

Signed-off-by: Saibernard Yogendran <bernie97@seas.upenn.edu>