Lab 3: NXP Cup Autonomous Car

Duration

2 hours:

  • 0h30 theoretical introduction to NXP Cup, vehicle dynamics, and PID control;
  • 1h30 practical tuning and modular firmware development.

Learning Objectives

After this laboratory, students should be able to:

  • Explain the data flow in an autonomous line-follower (sensors, control, actuators);
  • Describe the role of Proportional, Integral, and Derivative terms in a PID controller;
  • Tune a PID controller experimentally on physical or emulated hardware;
  • Implement and validate coordinate mapping algorithms for line tracking camera sensors;
  • Map abstract controller commands to physical servo PWM pulse widths.

Laboratory Scenario

The lab focuses on programming and tuning an autonomous line-following vehicle. The system utilizes a PixyCam2 camera for line detection, a PID controller for trajectory correction, and a steering servomotor.

``` [PixyCam2 Camera] → vector path → [Error Estimator (Ex 2)] → error → [PID Controller] → output → [Servo Command (Ex 3)] → PWM → [Steering Servo] ```

In each control loop iteration, the vehicle executes the following sequence:

1. Read the path vectors reported by PixyCam2.
2. Estimate the lateral steering error from the detected vector.
3. Compute the tracking error: error = 0.0f - estimated_error.
4. Apply the PID control algorithm to the tracking error.
5. Map the PID controller output to a physical servo command.
6. Adjust the motor speed profile based on path curvature and stability.
7. Write commands to the actuators (servo and ESC).
8. Wait for the next control cycle.

The vehicle does not know the track geometry in advance; it reacts dynamically to real-time measurements. If the line shifts left, it steers left; if it shifts right, it steers right; if the line is centered, the wheels remain straight.

Equipment Overview: The NXP Cup Platform

An NXP Cup autonomous vehicle consists of the following primary components:

Component Role Practical Engineering Challenges
Microcontroller Runs the real-time control loop sampling frequency, latency, memory constraints
PixyCam2 Detects path vectors in the image frame calibration, ambient light, lost vectors, intersections
Steering Servo Controls the front wheel angle mechanical limits, saturation, non-linear response
Motor / ESC Drives the vehicle's propulsion inertia, wheel slippage, current limits, battery sag
Encoder Measures real-time wheel speed missing pulses, quantization noise, sampling delay
Battery Powers the logic board and motors voltage drops, performance degradation under load

Controller Theory: PID

The PID controller computes the steering adjustment using three distinct terms:

Term Conceptual Formula Physical Effect
P - Proportional proportional to current error reacts quickly to immediate deviations from the line
I - Integral accumulates error over time corrects persistent steady-state offsets
D - Derivative proportional to error rate-of-change dampens overshoot and suppresses oscillations

The discrete implementation used in the vehicle firmware is:

integral = integral + error * dt;
derivative = (error - previous_error) / dt;
output = kp * error + ki * integral + kd * derivative;
previous_error = error;

After computing the output, it is saturated to the safety limits of the steering servo:

if (output > max_output) output = max_output;
if (output < min_output) output = min_output;

Project Layout

The workspace is organized into three functional directories:

  • pid_tuning/ — PlatformIO project for configuring and flashing the physical vehicle.
    • platformio.ini: PlatformIO configuration file.
    • src/configpid.cpp: Source file where you edit your vehicle's PID gains ($K_p$, $K_i$, $K_d$).
    • lib/libnxpcar.a: Precompiled static library containing the vehicle's core autonomous driving logic.
  • exercise2_pixy_vector/ — Coordinate mapping and error estimation.
    • pixy_vector.c / .h: Student implementation file and interface.
    • test_pixy_vector.o: Precompiled local unit test suite object.
  • exercise3_steering/ — Steering actuator command conversion.
    • steering.c / .h: Student implementation file and interface.
    • test_steering.o: Precompiled local unit test suite object.
  • test_runner — Precompiled interactive test runner TUI dashboard executable.
  • Makefile — Compiles and links student implementations with precompiled test objects (via make test).

