Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement the Simple Vehicle Dynamics Interface in C++ #330

Open
wants to merge 18 commits into
base: main
Choose a base branch
from

Conversation

Tegh25
Copy link
Member

@Tegh25 Tegh25 commented Nov 24, 2024

Resolves #329.

@Tegh25 Tegh25 self-assigned this Nov 24, 2024
Copy link
Contributor

@BlakeFreer BlakeFreer left a comment

Choose a reason for hiding this comment

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

looking good so far

firmware/projects/FrontController/inc/simp_vd_interface.h Outdated Show resolved Hide resolved
firmware/projects/FrontController/inc/simp_vd_interface.h Outdated Show resolved Hide resolved
@Tegh25 Tegh25 marked this pull request as ready for review December 30, 2024 02:25
@Tegh25 Tegh25 requested a review from BlakeFreer December 30, 2024 02:25
@Tegh25
Copy link
Member Author

Tegh25 commented Dec 30, 2024

Please run the test cases within simp_vd_interface_test.cc and let me know what it results.

When I try make simp_vd_interface_test, I get the below output. Not sure why it's finding so many errors within the firmware/shared directory.

Output

In file included from C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/linear_map.h:6,
                 from app.h:17,
                 from simp_vd_interface.h:6,
                 from simp_vd_interface_test.cc:4:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/mapper.h:17:13: error: expected constructor, destructor, or type conversion before '(' token
   17 |     requires(std::is_arithmetic_v<T>)
      |             ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/mapper.h:30:35: error: expected template-name before '<' token
   30 | class CompositeMap : public Mapper<Tf, U> {
      |                                   ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/mapper.h:30:35: error: expected '{' before '<' token
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/linear_map.h:16:32: error: expected template-name before '<' token
   16 | class LinearMap : public Mapper<T, U> {
      |                                ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/linear_map.h:16:32: error: expected '{' before '<' token
In file included from C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/moving_average.h:9,
                 from app.h:19:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/data_structures/circular_queue.h:12:13: error: expected constructor, destructor, or type conversion before '(' token
   12 |     requires(length > 0)
      |             ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/moving_average.h:14:13: error: expected constructor, destructor, or type conversion before '(' token
   14 |     requires(std::is_arithmetic_v<T>) && (length > 0) class MovingAverage {
      |             ^
app.h:27:17: error: 'shared::util::Mapper' has not been declared
   27 |                 shared::util::Mapper<double, uint16_t>* adc_to_position)
      |                 ^~~~~~
app.h:27:37: error: expected ',' or '...' before '<' token
   27 |                 shared::util::Mapper<double, uint16_t>* adc_to_position)
      |                                     ^
app.h:45:19: error: 'MovingAverage' in namespace 'shared::util' does not name a template type
   45 |     shared::util::MovingAverage<uint16_t, kMovingAverageLength> moving_average_;
      |                   ^~~~~~~~~~~~~
app.h:46:25: error: 'Mapper' in namespace 'shared::util' does not name a template type
   46 |     const shared::util::Mapper<double, uint16_t>* adc_to_position_;
      |                         ^~~~~~
app.h: In constructor 'AnalogInput::AnalogInput(shared::periph::ADCInput&, int)':
app.h:28:22: error: class 'AnalogInput' does not have any field named 'adc_to_position_'
   28 |         : adc_(adc), adc_to_position_(adc_to_position) {}
      |                      ^~~~~~~~~~~~~~~~
app.h:28:39: error: 'adc_to_position' was not declared in this scope
   28 |         : adc_(adc), adc_to_position_(adc_to_position) {}
      |                                       ^~~~~~~~~~~~~~~
app.h: In member function 'double AnalogInput::Update()':
app.h:32:9: error: 'moving_average_' was not declared in this scope
   32 |         moving_average_.LoadValue(uint16_t(position));
      |         ^~~~~~~~~~~~~~~
app.h: In member function 'double AnalogInput::GetPosition()':
app.h:40:16: error: 'adc_to_position_' was not declared in this scope
   40 |         return adc_to_position_->Evaluate(moving_average_.GetValue());
      |                ^~~~~~~~~~~~~~~~
app.h:40:43: error: 'moving_average_' was not declared in this scope
   40 |         return adc_to_position_->Evaluate(moving_average_.GetValue());
      |                                           ^~~~~~~~~~~~~~~
In file included from simp_vd_interface.h:7:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h: In function 'std::tuple<T, T> ctrl::CalculateMotorTorque(T, T, T, bool)':   
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:17:26: error: 'MovingAverage' in namespace 'shared::util' does not name a template type
   17 |     static shared::util::MovingAverage<T, 10> running_average;
      |                          ^~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:20:9: error: 'running_average' was not declared in this scope
   20 |         running_average = shared::util::MovingAverage<T, 10>();
      |         ^~~~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:20:41: error: 'MovingAverage' is not a member of 'shared::util'
   20 |         running_average = shared::util::MovingAverage<T, 10>();
      |                                         ^~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:20:56: error: expected primary-expression before ',' token
   20 |         running_average = shared::util::MovingAverage<T, 10>();
      |                                                        ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:20:62: error: expected primary-expression before ')' token
   20 |         running_average = shared::util::MovingAverage<T, 10>();
      |                                                              ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:23:5: error: 'running_average' was not declared in this scope
   23 |     running_average.LoadValue(new_torque_value);
      |     ^~~~~~~~~~~~~~~
In file included from C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/tvFactor.h:4,
                 from simp_vd_interface.h:9:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/lookup_table.h: At global scope:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/lookup_table.h:25:34: error: expected template-name before '<' token
   25 | class LookupTable : public Mapper<float> {
      |                                  ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/lookup_table.h:25:34: error: expected '{' before '<' token
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/tvFactor.h: In function 'T ctrl::CreateTorqueVectoringFactor(T)':
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/tvFactor.h:20:52: error: 'tv_lookup_table' has incomplete type
   20 |     static shared::util::LookupTable<table_length> tv_lookup_table{table_data};
      |                                                    ^~~~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/lookup_table.h:25:7: note: declaration of 'class shared::util::LookupTable<6>'
   25 | class LookupTable : public Mapper<float> {
      |       ^~~~~~~~~~~
In file included from C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/linear_map.h:6,
                 from app.h:17,
                 from simp_vd_interface.h:6,
                 from simp_vd_interface.cc:4:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/mapper.h:17:13: error: expected constructor, destructor, or type conversion before '(' token
   17 |     requires(std::is_arithmetic_v<T>)
      |             ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/mapper.h:30:35: error: expected template-name before '<' token
   30 | class CompositeMap : public Mapper<Tf, U> {
      |                                   ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/mapper.h:30:35: error: expected '{' before '<' token
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/linear_map.h:16:32: error: expected template-name before '<' token
   16 | class LinearMap : public Mapper<T, U> {
      |                                ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/linear_map.h:16:32: error: expected '{' before '<' token
In file included from C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/moving_average.h:9,
                 from app.h:19:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/data_structures/circular_queue.h:12:13: error: expected constructor, destructor, or type conversion before '(' token
   12 |     requires(length > 0)
      |             ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/moving_average.h:14:13: error: expected constructor, destructor, or type conversion before '(' token
   14 |     requires(std::is_arithmetic_v<T>) && (length > 0) class MovingAverage {
      |             ^
app.h:27:17: error: 'shared::util::Mapper' has not been declared
   27 |                 shared::util::Mapper<double, uint16_t>* adc_to_position)
      |                 ^~~~~~
app.h:27:37: error: expected ',' or '...' before '<' token
   27 |                 shared::util::Mapper<double, uint16_t>* adc_to_position)
      |                                     ^
app.h:45:19: error: 'MovingAverage' in namespace 'shared::util' does not name a template type
   45 |     shared::util::MovingAverage<uint16_t, kMovingAverageLength> moving_average_;
      |                   ^~~~~~~~~~~~~
app.h:46:25: error: 'Mapper' in namespace 'shared::util' does not name a template type
   46 |     const shared::util::Mapper<double, uint16_t>* adc_to_position_;
      |                         ^~~~~~
app.h: In constructor 'AnalogInput::AnalogInput(shared::periph::ADCInput&, int)':
app.h:28:22: error: class 'AnalogInput' does not have any field named 'adc_to_position_'
   28 |         : adc_(adc), adc_to_position_(adc_to_position) {}
      |                      ^~~~~~~~~~~~~~~~
app.h:28:39: error: 'adc_to_position' was not declared in this scope
   28 |         : adc_(adc), adc_to_position_(adc_to_position) {}
      |                                       ^~~~~~~~~~~~~~~
app.h: In member function 'double AnalogInput::Update()':
app.h:32:9: error: 'moving_average_' was not declared in this scope
   32 |         moving_average_.LoadValue(uint16_t(position));
      |         ^~~~~~~~~~~~~~~
app.h: In member function 'double AnalogInput::GetPosition()':
app.h:40:16: error: 'adc_to_position_' was not declared in this scope
   40 |         return adc_to_position_->Evaluate(moving_average_.GetValue());
      |                ^~~~~~~~~~~~~~~~
app.h:40:43: error: 'moving_average_' was not declared in this scope
   40 |         return adc_to_position_->Evaluate(moving_average_.GetValue());
      |                                           ^~~~~~~~~~~~~~~
In file included from simp_vd_interface.h:7:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h: In function 'std::tuple<T, T> ctrl::CalculateMotorTorque(T, T, T, bool)':   
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:17:26: error: 'MovingAverage' in namespace 'shared::util' does not name a template type
   17 |     static shared::util::MovingAverage<T, 10> running_average;
      |                          ^~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:20:9: error: 'running_average' was not declared in this scope
   20 |         running_average = shared::util::MovingAverage<T, 10>();
      |         ^~~~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:20:41: error: 'MovingAverage' is not a member of 'shared::util'
   20 |         running_average = shared::util::MovingAverage<T, 10>();
      |                                         ^~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:20:56: error: expected primary-expression before ',' token
   20 |         running_average = shared::util::MovingAverage<T, 10>();
      |                                                        ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:20:62: error: expected primary-expression before ')' token
   20 |         running_average = shared::util::MovingAverage<T, 10>();
      |                                                              ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/motor_torque.h:23:5: error: 'running_average' was not declared in this scope
   23 |     running_average.LoadValue(new_torque_value);
      |     ^~~~~~~~~~~~~~~
In file included from C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/tvFactor.h:4,
                 from simp_vd_interface.h:9:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/lookup_table.h: At global scope:
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/lookup_table.h:25:34: error: expected template-name before '<' token
   25 | class LookupTable : public Mapper<float> {
      |                                  ^
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/lookup_table.h:25:34: error: expected '{' before '<' token
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/tvFactor.h: In function 'T ctrl::CreateTorqueVectoringFactor(T)':
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/tvFactor.h:20:52: error: 'tv_lookup_table' has incomplete type
   20 |     static shared::util::LookupTable<table_length> tv_lookup_table{table_data};
      |                                                    ^~~~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/util/mappers/lookup_table.h:25:7: note: declaration of 'class shared::util::LookupTable<6>'
   25 | class LookupTable : public Mapper<float> {
      |       ^~~~~~~~~~~
simp_vd_interface.cc: In member function 'VdOutput SimpVdInterface::update(const VdInput&, int)':
simp_vd_interface.cc:39:62: error: variable 'const shared::util::LookupTable<2> pedal_to_torque' has initializer but incomplete type
   39 |     const shared::util::LookupTable<pedal_torque_lut_length> pedal_to_torque{pedal_torque_lut_data};
      |                                                              ^~~~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/tvFactor.h: In instantiation of 'T ctrl::CreateTorqueVectoringFactor(T) [with T = float]':  
simp_vd_interface.cc:36:52:   required from here
   36 |         steering_angle, CreateTorqueVectoringFactor(steering_angle));
      |                         ~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~
C:/Users/teghv/Documents/School/MAC-FE/racecar/firmware/shared/controls/tvFactor.h:20:52: error: 'shared::util::LookupTable<6> tv_lookup_table' has incomplete type 
   20 |     static shared::util::LookupTable<table_length> tv_lookup_table{table_data};
      |                                                    ^~~~~~~~~~~~~~~
make: *** [makefile:2: simp_vd_interface_test] Error 1

@BlakeFreer
Copy link
Contributor

BlakeFreer commented Jan 4, 2025

Please run the test cases within simp_vd_interface_test.cc and let me know what it results.

When I try make simp_vd_interface_test, I get the below output. Not sure why it's finding so many errors within the firmware/shared directory.

Sorry for the delay. What makefile are you running? There isn't one in your branch

You should consider doing what Luai did by making a separate project for your block. Then you can compile it with the regular build system make PROJECT=VD_Interface PLATFORM=cli. See his recent AMK PR

@Tegh25 Tegh25 closed this Jan 4, 2025
@Tegh25 Tegh25 reopened this Jan 4, 2025
@Tegh25
Copy link
Member Author

Tegh25 commented Jan 4, 2025

What makefile are you running? There isn't one in your branch

I noticed that there was no makefile specifically for front controller, I was simply referencing this readme and assumed it was general practice for running tests.

I created a separate project for testing and was able to build for the cli platform. Executing ./main.exe in the build directory results in a segmentation fault, gdb traces this to line 35 of simp_vd_interface_test.
I'll continue to work on this, feel free to take a look if you have the chance.

Closing the pr was a misclick.

@BlakeFreer
Copy link
Contributor

BlakeFreer commented Jan 6, 2025

I created a separate project for testing and was able to build for the cli platform. Executing ./main.exe in the build directory results in a segmentation fault, gdb traces this to line 35 of simp_vd_interface_test. I'll continue to work on this, feel free to take a look if you have the chance.

I don't get a Segfault. The program runs fine but fails an assertion.

when comparing floating point values, you can't rely on pure equality since there may be some rounding errors. Instead, you should assert that the absolute difference is small. Something like

void assert_close(float a, float b) {
    const float tolerance = 0.001f;
    assert(std::abs(a - b) < tolerance);
}

then use that instead of assert(a == b). I don't think this is causing your assertion to fail, but you should be using it regardless

EDIT: I wrote a ASSERT_CLOSE macro in shared/controls/testing. You should include that file and use it.

Tegh25 and others added 4 commits January 6, 2025 15:52
Remove unused `app.h` file. Update CMake structure since build system changed since this branch started. Rename some files from `.h` to `.hpp`
@BlakeFreer BlakeFreer force-pushed the user/atelieyt/vd-interface branch from 06bfb49 to b5e83cc Compare January 6, 2025 22:18
@BlakeFreer
Copy link
Contributor

BlakeFreer commented Jan 6, 2025

You correctly implemented the Simulink TC (Traction control) block, but that block was poorly designed in simulink.

image

The purpose of the block is to temporarily disable torque output (by multiplying by tc_scale_factor=0) if we start slipping. The TC_off->TC_on2 transition should occur when actual_slip > target_slip holds true for 50 continuous milliseconds, but as implemented, the transition will occur if the inequality is satisfied even momentarily after 50ms have passed since entering TC_off. This is incorrect.

After slipping is detected, we start the TC_on2 -> TC_on1 -> TC_on chain which slowly ramps back to full traction (scale_factor=1) over a period of 100 ms. There is no reason for this ramp to be broken into 33ms steps. It should be a smooth ramp.

I rewrote the CalculateTCScaleFactor function in this commit. There are two notable features:

  1. The HoldCondition class tracks a boolean condition over time. It remembers how long actual_slip has been above target_slip so that we can perform the proper transition.
  2. There is no state machine. This system is more event-based: we continually ramp up scale_factor over time until it reaches 1, but if we detect that the wheel has been slipping for >50 ms, we restart at 0.

I added some test cases in shared/controls/tc_scale_factor_test.cc to demonstrate this behaviour over time.


IMPORTANT Currently, the scale_factor starts at 0, so even without slipping, 100 ms must pass before the scale reaches 1.0 for the first time. It will affect your test cases since time_ms=0 will always output scale=0 even if actual_slip < target_slip. Should we change this?

@BlakeFreer
Copy link
Contributor

I also updated the project structure and rebased the commits onto main. There's been a lot of change since the branch was created.

@Tegh25
Copy link
Member Author

Tegh25 commented Jan 7, 2025

I like this implementation of the TC factor calculation better.
For the starting value of scale_factor, I believe it should always start at full torque (1.0). Even though it might not impact the car in a practical setting, it's much more intuitive to imagine that the wheels are not slipping immediately when started. Especially since we don't have any specific guides or documentation for these controls, it's an unexpected behavior that might impact future devs.
Could probably be fixed by subtracting the ramp up time (100 ms) from time_ms when statically defining reset_time.

@BlakeFreer
Copy link
Contributor

Could probably be fixed by subtracting the ramp up time (100 ms) from time_ms when statically defining reset_time.

Great point, can you implement this and leave a short comment?

@Tegh25
Copy link
Member Author

Tegh25 commented Jan 13, 2025

In the test cases for controls/tvFactor.h, some of the tests expect a left/right tv factor greater than 1. However, looking at the code it seems like it can only return values in the range of [0.683, 1]. Are these test cases updated?

Also, I noticed that since the running average calculation is done within the CalculateMotorTorque function in controls/motor_torque.h, the average is maintained throughout different instances of SimpVdInterface. You can see how the running average propagates through the expected outputs in each test case, even though they each create SimpVdInterface separately.
Should the running average calculation be moved to the SimpVdInterface class? This makes sense to me since I would expect the running average to be reset when creating a new SimpVdInterface object.

@Tegh25 Tegh25 requested a review from BlakeFreer January 13, 2025 21:10
@BlakeFreer
Copy link
Contributor

Also, I noticed that since the running average calculation is done within the CalculateMotorTorque function in controls/motor_torque.h, the average is maintained throughout different instances of SimpVdInterface. You can see how the running average propagates through the expected outputs in each test case, even though they each create SimpVdInterface separately. Should the running average calculation be moved to the SimpVdInterface class? This makes sense to me since I would expect the running average to be reset when creating a new SimpVdInterface object.

We were more focused on algorithm than code design when writing the controls functions. I think that you should move the running avg to the class so that each object instance has its own

Copy link
Contributor

Choose a reason for hiding this comment

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

These tests no longer pass.

run

make tvFactor_test from inside shared/controls

Copy link
Contributor

Choose a reason for hiding this comment

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

In the test cases for controls/tvFactor.h, some of the tests expect a left/right tv factor greater than 1. However, looking at the code it seems like it can only return values in the range of [0.683, 1]. Are these test cases updated?

Just noticed your comment. You're correct, TV values should never be > 1. Not sure how these tests got merged. can you look at the Simulink model ,figure out the correct behaviour, and update the tests / algorithm?

std::tuple<T, T> CalculateMotorTorque(T new_torque_value, T right_factor,
T left_factor, bool reset = false) {
struct MotorTorque {
T left_motor_torque_limit;
Copy link
Contributor

Choose a reason for hiding this comment

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

good implementation. You don't need motor_torque in the fields since it's implicit from the typename. This kaes it easier to write and read.

MotorTorque torque;
torque.left_motor_torque_limit
torque.right_motor_torque_limit
// vs
torque.left_limit
torque.right_limit

@@ -23,22 +24,28 @@ T CreateTorqueVectoringFactor(T steering_angle) {
}

template <typename T>
std::tuple<T, T> AdjustTorqueVectoring(T steering_angle,
T torque_vectoring_factor) {
struct TorqueVector {
Copy link
Contributor

Choose a reason for hiding this comment

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

same comment as motor_torque.h,, the fields can just be .left and .right since _torque_vector is implicit in the typename

@Tegh25
Copy link
Member Author

Tegh25 commented Jan 14, 2025

We were more focused on algorithm than code design when writing the controls functions. I think that you should move the running avg to the class so that each object instance has its own

The CalculateMotorTorque function wasn't doing much other than the running avg so I removed it entirely.

@Tegh25 Tegh25 requested a review from BlakeFreer January 14, 2025 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

Implement the Simple Vehicle Dynamics Interface in C++
2 participants