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

Launch Control Palmer #23

Open
wants to merge 16 commits into
base: roman
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ test/**/*.png
# Annoying ropeproject
**/.ropeproject

test/**/*.png

# vim
*.swp

Expand Down
36 changes: 26 additions & 10 deletions can_spec_my18.yml
Original file line number Diff line number Diff line change
Expand Up @@ -370,16 +370,6 @@ buses:
position: 6
length: 1
c_type: bool
lc_state:
position: 7
length: 3
c_type: enum
enum:
BEFORE: 0
SPEEDING_UP: 1
SPEED_CONTROLLER: 2
ZERO_TORQUE: 3
DONE: 4
VCUErrors:
can_id: 0x0F4
period: 111ms
Expand Down Expand Up @@ -686,6 +676,19 @@ buses:
position: 60
length: 1
c_type: bool
DashRequestLC:
can_id: 0x0D5
is_big_endian: true
period: 69ms
segments:
using_launch_ctrl:
position: 0
length: 1
c_type: bool
launch_ctrl_slip_ratio: # Ranges from 105 to 115
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does it range between these values? Will this ever change?

Copy link
Collaborator

Choose a reason for hiding this comment

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

I talk about this is confluence docs. This number was something that Luis suggested but could use some more backing.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, might be good to at least show how you might come up with this on confluence.

