Skip to content

Commit 6fc3616

Browse files
committed
shrink memory
1 parent 1676c15 commit 6fc3616

3 files changed

Lines changed: 73 additions & 164 deletions

File tree

src/common/base_classes/FOCMotor.cpp

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,8 @@ void FOCMotor::updateMotionControlType(MotionControlType new_motion_controller)
600600
}
601601

602602
if (new_motion_controller == MotionControlType::angle_profile) {
603-
trajectoryResetTrapezoidal(profile_state, shaft_angle, 0.0f, target);
603+
profile_state.position = shaft_angle;
604+
profile_state.velocity = 0.0f;
604605
profile_state.initialized = false;
605606
} else if (controller == MotionControlType::angle_profile) {
606607
profile_state.velocity = 0.0f;
@@ -825,25 +826,66 @@ void FOCMotor::move(float new_target) {
825826
// filter the measured angle to reduce noise and improve stability
826827
float measured_angle = LPF_angle(shaft_angle);
827828

828-
// if acceleration limit is set, use trapezoidal profile to
829-
// generate the angle and velocity set points
829+
// if acceleration limit is set, use inline trapezoidal profile (bang-bang control)
830830
if (acceleration_limit > 0.0f) {
831831
// calculate the time step in seconds
832832
float dt = move_time_us * 1e-6f;
833833
if (dt <= 0.0f || dt > 0.5f) dt = 1e-3f;
834834

835-
TrapezoidalProfileOutput prof = trajectoryStepTrapezoidal(profile_state,
836-
measured_angle,
837-
shaft_velocity,
838-
dt,
839-
target,
840-
velocity_limit,
841-
acceleration_limit);
842-
843-
// update the angle set point with the value from the trapezoidal profile
844-
shaft_angle_sp = prof.position;
845-
// update the feed forward velocity with the value from the trapezoidal profile
846-
velocity_ff += prof.velocity;
835+
// Initialize profile on first call
836+
if (!profile_state.initialized) {
837+
profile_state.position = measured_angle;
838+
profile_state.velocity = shaft_velocity;
839+
profile_state.initialized = true;
840+
}
841+
842+
// Bang-bang trapezoidal velocity profile
843+
float direction = _sign(target - profile_state.position);
844+
float distance_remaining = fabsf(target - profile_state.position);
845+
float speed_magnitude = fabsf(profile_state.velocity);
846+
847+
// IMPORTANT
848+
// for given velocity v and acceleration a, the time to stop t = v/a - (following from v = a.t )
849+
// and the distance traveled during that time is d = v.t - 0.5.a.t^2 = v^2 / (2.a)
850+
float stopping_distance = (speed_magnitude * speed_magnitude) / (2.0f * acceleration_limit);
851+
852+
// Determine commanded acceleration (bang-bang)
853+
float commanded_accel = 0.0f;
854+
if (profile_state.velocity * direction < 0.0f) {
855+
// Moving wrong direction: accelerate toward target
856+
commanded_accel = direction * acceleration_limit;
857+
} else if (stopping_distance >= distance_remaining) {
858+
// Close enough to stop: decelerate
859+
commanded_accel = -direction * acceleration_limit;
860+
} else if (speed_magnitude < velocity_limit) {
861+
// Below speed limit and far from target: accelerate
862+
commanded_accel = direction * acceleration_limit;
863+
} else {
864+
// At speed limit: maintain
865+
commanded_accel = 0.0f;
866+
}
867+
868+
// Integrate: new velocity
869+
profile_state.velocity += commanded_accel * dt;
870+
profile_state.velocity = _constrain(profile_state.velocity, -velocity_limit, velocity_limit);
871+
872+
// Integrate: new position
873+
float position_step = profile_state.velocity * dt;
874+
if (distance_remaining < 1e-6f && speed_magnitude < (acceleration_limit * dt)) {
875+
// Nearly at target and slow: snap to target
876+
profile_state.position = target;
877+
profile_state.velocity = 0.0f;
878+
} else if (distance_remaining <= fabsf(position_step)) {
879+
// Final step would overshoot: clamp
880+
profile_state.position = target;
881+
profile_state.velocity = 0.0f;
882+
} else {
883+
profile_state.position += position_step;
884+
}
885+
886+
// Update setpoint with profiled values
887+
shaft_angle_sp = profile_state.position;
888+
velocity_ff += profile_state.velocity;
847889
}
848890

849891
// calculate velocity set point

src/common/trajectory.cpp

Lines changed: 0 additions & 103 deletions
This file was deleted.

src/common/trajectory.h

Lines changed: 16 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,28 @@
11
#ifndef TRAJECTORY_H
22
#define TRAJECTORY_H
3-
4-
#include "foc_utils.h"
5-
63
/**
7-
* State of a trapezoidal motion profile
4+
* Trajectory profile implementation - INLINED
5+
*
6+
* All motion profile logic has been moved directly into FOCMotor::move()
7+
* for the angle_profile control case to reduce flash memory footprint
8+
* on resource-constrained boards (e.g., Arduino Leonardo).
9+
*
10+
* For reference on bang-bang motion profiles:
11+
* - https://mechatronics.studio/blog/bang-bang-motion-profile/
12+
* - https://www.youtube.com/watch?v=qYJpl7SNoww
13+
*
14+
* This file is kept for reference but generates no code.
815
*/
9-
struct TrapezoidalProfileState {
10-
float position = 0.0f;
11-
float velocity = 0.0f;
12-
// float acceleration = 0.0f; // not used so commented to save memory
13-
// float target = 0.0f;
14-
bool initialized = false;
15-
};
1616

17+
1718
/**
18-
* Output of a trapezoidal motion profile step
19+
* Minimal state for inline trapezoidal profile (no external functions)
20+
* Logic is implemented directly in FOCMotor::move() for angle_profile case
1921
*/
20-
struct TrapezoidalProfileOutput {
22+
struct TrapezoidalProfileState {
2123
float position = 0.0f;
2224
float velocity = 0.0f;
23-
float acceleration = 0.0f;
25+
bool initialized = false;
2426
};
2527

26-
/**
27-
* Resets the trapezoidal profile state to the current position and velocity, and sets the target position.
28-
* @param state - the current state of the trapezoidal profile (position, velocity, acceleration, target, initialized)
29-
* @param current_position - the current position of the system
30-
* @param current_velocity - the current velocity of the system
31-
* @param target_position - the desired target position to reach
32-
*/
33-
void trajectoryResetTrapezoidal(TrapezoidalProfileState& state,
34-
float current_position,
35-
float current_velocity,
36-
float target_position);
37-
38-
/**
39-
* Calculates the next step of a trapezoidal motion profile given the current state, target position, and limits.
40-
* @param state - the current state of the trapezoidal profile (position, velocity, acceleration, target, initialized)
41-
* @param current_position - the current position of the system
42-
* @param current_velocity - the current velocity of the system
43-
* @param dt - the time step in seconds
44-
* @param target_position - the desired target position to reach
45-
* @param velocity_limit - the maximum allowed velocity (absolute value)
46-
* @param acceleration_limit - the maximum allowed acceleration (absolute value)
47-
* @returns a TrapezoidalProfileOutput struct containing the updated position, velocity, and acceleration for the next step of the profile
48-
*
49-
*/
50-
TrapezoidalProfileOutput trajectoryStepTrapezoidal(TrapezoidalProfileState& state,
51-
float current_position,
52-
float current_velocity,
53-
float dt,
54-
float target_position,
55-
float velocity_limit,
56-
float acceleration_limit);
57-
5828
#endif

0 commit comments

Comments
 (0)