Students do not need to modify the full vehicle firmware. You will implement and validate the core modules locally, write your PID gains in the configuration file, and flash the precompiled vehicle firmware.

Exercise 1: Steering PID Controller Flashing & Tuning

Objective

Tune the steering PID gains ($K_p$, $K_i$, $K_d$) of the physical vehicle by editing the configuration file, compiling, and flashing the firmware onto the Teensy 4.1 using PlatformIO.

Materials

  • The student skeleton PlatformIO project inside pid_tuning/;
  • A Teensy 4.1 microcontroller on the NXP Cup Car;
  • A USB-micro cable to connect the Teensy to your laptop.

Procedure

1. Open the ''pid_tuning/'' directory in VS Code (make sure the **PlatformIO IDE** extension is installed).
2. Open ''src/configpid.cpp'' and set your desired PID gains (do not modify the `extern` keyword as it is required to link with the precompiled library):
   <code c>
   extern const float STEER_KP = 1.8f;
   extern const float STEER_KI = 0.00f;
   extern const float STEER_KD = 0.20f;
   </code>
3. Connect the Teensy 4.1 on your vehicle to your computer via USB.
4. Build and flash the project:
   - In VS Code, click the **PlatformIO: Upload** button (arrow icon at the bottom status bar), or
   - Open a terminal inside the ''pid_tuning/'' folder and run:
     <code bash>
     pio run -t upload
     </code>
   - PlatformIO will automatically compile your ''configpid.cpp'', link it against the precompiled static library ''lib/libnxpcar.a'', and upload the complete firmware to the vehicle!
5. Disconnect the USB cable, place the vehicle on the track, and turn on the power switch to observe its behavior.
6. To adjust the gains, turn off the vehicle, reconnect the Teensy to your laptop via USB, edit the values in ''src/configpid.cpp'', and re-flash.
7. Start with the integral term disabled (''ki = 0.00'').
8. Increase the proportional gain ''kp'' progressively (e.g., in steps of 0.2) until the car follows the line, but starts to oscillate left-and-right around the center.
9. Increase the derivative gain ''kd'' to dampen the oscillations and smooth the vehicle's trajectory.
10. Record your experimental runs in the table below.

Tuning Recommendations

  • One Parameter at a Time: Alter only a single PID gain parameter between experimental runs to isolate the physical effect of each gain.
  • Safety First: Start testing with the vehicle on a stand or at low speeds before attempting high-speed runs to prevent physical damage to the vehicle.
  • Handling Oscillations: If the vehicle exhibits high-frequency oscillations (wiggling), decrease kp or slightly increase kd.
  • Handling Sluggishness: If the vehicle reacts too slowly to curves and drifts wide, increase kp.
  • Handling Curve Instability: If the vehicle flies off the track in sharp turns, check if the steering controller gains need further tuning or if the track requires lower speed limits.

Telemetry & Diagnostics over USB Serial

The Teensy car code automatically streams real-time CSV telemetry data over the USB Serial interface (at 115200 baud). If you plug the USB cable while the car is on a stand and open the PlatformIO Serial Monitor, you can observe the real-time CSV output:

CSV format: time,state,vecs,side,lat,heading,curv,conf,steer,motor,dt

This is useful for verifying that the camera sees the track and the steering controller reacts correctly.

Test the vehicle on the track and document your findings:

Run Kp Ki Kd Observations
1
2
3
4

Questions & Observations

  • What physical behavior is observed when kp is too low?
  • What physical behavior is observed when kp is too high?
  • How does the vehicle's trajectory change as you increase kd?
  • Was an integral term ki necessary for stable tracking? Explain why.

Exercise 2: PixyCam2 Vector Error Estimation

Objective

Implement a C function that parses a raw tracking vector from PixyCam2 and returns a normalized steering error relative to the image frame center.

Theoretical Context

