Servo centerNEORACER DOCS
NEORACER DOCS
These docs are public and open source.Edit on GitHub
CALIBRATION / SERVO CENTER

STEERING CENTER.

When you call rc.drive.set_speed_angle(speed, 0) the wheels should point dead ahead. Out of the box they usually lean a touch, because the steering linkage sits a few counts off true center. The fix is a single software trim, and you do not have to guess it: the car measures its own drift with the gyro and lidar, then prints the exact value to set.

~0 minutesconfig/controller.yamlEdit + restart
FIG. A / STEERING RANGE, TOP DOWN
−1.0 left lock0.0 center+1.0 right lockFORWARDGOALset_speed_angle(_, 0) ⇒ straight
The angle in rc.drive.set_speed_angle maps −1 → full left, 0 → straight, +1 → full right. Centering pins the 0 to true-straight on your specific car.
01 / HOW IT WORKS

HOW IT WORKS.

Your steering angle is normalized in the range [-1, 1] all the way through the drive pipeline. The controller node writes the per-tick command v <m/s> <deg> over USB-CDC to the ESP32, where the angle in degrees is what the servo eventually sees. Before that send, the controller adds one YAML value, steering_trim_deg, from config/controller.yaml. That value starts at 0.0. Nudge it a degree or two and the wheels at zero angle shift with it.

02 / YOU'LL NEED

WHAT YOU NEED.

01

A straight line

Painter's tape on hardwood.
A metre of painter's tape on a flat floor is the test track. Carpet will not tell you whether a drift came from steering or from wheel slip.
02

Motor checked first

It comes before this page.
A car that creeps at zero speed will fight the roll test, so settle motor trim first, then center the steering.
03

SSH to the Jetson

Where the YAML lives.
The trim is one line in config/controller.yaml on the car. You edit it over SSH, covered in Networking.
ssh racecar@neoracer
FIG. B / FIVE STEPS, START TO FINISH
1
$_
SSH in
to the Jetson
2
Park it
facing a wall, 2 to 6 m
3
Run the lab
lab_trim_cal.py
4
Paste two lines
it prints the commands
5
Rerun
until it says CALIBRATED
Run the calibration lab, paste the two commands it prints, and run it again. Two or three passes lands within a degree, and the lab tells you when to stop.
03 / THE PROCEDURE

THE PROCEDURE.

bash
# 1. SSH into the Jetson and park the car facing a wall, 2 to 6 m of clear floor. ssh racecar@neoracer # 2. Run the calibration lab. Flip the transmitter to autonomy when it says so. cd ~/jupyter_ws/neoracer-os/labs python3 lab_trim_cal.py # The car drives straight for up to three seconds, measures its heading drift # with the gyro and the distance with the front lidar, then prints: # # current steering_trim_deg: +1.0 measured correction: -2.6 # # === RUN THESE TWO COMMANDS, THEN RERUN ME === # # sed -i -E 's/steering_trim_deg: *-?[0-9.]+/steering_trim_deg: -1.6/' # ~/ros2_ws/install/neoracer_ros2_driver/share/neoracer_ros2_driver/config/controller.yaml # ~/ros2_ws/src/neoracer_ros2_driver/neoracer_ros2_driver/config/controller.yaml # sudo systemctl restart neoracer-teleop # 3. Paste those two commands, then run the lab again. # Repeat until it prints === CALIBRATED === (usually two or three passes).
04 / VERIFY

VERIFY THE CENTER.

No tools handy, or want a second opinion? This holds the servo at center and the motor at zero so you can roll the car by hand along a metre of tape and watch the drift:

python
import racecar_core rc = racecar_core.create_racecar() HOLD_S = 8.0 timer = 0.0 def start(): global timer timer = 0.0 rc.drive.set_speed_angle(0, 0) print("Servo verify: holding straight, push the car 1 m along the tape") def update(): global timer timer += rc.get_delta_time() rc.drive.set_speed_angle(0, 0) # motor at zero, servo centered if timer > HOLD_S: rc.drive.stop() rc.set_start_update(start, update) rc.go()

A pass is finishing within a wheel's width of the line after a metre. A bigger gap means another nudge to the offset and a rebuild.

05 / WHERE IT LIVES

WHERE IT LIVES.

The trim is a YAML value the controller node reads on launch, so a teleop restart is what applies it. There is no colcon build to wait on. The commands the lab prints edit both copies of controller.yaml, the installed one the car runs and the source one, so the value survives a rebuild.

yaml
# ~/ros2_ws/src/neoracer_ros2_driver/neoracer_ros2_driver/config/controller.yaml controller_node: ros__parameters: port_name: /dev/osrbot_base max_speed_mps: 6.0 max_steering_angle_deg: 30.0 steering_trim_deg: 0.0 # your trim, in degrees; positive steers left throttle_channel: 2 steering_channel: 0 mode_channel: 4
  • A positive steering_trim_deg steers the zero-angle wheels left, a negative one right. The calibration lab handles the sign for you.
  • The top-speed cap is max_speed_mps on the same file; leave it alone if you only meant to trim the steering.
  • Every script that sends a steering angle of 0 now points true ahead, no per-program tweak needed.