Skip to content

Commit 03264c4

Browse files
authored
grSim Control Layer Abstraction (#2004)
* Add wheels to controls * Add draft stop function * Add rough interface for firmware_robot and force/velocity wheels * Add basic per wheel and local velociy (still needs implementation) * Further implement firmware_robot and integrate controls * Move robot_constants to its own file and change signatures to applyAccel / trackRobotInFrame accordingly * Add position trajectory to firmware_robot * Add robot constants and most of trajectory follower * MOre fixes * Get firmware_robot compiling * Delete files gone from merge confs * Replace some app_wheel_create instances * Temporarily reintroduce wheel getters, corner_kick_play_test works * Fix some unit tests * Minor fix to main.c * Fix simulator_robot_singleton test and formatting * Add app_firmware_robot_destroy for force wheels * Fix velocity wheel robot destroy * Fix free error whoops * Move move_plan_rotation away and fix main.c * Add wheel destroyers as separate functions * Clean up firmware robot * Clean up javadocs * Address PR comments * Address wheel array comments * Fix force wheels setLocalVelocity
1 parent 109fc47 commit 03264c4

26 files changed

+1152
-643
lines changed

src/firmware/app/control/BUILD

+2-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ cc_library(
7575
srcs = ["control.c"],
7676
hdrs = ["control.h"],
7777
deps = [
78-
"//firmware/app/world:firmware_robot",
78+
"//firmware/app/world:firmware_robot_constants",
79+
"//firmware/app/world:force_wheel",
7980
"//firmware/shared:physics",
8081
"//firmware/shared:util",
8182
],
@@ -87,7 +88,6 @@ cc_library(
8788
hdrs = ["physbot.h"],
8889
deps = [
8990
":bangbang",
90-
"//firmware/app/world:firmware_robot",
9191
"//firmware/shared:physics",
9292
],
9393
)

src/firmware/app/control/control.c

+32-64
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@
1010
* Note that this could scale the forces *down* if they exceed the physical capabilities
1111
* of the robot (ex. wheel slip).
1212
*
13-
* @param wheels Wheels to compute the maximum torque scaling from
13+
* @param force_wheels Force wheels to compute the maximum torque scaling from
1414
* @param wheel_forces Forces to apply to each wheel
1515
* @param battery_voltage The current battery voltage
1616
*
1717
* @return The amount by which to scale the force on each wheel to get the maximum
1818
* torque possible while maintaining the same torque ratio between wheels
1919
*/
20-
float app_control_getMaximalTorqueScaling(const Wheel_t* wheels[4],
20+
float app_control_getMaximalTorqueScaling(const ForceWheel_t* force_wheels[4],
2121
const float wheel_forces[4],
2222
float battery_voltage)
2323
{
@@ -26,12 +26,12 @@ float app_control_getMaximalTorqueScaling(const Wheel_t* wheels[4],
2626

2727
for (long i = 0; i < 4; i++)
2828
{
29-
const Wheel_t* wheel = wheels[i];
30-
const WheelConstants_t constants = app_wheel_getWheelConstants(wheel);
31-
float force = wheel_forces[i];
29+
const ForceWheel_t* wheel = force_wheels[i];
30+
const ForceWheelConstants_t constants = app_force_wheel_getWheelConstants(wheel);
31+
float force = wheel_forces[i];
3232
float motor_torque =
3333
force * constants.wheel_radius * constants.wheel_rotations_per_motor_rotation;
34-
float curr_motor_rpm = app_wheel_getMotorSpeedRPM(wheel);
34+
float curr_motor_rpm = app_force_wheel_getMotorSpeedRPM(wheel);
3535

3636
float resistive_voltage_loss = motor_torque *
3737
constants.motor_current_per_unit_torque *
@@ -62,20 +62,22 @@ float app_control_getMaximalTorqueScaling(const Wheel_t* wheels[4],
6262
* Note that this could scale the accelerations *down* if the given forces exceed the
6363
* physical capabilities of the robot (ex. wheel slip).
6464
*
65-
* @param robot The robot to compute the acceleration scaling constant for
65+
* @param robot_constants The robot constants representing the robot
66+
* @param battery_voltage The robot's battery voltage
67+
* @param force_wheels The robot's force wheels
6668
* @param linear_accel_x [m/s^2] The linear x acceleration to scale
6769
* @param linear_accel_y [m/s^2] The linear y acceleration to scale
6870
* @param angular_accel [rad/s^2] The angular acceleration to scale
6971
*
7072
* @return The scaling constant to multiply the all acceleration values by in order to
7173
* accelerate the robot as fast as physically possible
7274
*/
73-
float app_control_getMaximalAccelScaling(const FirmwareRobot_t* robot,
75+
float app_control_getMaximalAccelScaling(const RobotConstants_t robot_constants,
76+
float battery_voltage,
77+
const ForceWheel_t* force_wheels[4],
7478
const float linear_accel_x,
7579
const float linear_accel_y, float angular_accel)
7680
{
77-
const RobotConstants_t robot_constants = app_firmware_robot_getRobotConstants(robot);
78-
7981
// first convert accelerations into consistent units
8082
// choose units of Force (N)
8183
float normed_force[3];
@@ -87,25 +89,25 @@ float app_control_getMaximalAccelScaling(const FirmwareRobot_t* robot,
8789
float wheel_forces[4];
8890
force3_to_force4(normed_force, wheel_forces);
8991

90-
const Wheel_t* wheels[4];
91-
wheels[0] = app_firmware_robot_getFrontLeftWheel(robot);
92-
wheels[1] = app_firmware_robot_getBackLeftWheel(robot);
93-
wheels[2] = app_firmware_robot_getBackRightWheel(robot);
94-
wheels[3] = app_firmware_robot_getFrontRightWheel(robot);
95-
96-
float battery_voltage = app_firmware_robot_getBatteryVoltage(robot);
97-
98-
return app_control_getMaximalTorqueScaling(wheels, wheel_forces, battery_voltage);
92+
return app_control_getMaximalTorqueScaling(force_wheels, wheel_forces,
93+
battery_voltage);
9994
}
10095

101-
void app_control_applyAccel(const FirmwareRobot_t* robot, float linear_accel_x,
96+
void app_control_applyAccel(RobotConstants_t robot_constants,
97+
ControllerState_t* controller_state, float battery_voltage,
98+
ForceWheel_t* force_wheels[4], float linear_accel_x,
10299
float linear_accel_y, float angular_accel)
103100
{
104-
const RobotConstants_t robot_constants = app_firmware_robot_getRobotConstants(robot);
101+
const ForceWheel_t* wheels[4];
102+
wheels[0] = force_wheels[0];
103+
wheels[1] = force_wheels[1];
104+
wheels[2] = force_wheels[2];
105+
wheels[3] = force_wheels[3];
105106

106107
// check for max acceleration in direction of the vel difference
107-
float scaling = app_control_getMaximalAccelScaling(robot, linear_accel_x,
108-
linear_accel_y, angular_accel);
108+
float scaling =
109+
app_control_getMaximalAccelScaling(robot_constants, battery_voltage, wheels,
110+
linear_accel_x, linear_accel_y, angular_accel);
109111

110112
// if the (very naive) 1 tick acceleration violates the physical limits of the robot
111113
// scale it to maximum
@@ -117,10 +119,9 @@ void app_control_applyAccel(const FirmwareRobot_t* robot, float linear_accel_x,
117119
angular_accel *= scaling;
118120
}
119121

120-
ControllerState_t* controller_state = app_firmware_robot_getControllerState(robot);
121-
float prev_linear_accel_x = controller_state->last_applied_acceleration_x;
122-
float prev_linear_accel_y = controller_state->last_applied_acceleration_y;
123-
float prev_angular_accel = controller_state->last_applied_acceleration_angular;
122+
float prev_linear_accel_x = controller_state->last_applied_acceleration_x;
123+
float prev_linear_accel_y = controller_state->last_applied_acceleration_y;
124+
float prev_angular_accel = controller_state->last_applied_acceleration_angular;
124125

125126
float linear_diff_x = linear_accel_x - prev_linear_accel_x;
126127
float linear_diff_y = linear_accel_y - prev_linear_accel_y;
@@ -151,41 +152,8 @@ void app_control_applyAccel(const FirmwareRobot_t* robot, float linear_accel_x,
151152
float wheel_force[4];
152153
speed3_to_speed4(robot_force, wheel_force); // Convert to wheel coordinate system
153154

154-
app_wheel_applyForce(app_firmware_robot_getFrontLeftWheel(robot), wheel_force[0]);
155-
app_wheel_applyForce(app_firmware_robot_getFrontRightWheel(robot), wheel_force[3]);
156-
app_wheel_applyForce(app_firmware_robot_getBackLeftWheel(robot), wheel_force[1]);
157-
app_wheel_applyForce(app_firmware_robot_getBackRightWheel(robot), wheel_force[2]);
158-
}
159-
160-
void app_control_trackVelocityInRobotFrame(FirmwareRobot_t* robot,
161-
float linear_velocity_x,
162-
float linear_velocity_y,
163-
float angular_velocity)
164-
{
165-
float current_vx = app_firmware_robot_getVelocityX(robot);
166-
float current_vy = app_firmware_robot_getVelocityY(robot);
167-
float current_angular_velocity = app_firmware_robot_getVelocityAngular(robot);
168-
float current_orientation = app_firmware_robot_getOrientation(robot);
169-
170-
// Rotate the current_velocity vector from the world frame to the robot frame
171-
float current_velocity[2];
172-
current_velocity[0] = current_vx;
173-
current_velocity[1] = current_vy;
174-
rotate(current_velocity, -current_orientation);
175-
176-
// This is the "P" term in a PID controller. We essentially do proportional
177-
// control of our acceleration based on velocity error
178-
static const float VELOCITY_ERROR_GAIN = 10.0f;
179-
180-
float desired_acceleration[2];
181-
desired_acceleration[0] =
182-
(linear_velocity_x - current_velocity[0]) * VELOCITY_ERROR_GAIN;
183-
desired_acceleration[1] =
184-
(linear_velocity_y - current_velocity[1]) * VELOCITY_ERROR_GAIN;
185-
186-
float angular_acceleration =
187-
(angular_velocity - current_angular_velocity) * VELOCITY_ERROR_GAIN;
188-
189-
app_control_applyAccel(robot, desired_acceleration[0], desired_acceleration[1],
190-
angular_acceleration);
155+
app_force_wheel_applyForce(force_wheels[0], wheel_force[0]);
156+
app_force_wheel_applyForce(force_wheels[3], wheel_force[3]);
157+
app_force_wheel_applyForce(force_wheels[1], wheel_force[1]);
158+
app_force_wheel_applyForce(force_wheels[2], wheel_force[2]);
191159
}

src/firmware/app/control/control.h

+10-18
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,23 @@
11
#pragma once
22

3-
#include "firmware/app/world/firmware_robot.h"
3+
#include "firmware/app/world/firmware_robot_constants.h"
4+
#include "firmware/app/world/force_wheel.h"
45

56
/**
67
* Apply the given acceleration (in robot coordinates) to the given robot
78
*
8-
* @param robot The robot to apply acceleration to
9+
* @param robot_constants The robot constants representing the robot
10+
* @param controller_state The controller state representing the robot
11+
* @param battery_voltage The robot's battery voltage
12+
* @param force_wheels The robot's force wheels (front_left, back_left, back_right,
13+
* front_right in order)
914
* @param linear_accel_x The linear acceleration, in robot coordinates, in the x
1015
* (forward/backwards) direction (m/s^2)
1116
* @param linear_accel_y The linear acceleration, in robot coordinates, in the y
1217
* (side-to-side) direction (m/s^2)
1318
* @param angular_accel The angular acceleration to apply to the robot (rad/s^2)
1419
*/
15-
void app_control_applyAccel(const FirmwareRobot_t* robot, float linear_accel_x,
20+
void app_control_applyAccel(const RobotConstants_t robot_constants,
21+
ControllerState_t* controller_state, float battery_voltage,
22+
ForceWheel_t* force_wheels[4], float linear_accel_x,
1623
float linear_accel_y, float angular_accel);
17-
18-
/**
19-
* Drive the given robot at the given velocity in the robot coordinate frame
20-
*
21-
* @param robot The robot to move at the given velocity
22-
* @param linear_velocity_x The velocity to move at in the x-direction in the robot
23-
* coordinate frame (m/s)
24-
* @param linear_velocity_y The velocity to move at in the y-direction in the robot
25-
* coordinate frame (m/s)
26-
* @param angular_velocity The angular velocity to move at (rad/s)
27-
*/
28-
void app_control_trackVelocityInRobotFrame(FirmwareRobot_t* robot,
29-
float linear_velocity_x,
30-
float linear_velocity_y,
31-
float angular_velocity);

src/firmware/app/control/physbot.c

+5-7
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,12 @@
55

66
#define TIME_HORIZON 0.05f // s
77

8-
PhysBot app_physbot_create(const FirmwareRobot_t *robot, float *destination,
8+
PhysBot app_physbot_create(float velocity_x, float velocity_y, float position_x,
9+
float position_y, float orientation, float *destination,
910
float *major_vec, float *minor_vec)
1011
{
11-
float v[2] = {app_firmware_robot_getVelocityX(robot),
12-
app_firmware_robot_getVelocityY(robot)};
13-
float dr[2] = {destination[0] - app_firmware_robot_getPositionX(robot),
14-
destination[1] - app_firmware_robot_getPositionY(robot)};
12+
float v[2] = {velocity_x, velocity_y};
13+
float dr[2] = {destination[0] - position_x, destination[1] - position_y};
1514
const Component major = {
1615
.disp = dot2D(major_vec, dr), .vel = dot2D(major_vec, v), .accel = 0, .time = 0};
1716
const Component minor = {
@@ -20,8 +19,7 @@ PhysBot app_physbot_create(const FirmwareRobot_t *robot, float *destination,
2019
// current orientation is directly subtracted from destination because we do not
2120
// assume that the user wants the rotational displacement to be the min angle between
2221
// the destination and current orientation
23-
const Component rot = {.disp =
24-
destination[2] - app_firmware_robot_getOrientation(robot)};
22+
const Component rot = {.disp = destination[2] - orientation};
2523
PhysBot pb = {.rot = rot, .maj = major, .min = minor};
2624
for (unsigned i = 0; i < 2; i++)
2725
{

src/firmware/app/control/physbot.h

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#pragma once
22

3-
#include "firmware/app/world/firmware_robot.h"
4-
53
/**
64
* component to build information along major axis, minor axis, or rotation.
75
* disp is the displacement along that axis.
@@ -47,14 +45,19 @@ typedef struct
4745
* as well as data about the bot on the global axis. Details about what
4846
* can go in the PhysBot are in the physbot.h file.
4947
*
50-
* @param robot The current state of the robot
48+
* @param velocity_x the robot's x component of velocity
49+
* @param velocity_y the robot's y component of velocity
50+
* @param position_x the robot's x component of position
51+
* @param position_y the robot's y component of position
52+
* @param orientation the robot's orientation
5153
* @param destination a 3 length array of {x, y, rotation} destination values
5254
* on the global axis
5355
* @param major_vec the major vector components on the global axis
5456
* @param minor_vec the minor vector components on the global axis
5557
* @return a new PhysBot data container
5658
*/
57-
PhysBot app_physbot_create(const FirmwareRobot_t *robot, float *destination,
59+
PhysBot app_physbot_create(float velocity_x, float velocity_y, float position_x,
60+
float position_y, float orientation, float *destination,
5861
float *major_vec, float *minor_vec);
5962

6063
/**

src/firmware/app/primitives/direct_control_primitive.c

+4-11
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,7 @@ void app_direct_control_primitive_start(TbotsProto_DirectControlPrimitive prim_m
3131
prim_msg.wheel_control.direct_per_wheel_control;
3232
state->direct_velocity = false;
3333
// TODO (#1649): Fix passing rpm into an applyForce function
34-
app_wheel_applyForce(app_firmware_robot_getFrontLeftWheel(robot),
35-
control_msg.front_left_wheel_rpm);
36-
app_wheel_applyForce(app_firmware_robot_getBackLeftWheel(robot),
37-
control_msg.back_left_wheel_rpm);
38-
app_wheel_applyForce(app_firmware_robot_getBackRightWheel(robot),
39-
control_msg.back_right_wheel_rpm);
40-
app_wheel_applyForce(app_firmware_robot_getFrontRightWheel(robot),
41-
control_msg.front_right_wheel_rpm);
34+
app_firmware_robot_applyDirectPerWheelPower(robot, control_msg);
4235
break;
4336
}
4437
case TbotsProto_DirectControlPrimitive_direct_velocity_control_tag:
@@ -122,9 +115,9 @@ static void app_direct_control_primitive_tick(void* void_state_ptr,
122115
if (state->direct_velocity)
123116
{
124117
FirmwareRobot_t* robot = app_firmware_world_getRobot(world);
125-
app_control_trackVelocityInRobotFrame(robot, state->direct_target_velocity_x,
126-
state->direct_target_velocity_y,
127-
state->direct_target_velocity_angular);
118+
app_firmware_robot_trackVelocityInRobotFrame(
119+
robot, state->direct_target_velocity_x, state->direct_target_velocity_y,
120+
state->direct_target_velocity_angular);
128121
}
129122
}
130123

src/firmware/app/primitives/move_primitive.c

+2-66
Original file line numberDiff line numberDiff line change
@@ -35,28 +35,6 @@ typedef struct MoveState
3535
} MoveState_t;
3636
DEFINE_PRIMITIVE_STATE_CREATE_AND_DESTROY_FUNCTIONS(MoveState_t);
3737

38-
/**
39-
* Determines the rotation acceleration after setup_bot has been used and
40-
* plan_move has been done along the minor axis. The minor time from bangbang
41-
* is used to determine the rotation time, and thus the rotation velocity and
42-
* acceleration. The rotational acceleration is clamped under the MAX_T_A.
43-
*
44-
* @param pb [in/out] The PhysBot data container that should have minor axis time and
45-
* will store the rotational information
46-
* @param avel The rotational velocity of the bot
47-
*/
48-
void plan_move_rotation(PhysBot* pb, float avel);
49-
50-
void plan_move_rotation(PhysBot* pb, float avel)
51-
{
52-
pb->rot.time = (pb->min.time > TIME_HORIZON) ? pb->min.time : TIME_HORIZON;
53-
// 1.4f is a magic constant to force the robot to rotate faster to its final
54-
// orientation.
55-
pb->rot.vel = 1.4f * pb->rot.disp / pb->rot.time;
56-
pb->rot.accel = (pb->rot.vel - avel) / TIME_HORIZON;
57-
limit(&pb->rot.accel, MAX_T_A);
58-
}
59-
6038
void app_move_primitive_start(TbotsProto_MovePrimitive prim_msg, void* void_state_ptr,
6139
FirmwareWorld_t* world)
6240
{
@@ -159,50 +137,8 @@ static void app_move_primitive_tick(void* void_state_ptr, FirmwareWorld_t* world
159137
trajectory_index++;
160138
}
161139

162-
const float dest_x = state->position_trajectory.x_position[trajectory_index];
163-
const float dest_y = state->position_trajectory.y_position[trajectory_index];
164-
const float dest_orientation =
165-
state->position_trajectory.orientation[trajectory_index];
166-
float dest[3] = {dest_x, dest_y, dest_orientation};
167-
168-
const float curr_x = app_firmware_robot_getPositionX(robot);
169-
const float curr_y = app_firmware_robot_getPositionY(robot);
170-
171-
const float dx = dest_x - curr_x;
172-
const float dy = dest_y - curr_y;
173-
174-
float total_disp = sqrtf(dx * dx + dy * dy);
175-
// Add a small number to avoid division by zero
176-
float major_vec[2] = {dx / (total_disp + 1e-6f), dy / (total_disp + 1e-6f)};
177-
float minor_vec[2] = {major_vec[0], major_vec[1]};
178-
rotate(minor_vec, P_PI / 2);
179-
180-
PhysBot pb = app_physbot_create(robot, dest, major_vec, minor_vec);
181-
182-
const float dest_speed = state->position_trajectory.linear_speed[trajectory_index];
183-
184-
// plan major axis movement
185-
float max_major_a = (float)ROBOT_MAX_ACCELERATION_METERS_PER_SECOND_SQUARED;
186-
float max_major_v = state->max_speed_m_per_s;
187-
float major_params[3] = {dest_speed, max_major_a, max_major_v};
188-
app_physbot_planMove(&pb.maj, major_params);
189-
190-
// plan minor axis movement
191-
float max_minor_a = (float)ROBOT_MAX_ACCELERATION_METERS_PER_SECOND_SQUARED / 2.0f;
192-
float max_minor_v = state->max_speed_m_per_s / 2.0f;
193-
float minor_params[3] = {0, max_minor_a, max_minor_v};
194-
app_physbot_planMove(&pb.min, minor_params);
195-
196-
// plan rotation movement
197-
plan_move_rotation(&pb, app_firmware_robot_getVelocityAngular(robot));
198-
199-
float accel[3] = {0, 0, pb.rot.accel};
200-
201-
// rotate the accel and apply it
202-
app_physbot_computeAccelInLocalCoordinates(
203-
accel, pb, app_firmware_robot_getOrientation(robot), major_vec, minor_vec);
204-
205-
app_control_applyAccel(robot, accel[0], accel[1], accel[2]);
140+
app_firmware_robot_followPosTrajectory(robot, state->position_trajectory,
141+
trajectory_index, state->max_speed_m_per_s);
206142
}
207143

208144
/**

0 commit comments

Comments
 (0)