Skip to content

Dev#17

Merged
llLeo306 merged 12 commits into
masterfrom
dev
Mar 29, 2026
Merged

Dev#17
llLeo306 merged 12 commits into
masterfrom
dev

Conversation

@llLeo306

@llLeo306 llLeo306 commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Summary by Sourcery

Refine the chassis power control module with Eigen-based math utilities, enhanced power distribution logic, and updated CI to build and test the module via the generic libxr-based Linux workflow.

New Features:

  • Allow passing motor speed tracking error into PowerControl for both 3508 and 6020 motors to drive error-aware power allocation.
  • Expose measured chassis power, capacitor energy, and SuperPower online status via new PowerControl accessors.

Enhancements:

  • Replace custom matrix utilities with Eigen in both the PowerControl implementation and RLS estimator to simplify linear algebra handling.
  • Adjust recursive least squares parameter bounds and initialization for more flexible online identification of motor power model coefficients.
  • Rework power limiting for omni and helm chassis to mix demand-based and error-based power distribution with a reserved power margin.
  • Simplify the current back-calculation helper used to meet a target power in the motor model.

Build:

  • Replace the STM32 container-based BSP build in CI with a libxr/xrobot-driven Linux CMake build that links the module as part of a small test executable and adds required dependency modules (Referee, CMD, SuperPower).

CI:

  • Rework the GitHub Actions workflow to use the docker-image-linux container, initialize an xrobot project layout, add this module and its dependencies, and build it with standard CMake on Linux.

@sourcery-ai

sourcery-ai Bot commented Mar 29, 2026

Copy link
Copy Markdown

Reviewer's Guide

Refactors the PowerControl module and its RLS helper to use Eigen instead of a custom matrix library, introduces error-aware power distribution logic for omni and helm chassis, relaxes/changes some power model parameters and current-solving logic, and replaces the STM32-based CI build with a generic Linux/libxr-based build pipeline.

Sequence diagram for chassis power control loop using PowerControl

sequenceDiagram
    participant ChassisController
    participant PowerControl
    participant SuperPower
    participant RLS as RLS_2

    ChassisController->>PowerControl: SetMotorData3508(currents_3508, speeds_3508, speed_errors_3508)
    ChassisController->>PowerControl: SetMotorData6020(currents_6020, speeds_6020, speed_errors_6020)

    ChassisController->>PowerControl: CalculatePowerControlParam()
    PowerControl->>SuperPower: GetChassisPower()
    SuperPower-->>PowerControl: measured_power
    PowerControl->>SuperPower: IsOnline()
    SuperPower-->>PowerControl: online_flag
    PowerControl->>RLS: Update(samples_3508_, residual)
    RLS-->>PowerControl: params_3508_
    PowerControl->>PowerControl: update k1_3508_, k2_3508_

    ChassisController->>PowerControl: OutputLimit(max_power)
    alt is_helm_ == false
        PowerControl->>PowerControl: OutputLimitOmni(max_power)
    else is_helm_ == true
        PowerControl->>PowerControl: OutputLimitHelm(max_power)
    end

    ChassisController->>PowerControl: GetPowerControlData()
    PowerControl-->>ChassisController: PowerControlData (new currents, is_power_limited)
Loading

Updated class diagram for PowerControl and RLS

classDiagram
    class LibXR_Application {
    }

    class SuperPower {
      +float GetChassisPower()
      +float GetCapEnergy()
      +bool IsOnline()
    }

    class RLS_2 {
      <<template<2>>
      +uint32_t dimension_
      +float lambda_
      +float delta_
      +Eigen_Matrix_float_2_2 transmatrix_
      +ParamVector gainvector_
      +ParamVector paramsvector_
      +ParamVector defaultparamsvector_
      +RLS_2(float delta_, float lambda_)
      +void Reset()
      +const ParamVector& Update(const ParamVector& sample_vector, float actual_output)
      +void SetParamVector(const ParamVector& updated_params)
    }

    class PowerControl {
      +static int MAX_MOTOR_COUNT
      -LibXR_Mutex mutex_
      -SuperPower* superpower_
      -bool is_helm_
      -RLS_2 rls_
      -PowerControlData powercontrol_data_
      -float k3_chassis_
      -float error_confidence_
      -float sum_error_
      -float speed_error_3508_[MAX_MOTOR_COUNT]
      -float speed_error_6020_[MAX_MOTOR_COUNT]
      -int motor_count_3508_
      -int motor_count_6020_
      -float kt_3508_
      -float k1_3508_
      -float k2_3508_
      -Eigen_Matrix_float_2_1 samples_3508_
      -Eigen_Matrix_float_2_1 params_3508_
      -float output_current_3508_[MAX_MOTOR_COUNT]
      -float rotorspeed_rpm_3508_[MAX_MOTOR_COUNT]
      -float motor_power_3508_[MAX_MOTOR_COUNT]
      -float kt_6020_
      -float k1_6020_
      -float k2_6020_
      -float output_current_6020_[MAX_MOTOR_COUNT]
      -float rotorspeed_rpm_6020_[MAX_MOTOR_COUNT]
      -float motor_power_6020_[MAX_MOTOR_COUNT]
      -float measured_power_
      +PowerControl(LibXR_HardwareContainer& hw, LibXR_ApplicationManager& app, SuperPower* superpower, bool is_helm, float chassis_static_power_loss, int motor_count_3508, int motor_count_6020)
      +void SetMotorData3508(float* output_current, float* rotorspeed_rpm, float* speed_error)
      +void SetMotorData6020(float* output_current, float* rotorspeed_rpm, float* speed_error)
      +void CalculatePowerControlParam()
      +void OutputLimit(float max_power)
      +PowerControlData GetPowerControlData()
      +float GetMeasuredPower() const
      +float GetCapEnergy()
      +bool IsOnline()
      +void OnMonitor()
      -void OutputLimitOmni(float max_power)
      -void OutputLimitHelm(float max_power)
    }

    class PowerControlData {
      +float new_output_current_3508[POWER_CONTROL_MAX_MOTOR_COUNT]
      +float new_output_current_6020[POWER_CONTROL_MAX_MOTOR_COUNT]
      +bool is_power_limited
    }

    LibXR_Application <|-- PowerControl
    PowerControl --> SuperPower : uses
    PowerControl --> RLS_2 : uses
    PowerControl --> PowerControlData : aggregates