The PixyCam2 reports line tracking vectors in image coordinates. The $x$ coordinate increases from left to right, and the $y$ coordinate increases from top to bottom. To determine the immediate direction of the path, you must track the endpoint of the vector that is closest to the front of the car (the bottom of the image frame, which corresponds to the larger $y$ coordinate).

  • If $y_0 > y_1$, use $x_0$.
  • If $y_1 > y_0$, use $x_1$.
  • If the vector is horizontal ($y_0 == y_1$), use the average of $x_0$ and $x_1$.

The function must return a normalized error in the range [-1.0, 1.0]:

  • -1.0 represents the far-left edge of the frame;
  • 0.0 represents the exact center of the frame;
  • 1.0 represents the far-right edge of the frame.

If the input frame_width ⇐ 1, return 0.0f. Clamp the selected $x$ coordinate to the valid image boundaries $[0, \text{frame\_width} - 1]$ before normalization.

Students should derive a linear scaling formula to map the clamped $x$ coordinate from the pixel space $[0, \text{frame\_width} - 1]$ to the normalized target space $[-1.0, 1.0]$.

Examples for frame_width = 79

Vector Result Explanation
{39, 0, 39, 51} 0.0 Bottom endpoint is exactly in the center
{39, 0, 0, 51} -1.0 Bottom endpoint is at the far-left edge
{39, 0, 78, 51} 1.0 Bottom endpoint is at the far-right edge
{39, 0, 52, 51} approx. 0.333 Bottom endpoint is slightly to the right
{20, 20, 58, 20} 0.0 Horizontal vector: uses average x

Interface

Implement the function in exercise2_pixy_vector/pixy_vector.c:

typedef struct {
    int x0;
    int y0;
    int x1;
    int y1;
} PixyVector;
 
float estimate_pixy_vector_error(PixyVector vector, int frame_width);

Local Validation

Compile and run the local unit tests from the workspace:

cd nxp_car_lab_skeleton
make test-pixy

Exercise 3: Servo Command Conversion

Objective

Implement a C function to map the abstract floating-point PID controller output to a physical PWM pulse width in microseconds for the steering servomotor.

Theoretical Context

The PID controller produces an abstract output intended to represent steering direction. The function must:

1. Clamp the input `pid_output` to the safe operating range of ''[-1.0, 1.0]'', where ''-1.0'' represents maximum left steer and ''1.0'' represents maximum right steer.
2. Map this clamped value linearly to a standard servo PWM pulse width in the range ''[1000, 2000]'' microseconds, where ''1500'' microseconds represents the center position (wheels straight).

Students should derive a linear conversion formula that maps the clamped PID steering command from $[-1.0, 1.0]$ to the physical servo PWM pulse width range $[1000, 2000]$ microseconds.

Examples

pid_output Expected PWM (us)
-1.0 1000
-0.5 1250
0.0 1500
0.5 1750
1.0 2000
2.0 2000 (clamped)
-2.0 1000 (clamped)

Interface

Implement the function in exercise3_steering/steering.c:

int pid_output_to_servo_us(float pid_output);

Local Validation

Compile and run the local unit tests:

cd nxp_car_lab_skeleton
make test-steering

Deliverables

Upon completion of the laboratory, submit the following:

  • Your final tuned PID parameters (Kp, Ki, Kd) documented in your report;
  • Written answers to the theoretical questions in Exercise 1;
  • Your C implementations for exercise2_pixy_vector/pixy_vector.c and exercise3_steering/steering.c;

Grading Criteria

Component Percentage
PID tuning analysis and track characterization 30%
Functional PID parameters on the physical track 25%
Exercise 2: PixyCam2 error estimation implementation 20%
Exercise 3: Servo command conversion implementation 15%
Code cleanliness, proper clamping, and local validation 10%

General Recommendations

  • Local Validation: Always verify your code implementations using the local test suites (make test) before deploying or tuning.
  • Code Quality: Write clean, self-documenting code, handle all safety clamping, and consider extreme edge cases (such as negative or zero frame width).
rasb/lab/03.txt · Last modified: 2026/06/30 14:48 by rares.sarmasag
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0