Before running an autonomous path, Odyssey needs four feedforward constants (Documentation Index
Fetch the complete documentation index at: https://mintlify.com/saquer916/odyssey/llms.txt
Use this file to discover all available pages before exploring further.
kS, kV, kA) and two PID controllers tuned to your specific robot. The constants live in MecanumDrive; the PID gains are passed to the Follower constructor. Follow the steps below in order — each step builds on the results of the previous one.
Tune kS — static friction coefficient
kS is the minimum normalised motor power required to overcome static friction and begin moving. MecanumDrive adds kS * Math.signum(velocity) to every wheel before scaling by kV and kA, ensuring the motors always have enough power to break away from rest.Procedure — use StaticCoefficientOpMode:The StaticCoefficientOpMode TeleOp ramps power from 0.0 to 0.4 in 0.1 increments. At each step it drives all four wheels for 2 000 ms, reads the forward velocity from the Pinpoint localizer (localizer.getVelX(DistanceUnit.MM)), logs the result, then rests for 2 000 ms before moving to the next step.- Deploy the OpMode and run it on a flat surface.
-
Watch the telemetry log. You will see lines like:
-
Find the first power level at which the velocity is non-zero — that is your
kS. In the example above,kS ≈ 0.2.
Run this test on the same carpet surface you will use for the match. Static friction is higher on carpet than on smooth tile.
Tune kV — velocity feedforward
kV converts a target wheel velocity (mm/s) into a normalised motor power. It is defined as the reciprocal of the robot’s steady-state velocity at full power:- Run the robot in a straight line at full motor power (
1.0) for at least 2 000 mm. - Read the steady-state forward velocity from
PinpointLocalizertelemetry once acceleration has plateaued. - Divide
1by that velocity.
1 250 mm/s at full power:kV means the robot reaches the path’s target velocity without the translational PID needing to compensate for a persistent speed error.Tune kA — acceleration feedforward
kA scales the tangential and centripetal acceleration components from the VelocityProfile into additional motor power. Start at kA = 0 and increase incrementally.Signs of under-tuned kA (too low):- The robot lags behind the profile at the start of the path and takes time to reach target velocity.
- The robot coasts past the endpoint because braking power is insufficient.
- The robot jerks at path start or oscillates as acceleration commands change sign.
- Wheel slip on carpet.
kA by 0.0001 at a time and re-run a straight-line path until the robot accelerates and decelerates crisply without overshoot.Tune the translational PID
The translational Procedure:
PIDController corrects the robot’s lateral offset from the nearest point on the path. Its setpoint is always 0; the input is the negative magnitude of the position error vector.Start with kI = 0 throughout. Integral gain is rarely needed for path following and causes wind-up if the robot is held off the path at the start.- Set
kD_trans = 0. IncreasekP_transfrom0until the robot tracks the path cleanly without significant overshoot. - If the robot oscillates around the path, add a small
kD_trans(start atkP_trans / 10) to damp the oscillation. - Re-run until lateral error is consistently less than ~15 mm on a sweeping curve.
PIDController exposes setOutputLimits(min, max) and setMaxIntegral(value). If you do enable kI, always call setMaxIntegral() to prevent the integral term from winding up during a long stall at path start.Tune the heading PID
The heading Procedure:
PIDController corrects the angle error between the reference heading (from the HeadingInterpolator) and the robot’s actual heading. Setpoint is 0; error is −normalizeAngle(referenceHeading − poseHeading).- Run a path with
LinearInterpolatorso the robot must rotate while driving. - Set
kD_head = 0. IncreasekP_headuntil the robot reaches its target heading quickly without overshooting. - If the robot oscillates through the target heading, add
kD_head.
kP_head = 1.0 – 3.0.Common issues
Robot oscillates on straight segments
Robot oscillates on straight segments
The translational PID gain is too aggressive relative to the feedforward. Try lowering
kP_trans by 20 % or adding kD_trans if not already set. Also verify that kV is correct — a persistent velocity error forces the translational PID to do extra work.Robot undershoots or overshoots the endpoint
Robot undershoots or overshoots the endpoint
The braking profile is not matched to the robot’s actual deceleration capability. Increase
maxBrake in the VelocityProfile constructor to command stronger deceleration, which gives the profile more headroom to stop in time. If the robot still overshoots, kA may be too high — reduce it slightly.Robot spins instead of driving straight
Robot spins instead of driving straight
The right-side motor direction is incorrect.
MecanumDrive sets rightFront and rightBack to Direction.REVERSE by default for a standard symmetric FTC chassis. If your chassis mounts the right-side motors the other way, change those two motors to Direction.FORWARD in your MecanumDrive constructor call.Robot stalls briefly at the start of a path
Robot stalls briefly at the start of a path
The
VelocityProfile ramps up from zero, and at very low profile velocities the feedforward alone may not overcome static friction. Increase minDriveSpeed in the Follower constructor — for example from 50.0 to 80.0 mm/s — to add a speed floor while the robot is still far from the end. Make sure kS is also correctly tuned so the static friction term is applied.Robot drifts on curved segments
Robot drifts on curved segments
Centripetal acceleration feedforward is handled automatically by the
Follower using path.getCurvatureFromPathDistance() and path.getCentripetalVectorPath(). If the robot still drifts outward, try increasing maxCentripetalAccel in the VelocityProfile so the profile slows down more aggressively before tight curves.