position: 16
length: 16
c_type: uint16_t
VCUControlsParams:
can_id: 0x0D4
is_big_endian: true
Expand Down Expand Up @@ -735,6 +738,19 @@ buses:
position: 60
length: 1
c_type: bool
VCUParamsLC:
can_id: 0x0D6
is_big_endian: true
period: 200ms
segments:
using_launch_ctrl:
position: 0
length: 1
c_type: bool
slip_ratio: # Ranges from 105 to 115
position: 16
length: 16
c_type: uint16_t
ButtonRequest:
can_id: 0x0D8
period: 73ms
Expand Down
36 changes: 34 additions & 2 deletions src/dashboard/src/page_manager.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ void draw_nav_line(page_manager_t *pm, NHD_US2066_OLED *oled) {

void draw_critical_page(page_manager_t *pm, NHD_US2066_OLED *oled);
void draw_regen_page(page_manager_t *pm, NHD_US2066_OLED *oled);
void draw_launch_control_page(page_manager_t *pm, NHD_US2066_OLED *oled);
void draw_traction_page(page_manager_t *pm, NHD_US2066_OLED *oled);
void draw_fault_page(page_manager_t *pm, NHD_US2066_OLED *oled);

Expand All @@ -60,8 +61,11 @@ void page_manager_update(page_manager_t *pm, NHD_US2066_OLED *oled) {
draw_critical_page(pm, oled);
break;
case DASH_PAGE_REGEN:
draw_regen_page(pm, oled);
break;
draw_regen_page(pm, oled);
break;
case DASH_PAGE_LAUNCH_CONTROL:
draw_launch_control_page(pm, oled);
break;
case DASH_PAGE_TEMP_LIM:
draw_temp_lim_page(pm, oled);
break;
Expand Down Expand Up @@ -430,6 +434,34 @@ void draw_volt_lim_page(page_manager_t *pm, NHD_US2066_OLED *oled) {
oled_print(oled, ">");
}

void draw_launch_control_page(page_manager_t *pm, NHD_US2066_OLED *oled) {
carstats_t *stats = pm->stats;

oled_clearline(oled, 1);
oled_set_pos(oled, 1, 0);

if (stats->buttons.right.rising_edge) {
stats->controls.launch_ctrl_slip_ratio += 1;
}

stats->controls.launch_ctrl_slip_ratio = LOOPOVER(stats->controls.launch_ctrl_slip_ratio, 101, 120);

if (stats->buttons.B.rising_edge) stats->controls.using_launch_ctrl ^= 1; // NOT

oled_print(oled, "LAUNCH CONTROL ");

oled_print(oled, (stats->controls.using_launch_ctrl) ? "ON" : "OFF");

oled_rprint_pad(oled, "SLIP RATIO ", 4);

if (stats->controls.launch_ctrl_slip_ratio != -1) {
oled_print_num(oled, stats->controls.launch_ctrl_slip_ratio);
}
else {
oled_print(oled, DATA_UNKNOWN);
}
}

void draw_fault_page(page_manager_t *pm, NHD_US2066_OLED *oled) {
carstats_t *stats = pm->stats;

Expand Down
20 changes: 20 additions & 0 deletions src/vcu/inc/controls.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@
#define MAX_ACCEL_VAL 1000
#define MIN_ACCEL_VAL 0

// Launch control contants
Copy link
Contributor

Choose a reason for hiding this comment

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

Spelling error

// After wheel speed crosses this threshold, start using slip controller
#define LC_WS_THRESH 45000
#define LC_cGR 347 // Gear ratio times 100
#define LC_ACCEL_BEGIN 950 // 95%
#define LC_ACCEL_RELEASE 50 // 5%
#define LC_BRAKE_BEGIN 100 // We want a lower threshold
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we still want this comment?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry, this comment was to indicate that we want lower threshold than normal. I can fix it to make it clearer

#define LC_BACKWARDS_CUTOFF 10

// RG = regen
#define RG_MOTOR_SPEED_THRESH 250 // RPM
#define RG_CAR_SPEED_THRESH 5 // kph
Expand All @@ -31,6 +40,14 @@
#define FRONT_BRAKE brake_1
#define REAR_BRAKE brake_2

typedef enum {
BEFORE,
SPEEDING_UP,
SPEED_CONTROLLER,
ZERO_TORQUE,
DONE,
} Launch_Control_State_T;

// TL = temp limiting
#define MAX_TEMP 5800 // centiCelsius

Expand All @@ -40,11 +57,14 @@
#define TEMP_LOG_LENGTH 200

extern can0_VCUControlsParams_T control_settings;
extern can0_VCUParamsLC_T lc_settings;

// INTERACTION FUNCTIONS
void enable_controls(void);
void disable_controls(void);
bool get_controls_enabled(void);
void execute_controls(void);
void set_lc_done(void);
void set_lc_state_before(void);

#endif // ifndef __TORQUE_CALC
141 changes: 131 additions & 10 deletions src/vcu/src/controls.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ static bool enabled = false;
static int32_t torque_command = 0;
static int32_t speed_command = 0;
can0_VCUControlsParams_T control_settings = {};
can0_VCUParamsLC_T lc_settings = {};
static Launch_Control_State_T lc_state = BEFORE;

static uint32_t get_front_wheel_speed(void);
static bool any_lc_faults();

static int32_t hinge_limiter(int32_t x, int32_t m, int32_t e, int32_t c);

// PRIVATE FUNCTIONS
static int32_t get_torque(void);
static int32_t get_regen_torque(void);
static int32_t get_launch_control_speed(uint32_t front_wheel_speed);
static int32_t get_temp_limited_torque(int32_t pedal_torque);
static int32_t get_voltage_limited_torque(int32_t pedal_torque);

Expand All @@ -22,12 +28,16 @@ void init_controls_defaults(void) {
control_settings.volt_lim_min_gain = 0;
control_settings.volt_lim_min_voltage = 300;
control_settings.torque_temp_limited = false;

lc_settings.using_launch_ctrl = false;
lc_settings.slip_ratio = 112;
Copy link
Contributor

Choose a reason for hiding this comment

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

Would recommend bringing 112 out to a DEFAULT_SLIP_RATIO constant

}

void enable_controls(void) {
enabled = true;
torque_command = 0;
speed_command = 0;
lc_state = BEFORE;

unlock_brake_valve();
}
Expand All @@ -36,6 +46,7 @@ void disable_controls(void) {
enabled = false;
torque_command = 0;
speed_command = 0;
lc_state = DONE;

set_brake_valve(false);
lock_brake_valve();
Expand All @@ -47,6 +58,7 @@ bool get_controls_enabled(void) {

void execute_controls(void) {
if (!enabled) return;
sebLopezCot marked this conversation as resolved.
Show resolved Hide resolved
bool launch_ctrl_entered = false;

torque_command = get_torque();
controls_monitoring.raw_torque = torque_command;
Expand All @@ -69,9 +81,10 @@ void execute_controls(void) {
// Extra check to ensure we are only sending regen torque when allowed
if (torque_command == 0) {
torque_command = regen_torque;
}
else {
// Only use limits when we're not doing regen
} else { // Only use limits and launch control when we're not doing regen
// Even if we are doing launch control, calculate limits for loggind also so that we are not doing
// launch control when we're supposed to be limiting

int32_t voltage_limited_torque = get_voltage_limited_torque(torque_command);
// static uint32_t last_vt = 0;
// if (HAL_GetTick() - last_vt > 10) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Just remove this commented code

Copy link
Contributor

Choose a reason for hiding this comment

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

And also there is a typo here "loggind"

Expand All @@ -90,13 +103,14 @@ void execute_controls(void) {
// }
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here: remove commented code

if (!control_settings.using_temp_limiting) temp_limited_torque = torque_command;

uint32_t torque_temp_limited = temp_limited_torque < torque_command;
// Whether torque is temp limited needs to be sent out over CAN so the dash knows not to allow regen
control_settings.torque_temp_limited = temp_limited_torque < torque_command;

int32_t min_sensor_torque;
if (voltage_limited_torque < temp_limited_torque) {
min_sensor_torque = voltage_limited_torque;
}
else {
} else {
min_sensor_torque = temp_limited_torque;
}

Expand All @@ -105,15 +119,70 @@ void execute_controls(void) {
int32_t limited_torque;
if (dash_limited_torque < min_sensor_torque) {
limited_torque = dash_limited_torque;
}
else {
} else {
limited_torque = min_sensor_torque;
}

torque_command = limited_torque;
bool torque_limited = limited_torque < controls_monitoring.raw_torque;

if (launch_ctrl_entered = (lc_settings.using_launch_ctrl && lc_state != DONE && !torque_limited)) {
// We shouldn't be braking in launch control, so reset regen valve
set_brake_valve(false);
uint32_t front_wheel_speed = get_front_wheel_speed();

// Mini FSM
switch (lc_state) {
case BEFORE:
sendSpeedCmdMsg(0, 0);

// Transition
if (pedalbox_min(accel) > LC_ACCEL_BEGIN) {
lc_state = SPEEDING_UP;
printf("[LAUNCH CONTROL] SPEEDING UP STATE ENTERED\r\n");
}
break;
case SPEEDING_UP:
if (torque_command < 1000) sendSpeedCmdMsg(500, torque_command);
Copy link
Contributor

@sebLopezCot sebLopezCot Sep 8, 2018

Choose a reason for hiding this comment

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

In confluence, we have "LC_SPEEDING_UP_TORQUE", but here it is not a constant. Can we fix this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also can we make 300 and 500 some sort of constants too and add them to the documentation in confluence?

Copy link
Contributor

Choose a reason for hiding this comment

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

Also technically the if statement here with < 1000 should probably be reflected in the state machine somehow. I think you intended to back off on the torque command if we start to exceed 1000, right?

Copy link
Collaborator

@daniwhite daniwhite Sep 8, 2018

Choose a reason for hiding this comment

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

Oh yeah I realized I had made it a constant and forgot to push it. I'll fix the others

Copy link
Collaborator

Choose a reason for hiding this comment

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

And yeah my intention we to command max(commanded torque, 1000)

else sendSpeedCmdMsg(300, 1000);

// Transition
if (any_lc_faults()) {
lc_state = ZERO_TORQUE;
printf("[LAUNCH CONTROL] ZERO TORQUE STATE ENTERED\r\n");
} else if (front_wheel_speed > LC_WS_THRESH) {
lc_state = SPEED_CONTROLLER;
printf("[LAUNCH CONTROL] SPEED CONTROLLER STATE ENTERED\r\n");
}
break;
case SPEED_CONTROLLER:
speed_command = get_launch_control_speed(front_wheel_speed);
sendSpeedCmdMsg(speed_command, torque_command);

// Transition
if (any_lc_faults()) {
lc_state = ZERO_TORQUE;
printf("[LAUNCH CONTROL] ZERO TORQUE STATE ENTERED\r\n");
}
break;
case ZERO_TORQUE:
sendTorqueCmdMsg(0);

if (pedalbox_max(accel) < LC_ACCEL_RELEASE) {
lc_state = DONE;
printf("[LAUNCH CONTROL] DONE STATE ENTERED\r\n");
}
break;
default:
printf("ERROR: NO STATE!\r\n");
sebLopezCot marked this conversation as resolved.
Show resolved Hide resolved
break;
}
}
}
if (!launch_ctrl_entered) {
// In LC we already sent our command above
sendTorqueCmdMsg(torque_command);
}

sendTorqueCmdMsg(torque_command);
}

static int32_t get_torque(void) {
Expand Down Expand Up @@ -150,10 +219,62 @@ static int32_t get_regen_torque() {
}
}

// Regen is negative torque, and we've calculated a positive number so far
return -1 * regen_torque;
}

static int32_t get_launch_control_speed(uint32_t front_wheel_speed) {
uint32_t front_wheel_speedRPM = front_wheel_speed / 1000;
// Divide 100 because slip ratio is times 100, divide by 100 again because
// gear ratio is also multiplied by 100
int32_t target_speed = front_wheel_speedRPM * lc_settings.slip_ratio * LC_cGR / (100 * 100);
return target_speed;
}

static uint32_t get_front_wheel_speed() {
uint32_t left_front_speed;
uint32_t right_front_speed;

// If the 32 bit wheel speed is zero, then it's disconnect (in which case we should
// use the 16 bit one), or the wheels are actually not moving, so the 16 bit one will
// be zero as well
if (wheel_speeds.front_left_32b_wheel_speed == 0) {
left_front_speed = wheel_speeds.front_left_16b_wheel_speed;
} else {
left_front_speed = wheel_speeds.front_left_32b_wheel_speed;
}

if (wheel_speeds.front_right_32b_wheel_speed == 0) {
right_front_speed = wheel_speeds.front_right_16b_wheel_speed;
} else {
right_front_speed = wheel_speeds.front_right_32b_wheel_speed;
}

uint32_t avg_wheel_speed = left_front_speed/2 + right_front_speed/2;
return avg_wheel_speed;
}

static bool any_lc_faults() {
if (pedalbox_min(accel) < LC_ACCEL_BEGIN) {
printf("[LAUNCH CONTROL ERROR] Accel min (%d) too low\r\n", pedalbox_min(accel));
return true;
} else if (pedalbox.brake_2 > LC_BRAKE_BEGIN) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why only brake_2? Don't we want the max of the 2 brakes?

Copy link
Contributor

Choose a reason for hiding this comment

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

I have learned the reason, but would still like a comment here explaining why we only need to check brake 2

Copy link
Collaborator

Choose a reason for hiding this comment

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

I actually don't remember the reason myself...should definitely go in a comment

printf("[LAUNCH CONTROL ERROR] Brake min (%d) too low\r\n", pedalbox.brake_2);
return true;
} else if (mc_readings.speed > LC_BACKWARDS_CUTOFF) {
printf("[LAUNCH CONTROL ERROR] MC reading (%d) is great than cutoff (%d)\r\n", mc_readings.speed, LC_BACKWARDS_CUTOFF);
return true;
}
return false;
}

void set_lc_state_before() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this function ever used? Can we delete it?

lc_state = BEFORE;
}

void set_lc_zero_torque() {
sebLopezCot marked this conversation as resolved.
Show resolved Hide resolved
lc_state = ZERO_TORQUE;
}

static int32_t get_temp_limited_torque(int32_t pedal_torque) {
uint32_t temp_sum = 0;
for (uint32_t i = 0; i < TEMP_LOG_LENGTH; i++) {
Expand Down
Loading