Skip to content

controls algo setup - #1936

Open
Lucien950 wants to merge 35 commits into
masterfrom
Shayan/algo_set_up
Open

controls algo setup#1936
Lucien950 wants to merge 35 commits into
masterfrom
Shayan/algo_set_up

Conversation

@Lucien950

Copy link
Copy Markdown
Contributor

Changelist

Testing Done

Resolved Tickets

@Lucien950 Lucien950 added the Vehicle Controls Torque Vectoring, Regen, Brake/Drive Diffs label Mar 29, 2026
@Lucien950 Lucien950 changed the title controls algo algo setup Mar 29, 2026
@Lucien950 Lucien950 changed the title algo setup controls algo setup Mar 29, 2026

@Lucien950 Lucien950 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@shayana18

  • imma trust you on the equations
  • i don't really agree with internal state abuse bceause I think it makes the code very hard to follow, i would prefer to see that the functions are all pure

Comment thread firmware/hexray/VC/src/app/torque_vectoring/torque_vectoring.cpp
Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/tire_model.cpp Outdated
Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/tire_model.cpp Outdated
void TireModel::estimateSlipRatio(const float wheel_angular_velocity_radps)
{
const float wheel_surface_speed_mps = wheel_angular_velocity_radps * WHEEL_RADIUS_M;
const float effective_wheel_speed_mps = std::cos(tire_outputs_.slip_angle_rad) * wheel_vel_x_mps_;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i imagine this is also a function of wheelSteeringAngleRad?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

slip angle is a function of wheel steering angle, it is not directly a function of wheel angle

Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/tire_model.cpp Outdated
Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/tire_model.cpp Outdated
Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/tire_model.cpp Outdated
[[nodiscard]] float estimateDrag_N(float v_x_mps) const;

private:
static constexpr float FRONTAL_AREA_M2 = 0.94f; // m^2 from aero team

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should just put all these constants into constants.hpp

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fr

@Lucien950 Lucien950 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

just a first pass, I think there are some high level structural understandability issues with the code we should address before correctness

static constexpr float W_FX = 2.0f / 3.0f; // Weight on per-wheel force tracking error
static constexpr float W_MZ = 1.0f / 3.0f; // Weight on yaw moment tracking error
static constexpr int MAX_ITER = 8; // Gauss-Newton iterations per control cycle
static constexpr float SLIP_CLAMP = 0.3f; // Physical slip ratio bounds

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

is it expensive to calculate high slip?

Comment on lines +24 to +27
static constexpr int FL = 0;
static constexpr int FR = 1;
static constexpr int RL = 2;
static constexpr int RR = 3;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

use unsigned integers

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

also i prefer the wheel_set datastructure over this

@@ -0,0 +1,22 @@
#pragma once

namespace app::tv::datatypes::datatypes

@Lucien950 Lucien950 Apr 5, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

why two namespace qualifiers?

Comment on lines +37 to +51
[[nodiscard]] estimation::TireModel::StateInputs buildStateInputs(
const datatypes::datatypes::VehicleState& vs,
const float normal_load_N,
const float wheel_angular_velocity_radps)
{
return {
.wheel_angular_velocity_radps = wheel_angular_velocity_radps,
.vehicle_velocity_x_mps = vs.v_x_mps,
.vehicle_velocity_y_mps = vs.v_y_mps,
.yaw_rate_radps = vs.yaw_rate_radps,
.steering_angle_rad = vs.steer_ang_rad,
.normal_load_N = normal_load_N,
};
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

you can just make a constructor for this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

also this is a very trivial constructor


// ---- Construction ----

TorqueAllocator::TorqueAllocator(estimation::TireModel::TirePressure pressure)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

put this in the header please (optimization point)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

bomba

Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/dynamics_estimation.cpp Outdated
Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/dynamics_estimation.cpp Outdated
return std::atan2(v_y_mps, safeLongitudinalVelocity(v_x_mps));
}

float vehicleDynamics::estimateYawMoment_Nm(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

i think this is a better yaw moment estimator than in the ta? why not use this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

oh yes I was thinking that but I didn't know how ur C++ generation was going to work so I left it here for now to make it easier

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

but yes I agree for our code it should go there

Comment on lines +28 to +29
const app::tv::datatypes::datatypes::wheel_set& longitudinal_forces_N,
const app::tv::datatypes::datatypes::wheel_set& lateral_forces_N,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

also you can just go F_y_N and F_x_N

@Lucien950 Lucien950 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

more

@@ -34,8 +34,7 @@ namespace app::tv::controllers::dyrc
*
* @return The corrective yaw moment in Nm to apply on the vehicle
*/
[[nodiscard]] inline float
computeYawMoment(const float r_actual_rad, const float steer_ang_rad, const float body_velx_mps);
[[nodiscard]] float computeYawMoment(const float r_actual_rad, const float steer_ang_rad, const float body_velx_mps);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

lowkey can we calculate yawacceleration

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

??

}

datatypes::datatypes::wheel_set TorqueAllocator::optimize(
const datatypes::datatypes::wheel_set& des_f_x,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

your resired F_x is one number, and it represents the desired body F_x

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

please do not specify individual wheel f_x references

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

because you actually don't know how to effectively allocate, that is the whole point of the optimizer

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hmm, yeah it might be redundant rn because I optimize on Mz err but also Fx error with Mz taken into account. Note I also realized no constraint is placed on the sum of forces adding on the user quested force * 4. That is important I BELIEVE

Comment on lines +124 to +143
// Desired per-wheel longitudinal force from pedal request, projected along tire heading
const float per_wheel_tq = MAX_TORQUE_REQUEST_NM * pedal_percentage;
wheel_set des_f_x = {
.fl = per_wheel_tq * std::cos(acc_slip_angle.fl) * WHEEL_RADIUS_M ,
.fr = per_wheel_tq * std::cos(acc_slip_angle.fr) * WHEEL_RADIUS_M,
.rl = per_wheel_tq * std::cos(acc_slip_angle.rl) * WHEEL_RADIUS_M,
.rr = per_wheel_tq * std::cos(acc_slip_angle.rr) * WHEEL_RADIUS_M,
};

// Direct yaw rate control: corrective yaw moment
const float des_yaw_moment_nm = controllers::dyrc::computeYawMoment(
estimated_state.yaw_rate_radps, estimated_state.steer_ang_rad, estimated_state.v_x_mps);

// Distribute yaw moment into per-wheel force adjustment
// From Mz = (t/2) * (Fx_right - Fx_left), solve for delta Fx per side:
const float des_fx_delta = des_yaw_moment_nm / TRACK_WIDTH_m;
des_f_x.fl -= des_fx_delta;
des_f_x.fr += des_fx_delta;
des_f_x.rl -= des_fx_delta;
des_f_x.rr += des_fx_delta;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

must change as due to optimizer interface comment

Comment on lines +72 to +86
void unpackTireOutputs(
const estimation::TireModel::Outputs& fl,
const estimation::TireModel::Outputs& fr,
const estimation::TireModel::Outputs& rl,
const estimation::TireModel::Outputs& rr)
{
acc_f_x = { .fl = fl.longitudinal_force_N, .fr = fr.longitudinal_force_N,
.rl = rl.longitudinal_force_N, .rr = rr.longitudinal_force_N };
acc_f_y = { .fl = fl.lateral_force_N, .fr = fr.lateral_force_N,
.rl = rl.lateral_force_N, .rr = rr.lateral_force_N };
acc_slip_ratio = { .fl = fl.slip_ratio, .fr = fr.slip_ratio,
.rl = rl.slip_ratio, .rr = rr.slip_ratio };
acc_slip_angle = { .fl = fl.slip_angle_rad, .fr = fr.slip_angle_rad,
.rl = rl.slip_angle_rad, .rr = rr.slip_angle_rad };
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

can you unpack them purely

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

it makes it easier to keep track of data dependencies

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

uhhhhhh sure

Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/dynamics_estimation.hpp Outdated
Comment on lines +93 to +94
const float fl_omega, const float fr_omega,
const float rl_omega, const float rr_omega)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

just pass the omegas in a wheels struct

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@Lucien950 Our particular H7 has really shit SIMD, the width is like 32 bits so we can only perform it with 16 bit or 8 bit values. Our main performance benefit would come from the CORDIC because you can do trig, trig inverse, and square root functions with vectors as well, but we dont have the SIMD capabilities to do add, sub, multiply with 32bit float vectors. In other versions of the H7 there is Helium SIMD which has a 128 bit width so we can conveniently do SIMD for that

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

but also it may be still beneficial to vectorize this so we can easily port it to SIMD in the future

* @return Per-wheel optimal slip ratios
*/
[[nodiscard]] datatypes::datatypes::wheel_set optimize(
const datatypes::datatypes::wheel_set& des_f_x,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: can you hit a using datatypes = datatypes::datatypes for anywhere where this is used it just makes it a bit easier to read

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

its been changed to shared_datatypes.

Comment thread firmware/hexray/VC/src/app/torque_vectoring/estimation/tire_model.cpp Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

also arent I doing this i have an MR up for body velocity estimation and i can add yaw moment + yaw rate in the state as well

@shayana18
shayana18 force-pushed the Shayan/algo_set_up branch from c6d491a to 880059a Compare April 8, 2026 21:43
@Lucien950

Copy link
Copy Markdown
Contributor Author

force push :(((((((

@Aditya-Dhiman4 Aditya-Dhiman4 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

pretty sick mostly small things

Comment thread firmware/hexray/VC/src/app/torque_vectoring/shared_datatypes/datatypes.hpp Outdated
Comment thread firmware/hexray/VC/src/app/torque_vectoring/shared_datatypes/datatypes.hpp Outdated
Comment thread firmware/hexray/VC/src/app/torque_vectoring/shared_datatypes/datatypes.hpp Outdated
Comment on lines +241 to +260
/**
* Yaw moment distribution factor Kmz (page 57)
* Accounts for load transfer effect on yaw moment generation capacity
* @return Effective moment arm (m)
*/
[[nodiscard]] constexpr float ACCELERATION_TERM_KMZ() const
{
return vd_constants::DIST_FRONT_AXLE_CG_m + (a_x_mps2 * vd_constants::DIST_HEIGHT_CG_m) / vd_constants::GRAVITY;
}
[[nodiscard]] constexpr float KMZ() const
{
const float LONG_ACCEL_TERM = ACCELERATION_TERM_KMZ();
return ((vd_constants::CAR_WEIGHT - (vd_constants::CAR_WEIGHT / vd_constants::WHEELBASE_m) * LONG_ACCEL_TERM)) /
((vd_constants::CAR_WEIGHT / vd_constants::WHEELBASE_m) * LONG_ACCEL_TERM);
}
/**
* Moment scaling factor F (page 58)
* Relates torque differential to yaw moment through track width and effective radius
*/
static constexpr float F = (vd_constants::TRACK_WIDTH_m / ((WHEEL_DIAMETER_IN / 2.0f) * IN_TO_M)) * GEAR_RATIO;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These were required for the Quintuna algo not Hexray, we should probably add a comment for future reference to prevent confusion

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

actually I'm confused as to why this is required at all, i'm not so sure about what these terms are

@Lucien950 Lucien950 Apr 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

shayan gave these to me

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ic we can remove if u want or keep for legacy/fallback

constexpr std::size_t AY = 1;

constexpr float ESTIMATOR_DT_S = 0.01f; // Matches the 100 Hz control task.
constexpr float ESTIMATOR_YAW_INERTIA = 110.0f; // TODO: Replace with measured Hexray yaw inertia.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Should we put this into constants.hpp?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

idk I didn't write this this all u

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

dawg i did not write this i have a separate PR for this

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

ok well use that then

Comment thread firmware/hexray/VC/src/app/torque_vectoring/controllers/torque_allocator.cpp Outdated
Comment thread firmware/hexray/VC/src/app/torque_vectoring/controllers/torque_allocator.cpp Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is kinda hard to read lowkey grouping the functions properly would help

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

:)

@Lucien950
Lucien950 marked this pull request as ready for review April 10, 2026 20:29
} };
// bring it in
const auto [k_kappas, k_torque_max, k_torque_min] = update(state);
// std::cout << "DIH" << std::endl;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

DIH

Aditya-Dhiman4 and others added 4 commits April 20, 2026 11:28
### Changelist 
<!-- Give a list of the changes covered in this PR. This will help both
you and the reviewer keep this PR within scope. -->

### Testing Done
<!-- Outline the testing that was done to demonstrate the changes are
solid. This could be unit tests, integration tests, testing on the car,
etc. Include relevant code snippets, screenshots, etc as needed. -->

### Resolved Tickets
<!-- Link any tickets that this PR resolves. -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Vehicle Controls Torque Vectoring, Regen, Brake/Drive Diffs

Development

Successfully merging this pull request may close these issues.

3 participants