Loading

File-Level Changes

Change Details Files
Refactor PowerControl to use Eigen, expose additional telemetry helpers, and implement error-weighted power distribution for both omni and helm modes.
  • Replace custom Matrixf usage with Eigen::Matrix for 2x1 parameter and sample vectors and update initialization/indexing syntax.
  • Simplify solve_current_for_power to always compute quadratic roots, change handling of near-zero discriminant, and adjust current selection strategy.
  • Add optional speed_error inputs to SetMotorData3508/6020 and store absolute tracking errors per motor.
  • Modify OutputLimitOmni to reserve extra power margin, accumulate speed error, compute an error-based confidence factor, and mix error-based vs proportional power weights when distributing limited power among motors.
  • Extend OutputLimitHelm to apply similar mixed error/proportional power distribution separately for 3508 and 6020 motor groups, while keeping the existing group-level power budgeting logic.
  • Expose measured power, capacitor energy, and online status via new getters on PowerControl.
  • Retune RLS-updated loss parameters k1_3508_/k2_3508_ with new minimum bounds and adjust residual logic slightly.
  • Replace Matrix module dependency in manifest and includes with Eigen/Core, and add new error distribution threshold macros.
PowerControl.hpp
Port the RLS helper class from a FreeRTOS-specific implementation using a custom matrix library to a header-only Eigen-based implementation.
  • Remove FreeRTOS and custom matrix includes and assertions, making RLS.hpp platform-agnostic.
  • Introduce a ParamVector alias using Eigen::Matrix<float, dim, 1> and use Eigen matrices for internal covariance and gain matrices.
  • Rewrite Reset and Update to use Eigen operations and .transpose()/.operator()(row,col) access, preserving the underlying RLS algorithm.
  • Adjust Update signature to take const ParamVector& and rename parameters to more conventional styles.
  • Keep SetParamVector but update it to operate on Eigen vectors and store the provided parameters as both current and default values.
RLS.hpp
Replace the STM32/bsp-dev-c-based GitHub Actions workflow with a Linux/libxr-based xrobot module integration test build.
  • Change the build container to ghcr.io/xrobot-org/docker-image-linux:main and remove STM32 toolchain-specific environment and CMake configuration.
  • Check out the module under a Modules/ subdirectory, create a minimal main.cpp and CMakeLists.txt that build an xr_test executable using libxr and the module.
  • Clone libxr and check out additional required modules (Referee, CMD, SuperPower) into Modules/ to satisfy dependencies.
  • Install Python-based xrobot tooling, run xrobot_setup/xrobot_init_mod, register standard helper modules and this module via xrobot_add_mod, and regenerate the xrobot main.
  • Configure and build the project with standard CMake/make on Linux while preserving the tag-creation step for successful non-PR builds.
.github/workflows/build.yml
Minor documentation and build script touch-ups for the PowerControl module.
  • Retain and reformat README.md content without functional changes.
  • Keep the module CMakeLists.txt structure intact, with a no-op formatting-only update.
README.md
CMakeLists.txt

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@llLeo306 llLeo306 merged commit d08b04c into master Mar 29, 2026
3 checks passed

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • The new implementation of solve_current_for_power removes the negative-delta/small-a guard but still calls sqrtf(delta) unconditionally and divides by 2*a, which can lead to NaNs or division-by-zero when delta < 0 or k1 ≈ 0; consider restoring/adjusting these checks and setting final_current consistently (the delta < 1e-9 branch currently computes x3 but never uses it).
  • In OutputLimitOmni/OutputLimitHelm, constants like the extra power margin 3.0f and the thresholds ERROR_POWERDISTRIBUTION_SET/POP_POWERDISTRIBUTION are hard-coded; consider making them constexpr configuration parameters or clearly named class members so their intent and tunability are explicit.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The new implementation of `solve_current_for_power` removes the negative-`delta`/small-`a` guard but still calls `sqrtf(delta)` unconditionally and divides by `2*a`, which can lead to NaNs or division-by-zero when `delta < 0` or `k1 ≈ 0`; consider restoring/adjusting these checks and setting `final_current` consistently (the `delta < 1e-9` branch currently computes `x3` but never uses it).
- In `OutputLimitOmni`/`OutputLimitHelm`, constants like the extra power margin `3.0f` and the thresholds `ERROR_POWERDISTRIBUTION_SET`/`POP_POWERDISTRIBUTION` are hard-coded; consider making them `constexpr` configuration parameters or clearly named class members so their intent and tunability are explicit.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants