Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
5a3fb6d
Remove unused member functions and variables
nycrat Jun 3, 2026
868cf6b
Fix call to setStopPrimitive
nycrat Jun 3, 2026
67b3833
Pass in delta_time dynamically for prim exec
nycrat Jun 3, 2026
dd126db
Fix calls to prim exec constructor and stepPrimitive
nycrat Jun 3, 2026
c5342f3
Add setters to RobotState class
nycrat Jun 3, 2026
d449a95
Replace state variables with one RobotState
nycrat Jun 3, 2026
3e929ba
Create default constructor for robot state
nycrat Jun 3, 2026
03da9c8
Replace use of std::pair with RobotState
nycrat Jun 3, 2026
b5b513b
Prim exec update velocity to update state (same logic as only update …
nycrat Jun 3, 2026
5403bbf
Use auto
nycrat Jun 3, 2026
83f5113
Separate time since trajectory creation variables
nycrat Jun 3, 2026
7126c14
Port trajectory path changes from robot localizer branch
nycrat Jun 4, 2026
1d6c8e7
Update robot constants
nycrat Jun 4, 2026
b00e31f
Add cmath dependency
nycrat Jun 4, 2026
c855e54
Implement getting velocities from motion controllers
nycrat Jun 4, 2026
48eaee3
Fix for inverted yellow team world
nycrat Jun 4, 2026
b280095
Remove TODO comment
nycrat Jun 4, 2026
cbbc7e0
Merge branch 'master' into avah/prim_exec_motion_controller
nycrat Jun 5, 2026
b870c79
[pre-commit.ci lite] apply automatic fixes
pre-commit-ci-lite[bot] Jun 5, 2026
b08dce1
Tune pid constants
nycrat Jun 6, 2026
6b400ef
Tune more
nycrat Jun 6, 2026
bd2ad3a
Merge branch 'master' into avah/prim_exec_motion_controller
nycrat Jun 7, 2026
5925517
Merge branch 'master' of github.com:UBC-Thunderbots/Software into ava…
Andrewyx Jun 7, 2026
aa8d9eb
Merge branch 'avah/prim_exec_motion_controller' of github.com:UBC-Thu…
Andrewyx Jun 7, 2026
9155ed6
Fix simulator prmitive executor update order
nycrat Jun 8, 2026
b7ddf2a
Reduce linear trajectory target max speed
nycrat Jun 8, 2026
def1626
Disable pure pid and tune constants
nycrat Jun 8, 2026
1ad0911
Enable pure pid based on time as well
nycrat Jun 8, 2026
c35ab85
Merge branch 'master' into avah/prim_exec_motion_controller
nycrat Jun 9, 2026
1fe5a67
DEBUGGING DONT MERGE
nycrat Jun 9, 2026
bc2f713
Revert create trajectory from params changes
nycrat Jun 9, 2026
35f0160
WIP
nycrat Jun 9, 2026
3315560
Revert "DEBUGGING DONT MERGE"
nycrat Jun 10, 2026
241ded8
Get rid of debug stuff
nycrat Jun 10, 2026
5e61060
Tag TODO for robot localizer
nycrat Jun 10, 2026
8808c2b
Reset some stuff
nycrat Jun 10, 2026
a37fede
WIP
nycrat Jun 10, 2026
9db8d81
Log motion to plot juggler
Thunderbots Jun 10, 2026
72fa828
Use only feedforward for motion controllers
Thunderbots Jun 10, 2026
d65dcda
Formatting
Thunderbots Jun 10, 2026
fa2c6b6
Clamp max speed from motion controllers
Thunderbots Jun 10, 2026
81c039b
Formatting
Thunderbots Jun 10, 2026
c90a6c8
Implement old velocity dampening
nycrat Jun 10, 2026
45d310d
Increase threshold for test
nycrat Jun 10, 2026
e7bb4a3
Rename move tactic test
nycrat Jun 10, 2026
451f856
Comment out linear motion debugging
nycrat Jun 10, 2026
9393179
Revert unused trajectory invalidation code
nycrat Jun 10, 2026
030f74d
Formatting
Thunderbots Jun 10, 2026
6048157
Merge branch 'master' into avah/prim_exec_motion_controller
nycrat Jun 10, 2026
c1fc861
Fix dependency issue
nycrat Jun 10, 2026
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
5 changes: 3 additions & 2 deletions src/proto/message_translation/tbots_protobuf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ BangBangTrajectory1DAngular createAngularTrajectoryFromParams(
return BangBangTrajectory1DAngular(
createAngle(params.start_angle()), createAngle(params.final_angle()),
initial_velocity,
AngularVelocity::fromRadians(robot_constants.robot_max_ang_speed_rad_per_s),
AngularVelocity::fromRadians(
robot_constants.robot_trajectory_max_ang_speed_rad_per_s),
AngularVelocity::fromRadians(
robot_constants.robot_max_ang_acceleration_rad_per_s_2),
AngularVelocity::fromRadians(
Expand Down Expand Up @@ -513,7 +514,7 @@ double convertMaxAllowedSpeedModeToMaxAllowedSpeed(
switch (max_allowed_speed_mode)
{
case TbotsProto::MaxAllowedSpeedMode::PHYSICAL_LIMIT:
return robot_constants.robot_max_speed_m_per_s;
return robot_constants.robot_trajectory_max_speed_m_per_s;
case TbotsProto::MaxAllowedSpeedMode::STOP_COMMAND:
return STOP_COMMAND_ROBOT_MAX_SPEED_METERS_PER_SECOND -
STOP_COMMAND_SPEED_SAFETY_MARGIN_METERS_PER_SECOND;
Expand Down
4 changes: 2 additions & 2 deletions src/proto/message_translation/tbots_protobuf.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,9 @@ std::optional<TrajectoryPath> createTrajectoryPathFromParams(
const robot_constants::RobotConstants& robot_constants);

/**
* Generate an angular trajectory Path given angular trajectory proto parameters
* Generate an angular trajectory path given angular trajectory proto parameters
*
* @param params angular Trajectory Path
* @param params Angular trajectory path
* @param initial_velocity Initial velocity to use for the trajectory
* @param robot_constants Constants to use for the trajectory
* @return Generate angular trajectory
Expand Down
33 changes: 23 additions & 10 deletions src/shared/robot_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ struct RobotConstants
// The maximum speed achievable by our robots, in metres per second [m/s]
float robot_max_speed_m_per_s;

// The maximum speed that the trajectory planner is allowed to command the robot to
// move at, while still leaving headroom for the PID to apply correction on lag. [m/s]
float robot_trajectory_max_speed_m_per_s;

// The maximum acceleration achievable by our robots [m/s^2]
float robot_max_acceleration_m_per_s_2;

Expand All @@ -97,6 +101,11 @@ struct RobotConstants
// The maximum angular speed achievable by our robots [rad/s]
float robot_max_ang_speed_rad_per_s;

// The maximum speed that the trajectory planner is allowed to command the robot to
Comment thread
nycrat marked this conversation as resolved.
// move at, while still leaving headroom for the PID to apply correction on lag.
// [rad/s]
float robot_trajectory_max_ang_speed_rad_per_s;

// The maximum angular acceleration achievable by our robots [rad/s^2]
float robot_max_ang_acceleration_rad_per_s_2;

Expand Down Expand Up @@ -142,13 +151,15 @@ constexpr RobotConstants createRobotConstants()
.motor_max_acceleration_m_per_s_2 = 2.0f,

// Robot's linear movement constants
.robot_max_speed_m_per_s = 3.0f,
.robot_max_acceleration_m_per_s_2 = 3.0f,
.robot_max_deceleration_m_per_s_2 = 3.0f,
.robot_max_speed_m_per_s = 3.0f,
.robot_trajectory_max_speed_m_per_s = 2.5f,
.robot_max_acceleration_m_per_s_2 = 3.0f,
.robot_max_deceleration_m_per_s_2 = 2.0f,

// Robot's angular movement constants
.robot_max_ang_speed_rad_per_s = 10.0f,
.robot_max_ang_acceleration_rad_per_s_2 = 30.0f,
.robot_max_ang_speed_rad_per_s = 10.0f,
.robot_trajectory_max_ang_speed_rad_per_s = 7.0f,
.robot_max_ang_acceleration_rad_per_s_2 = 30.0f,

.wheel_radius_meters = 0.03f,

Expand All @@ -173,13 +184,15 @@ constexpr RobotConstants createRobotConstants()
.motor_max_acceleration_m_per_s_2 = 4.5f,

// Robot's linear movement constants
.robot_max_speed_m_per_s = 3.000f,
.robot_max_acceleration_m_per_s_2 = 3.0f,
.robot_max_deceleration_m_per_s_2 = 3.0f,
.robot_max_speed_m_per_s = 3.000f,
.robot_trajectory_max_speed_m_per_s = 3.000f,
.robot_max_acceleration_m_per_s_2 = 3.0f,
.robot_max_deceleration_m_per_s_2 = 3.0f,

// Robot's angular movement constants
.robot_max_ang_speed_rad_per_s = 10.0f,
.robot_max_ang_acceleration_rad_per_s_2 = 30.0f,
.robot_max_ang_speed_rad_per_s = 10.0f,
.robot_trajectory_max_ang_speed_rad_per_s = 7.0f,
.robot_max_ang_acceleration_rad_per_s_2 = 30.0f,

.wheel_radius_meters = 0.03f};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,9 @@ def setup(*args):
RobotEventuallyAtOrientation(robot_id=1, orientation=pass_orientation),
# Larger threshold since techically ball is at passer point, not the robot
RobotEventuallyAtPosition(
robot_id=1, position=passer_point, threshold=ROBOT_MAX_RADIUS_METERS
robot_id=1,
position=passer_point,
threshold=ROBOT_MAX_RADIUS_METERS * 1.5,
Comment thread
nycrat marked this conversation as resolved.
),
BallEventuallyKickedInDirection(kick_direction=pass_orientation),
]
Expand Down
44 changes: 44 additions & 0 deletions src/software/ai/hl/stp/tactic/move/move_tactic_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,5 +298,49 @@ def setup(*args):
)


def test_move_across_x_axis(simulated_test_runner):
initial_position = tbots_cpp.Point(-4.4, 0)
destination = tbots_cpp.Point(3, 0)

def setup(*args):
simulated_test_runner.set_world_state(
create_world_state(
blue_robot_locations=[
initial_position,
],
yellow_robot_locations=[],
ball_location=tbots_cpp.Point(-3, -3),
ball_velocity=tbots_cpp.Vector(0, 0),
),
)

simulated_test_runner.set_tactics(
blue_tactics={
0: MoveTactic(
destination=tbots_cpp.createPointProto(destination),
final_orientation=tbots_cpp.createAngleProto(
tbots_cpp.Angle.zero()
),
)
}
)

eventually_validation_sequence_set = [
# Robot stays at destination for one second
[
DurationValidation(
duration_s=1, validation=RobotEventuallyAtPosition(0, destination)
)
]
]

simulated_test_runner.run_test(
setup=setup,
inv_eventually_validation_sequence_set=eventually_validation_sequence_set,
ag_eventually_validation_sequence_set=eventually_validation_sequence_set,
test_timeout_s=6,
)


if __name__ == "__main__":
pytest_main(__file__)
2 changes: 2 additions & 0 deletions src/software/embedded/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ cc_library(
"//proto/primitive:primitive_msg_factory",
"//software/ai/navigator/trajectory:bang_bang_trajectory_1d_angular",
"//software/ai/navigator/trajectory:trajectory_path",
"//software/embedded/motion_control:orientation_controller",
"//software/embedded/motion_control:position_controller",
"//software/math:math_functions",
"//software/physics:velocity_conversion_util",
"//software/time:duration",
Expand Down
1 change: 1 addition & 0 deletions src/software/embedded/motion_control/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ cc_library(
":controller",
":pid_controller",
"//software/ai/navigator/trajectory:trajectory_path",
"//software/geom/algorithms",
],
)

Expand Down
2 changes: 2 additions & 0 deletions src/software/embedded/motion_control/controller.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#pragma once

#include "software/time/duration.h"

/**
Expand Down
33 changes: 15 additions & 18 deletions src/software/embedded/motion_control/orientation_controller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,27 @@ AngularVelocity OrientationController::step(
const Angle& orientation, const BangBangTrajectory1DAngular& target_trajectory,
Duration elapsed_time, Duration delta_time)
{
const Angle difference_from_target =
(target_trajectory.getDestination() - orientation).clamp();
// feedforward trajectory angular velocity with small pid control effort
const Angle error_angular =
(target_trajectory.getPosition(elapsed_time.toSeconds()) - orientation).clamp();
const AngularVelocity pid_effort_angular = AngularVelocity::fromRadians(
w_pid_.step(error_angular.toRadians(), delta_time.toSeconds()));

if (difference_from_target.abs().toDegrees() < ANGULAR_PURE_PID_THRESHOLD_DEGREES)
{
// if target orientation is close enough, use pure PID for angular velocity
return AngularVelocity::fromRadians(w_pid_close_.step(
difference_from_target.toRadians(), delta_time.toSeconds()));
}
else
AngularVelocity angular_velocity =
target_trajectory.getVelocity(elapsed_time.toSeconds()) + pid_effort_angular;

const Angle orientation_to_destination =
orientation.minDiff(target_trajectory.getDestination());
// Dampen angular velocity as we get closer to the destination to reduce jittering
if (orientation_to_destination.toDegrees() < ANGULAR_DESTINATION_THRESHOLD_DEGREES)
{
// feedforward trajectory angular velocity with small pid control effort
const Angle error_angular =
(target_trajectory.getPosition(elapsed_time.toSeconds()) - orientation)
.clamp();
const AngularVelocity pid_effort_angular = AngularVelocity::fromRadians(
w_pid_.step(error_angular.toRadians(), delta_time.toSeconds()));
return target_trajectory.getVelocity(elapsed_time.toSeconds()) +
pid_effort_angular;
angular_velocity *= orientation_to_destination.toDegrees() /
ANGULAR_DESTINATION_THRESHOLD_DEGREES;
}
return angular_velocity;
}

void OrientationController::reset()
{
w_pid_.reset();
w_pid_close_.reset();
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ class OrientationController

private:
// TODO(#3737): tune constants
PidController w_pid_{0.7, 0.0, 2.0, 0.0};
PidController w_pid_close_{2.0, 0.0, 4.0, 0.0};
PidController w_pid_{0.4, 0.0, 0.0, 0.0};

static constexpr double ANGULAR_PURE_PID_THRESHOLD_DEGREES = 25.0;
static constexpr double ANGULAR_DESTINATION_THRESHOLD_DEGREES = 5;
};
34 changes: 16 additions & 18 deletions src/software/embedded/motion_control/position_controller.cpp
Original file line number Diff line number Diff line change
@@ -1,34 +1,32 @@
#include "software/embedded/motion_control/position_controller.h"

#include "software/geom/algorithms/distance.h"

Vector PositionController::step(const Point& position,
const TrajectoryPath& target_trajectory,
Duration elapsed_time, Duration delta_time)
{
const Vector distance_from_destination =
target_trajectory.getDestination() - position;
// feedforward trajectory velocity with small pid control effort
const Vector error =
target_trajectory.getPosition(elapsed_time.toSeconds()) - position;
const Vector control_effort{x_pid_.step(error.x(), delta_time.toSeconds()),
y_pid_.step(error.y(), delta_time.toSeconds())};
double distance_to_destination =
distance(position, target_trajectory.getDestination());

if (distance_from_destination.length() < LINEAR_PURE_PID_THRESHOLD_METERS)
{
// if target destination is close enough, use pure PID for velocity
return Vector{
x_pid_close_.step(distance_from_destination.x(), delta_time.toSeconds()),
y_pid_close_.step(distance_from_destination.y(), delta_time.toSeconds())};
}
else
Vector local_velocity =
target_trajectory.getVelocity(elapsed_time.toSeconds()) + control_effort;

// Dampen velocity as we get closer to the destination to reduce jittering
if (distance_to_destination < MAX_DAMPENING_VELOCITY_DISTANCE_M)
{
// feedforward trajectory velocity with small pid control effort
const Vector error =
target_trajectory.getPosition(elapsed_time.toSeconds()) - position;
const Vector control_effort{x_pid_.step(error.x(), delta_time.toSeconds()),
y_pid_.step(error.y(), delta_time.toSeconds())};
return target_trajectory.getVelocity(elapsed_time.toSeconds()) + control_effort;
local_velocity *= distance_to_destination / MAX_DAMPENING_VELOCITY_DISTANCE_M;
}
return local_velocity;
}

void PositionController::reset()
{
x_pid_.reset();
y_pid_.reset();
x_pid_close_.reset();
y_pid_close_.reset();
}
9 changes: 3 additions & 6 deletions src/software/embedded/motion_control/position_controller.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,8 @@ class PositionController : public MotionController<Point, TrajectoryPath, Vector

private:
// TODO(#3737): tune constants
PidController x_pid_{0.8, 0.0, 0.0, 0.0};
PidController y_pid_{0.8, 0.0, 0.0, 0.0};
PidController x_pid_{0.2, 0.0, 0.0, 0.0};
PidController y_pid_{0.2, 0.0, 0.0, 0.0};

PidController x_pid_close_{2.0, 0.0, 0.0, 0.0};
PidController y_pid_close_{2.0, 0.0, 0.0, 0.0};

static constexpr double LINEAR_PURE_PID_THRESHOLD_METERS = 0.5;
static constexpr double MAX_DAMPENING_VELOCITY_DISTANCE_M = 0.05;
};
Loading
Loading