Differences

This shows you the differences between two versions of the page.

Link to this comparison view

rasb:lab:03 [2026/06/20 23:58]
cezar.zlatea
rasb:lab:03 [2026/06/30 14:48] (current)
rares.sarmasag [Lab 3: NXP Cup Autonomous Car]
Line 1: Line 1:
-===== Lab 3: Renode for MCU Emulation and Validation ​===== +====== Lab 3: NXP Cup Autonomous Car ====== 
 +{{:​rasb:​lab:​nxpcar-lab.zip|Lab 3 skel}}
 ===== Duration ===== ===== Duration =====
  
-hours: +hours: 
- +  * 0h30 theoretical ​introduction to NXP Cup, vehicle dynamics, ​and PID control
-  * 1h30 guided ​introduction to Renode ​and the digital-twin workflow+  * 1h30 practical ​tuning and modular ​firmware ​development.
-  * 1h30 practical firmware ​exercise using a virtual sensor stream.+
  
 ===== Learning Objectives ===== ===== Learning Objectives =====
  
 After this laboratory, students should be able to: After this laboratory, students should be able to:
- +  ​Explain ​the data flow in an autonomous line-follower (sensors, control, actuators)
-  ​explain ​the role of Renode ​in embedded firmware development and testing+  * Describe the role of Proportional,​ Integral, ​and Derivative terms in a PID controller
-  * distinguish between ''​.resc''​ Renode scripts ​and ''​.repl''​ platform descriptions;​ +  * Tune PID controller experimentally on physical or emulated ​hardware
-  * run Raspberry Pi Pico firmware ​in Renode without physical hardware+  * Implement ​and validate coordinate mapping algorithms for line tracking camera sensors
-  * attach ​custom virtual I2C peripheral to an emulated ​board+  * Map abstract controller commands to physical servo PWM pulse widths.
-  * validate firmware behavior through UART output ​and generated reports+
-  * implement and compare a naive threshold filter with a tiny fixed-point model.+
  
 ===== Laboratory Scenario ===== ===== Laboratory Scenario =====
  
-The lab uses Raspberry Pi Pico firmware project running in Renode digital +The lab focuses on programming and tuning an autonomous line-following vehicle. The system utilizes ​PixyCam2 camera for line detection, ​PID controller for trajectory correction, and a steering servomotor.
-twin. Renode provides the RP2040 board model, UART capture, and a deterministic +
-virtual I2C sensor. No physical Pico board or sensor is required.+
  
-<​code>​ +``` 
-[Virtual I2C sensor @ 0x52] -> sample stream ​-> [RP2040 firmware] +[PixyCam2 Camera] -> vector path -> [Error Estimator (Ex 2)-error -> [PID Controller] ​-> output ​-> [Servo Command (Ex 3)] -> PWM -> [Steering Servo] 
-</code> +```
- +
-Each virtual sensor sample contains: +
- +
-  * ''​seq'':​ sample number; +
-  * ''​value'':​ signed sensor reading. +
- +
-The firmware must classify every sample with two methods: +
- +
-  * **Threshold filter**: simple hand-written ''​if''/''​else''​ logic using minimum value, maximum value, and maximum jump thresholds. +
-  * **TinyML-style filter**: a small fixed-point linear model using weights from ''​firmware/​model_weights.h''​. +
- +
-The goal is not to train a model during the lab. The model weights are already +
-provided. Students focus on running firmware in a digital twin, reading the +
-virtual sensor, implementing the inference formula, and comparing the two +
-filtering methods. +
- +
-===== Project Layout ===== +
- +
-The important files are:+
  
-<​code>​ +In each control loop iteration, the vehicle executes the following sequence: 
-firmware/​main.+<​code ​text
-firmware/​model_weights.h +1Read the path vectors reported by PixyCam2
-renode/​run_test.resc +2Estimate the lateral steering error from the detected vector
-renode/​run_metrics.resc +3Compute the tracking error: error = 0.0f - estimated_error
-renode/​sensor_i2c.repl +4Apply the PID control algorithm to the tracking error
-renode/​peripherals/​VirtualSensorStream.cs +5. Map the PID controller output to a physical servo command
-docker/​scripts/​build_firmware.sh +6. Adjust the motor speed profile based on path curvature and stability
-docker/​scripts/​run_test.sh +7. Write commands to the actuators (servo and ESC)
-docker/​scripts/​generate_report.py +8. Wait for the next control cycle.
-docs/​renode_primer.md +
-docs/​exercise_guide.md +
-reference/​firmware/​main.c +
-output/​report.html+
 </​code>​ </​code>​
  
-Short description:​+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.
  
-  * ''​firmware/​main.c''​ contains the student TODOs. +===== Equipment Overview: The NXP Cup Platform =====
-  * ''​firmware/​model_weights.h''​ contains the fixed-point model constants. +
-  * ''​renode/​run_test.resc''​ creates the Renode scenario, loads firmware, and captures UART output. +
-  * ''​renode/​sensor_i2c.repl''​ connects the virtual sensor to the Pico I2C bus. +
-  * ''​renode/​peripherals/​VirtualSensorStream.cs''​ implements the deterministic I2C sensor stream. +
-  * ''​docker/​scripts/​run_test.sh''​ validates the UART output and final summary. +
-  * ''​docker/​scripts/​generate_report.py''​ creates ''​output/​report.html''​. +
-  * ''​reference/​firmware/​main.c''​ contains the completed instructor reference implementation.+
  
-===== Part 1Renode Theory =====+An NXP Cup autonomous vehicle consists of the following primary components:
  
-==== What Renode Is ====+^ 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 |
  
-Renode is an emulator for embedded systems. It can run firmware built for a +===== Controller Theory: PID =====
-microcontroller or SoC inside a virtual machine that includes CPUs, buses, +
-memories, UARTs, timers, and peripherals.+
  
-For this laboratory, Renode gives us a repeatable digital twin:+The PID controller computes the steering adjustment using three distinct terms:
  
-  * the same Pico firmware is loaded every run; +^ Term ^ Conceptual Formula ^ Physical Effect ^ 
-  ​* ​the same deterministic virtual sensor samples are produced every run; +| P - Proportional | proportional to current error | reacts quickly to immediate deviations from the line | 
-  * the same validation script checks the UART output every run.+| I - Integral | accumulates error over time | corrects persistent steady-state offsets | 
 +| D - Derivative | proportional to error rate-of-change | dampens overshoot and suppresses oscillations |
  
-This makes the exercise independent of physical boards, USB cables, sensor +The discrete implementation used in the vehicle ​firmware ​is
-availability,​ and lab hardware differences. +<code c> 
- +integral = integral + error * dt; 
-==== Digital Twin Mental Model ==== +derivative = (error ​previous_error) ​dt; 
- +output = kp * error + ki * integral + kd * derivative;​ 
-A Renode lab scenario has three layers: +previous_error = error;
- +
-  * firmware: ​the compiled application,​ here ''​firmware.elf'';​ +
-  * virtual hardware: the Raspberry Pi Pico plus a custom I2C sensor; +
-  * automation: the ''​.resc''​ script that creates, wires, runs, and observes the machine. +
- +
-In this lab: +
- +
-<code+
-firmware/​main.                     -compiled to firmware.elf +
-renode/​peripherals/​VirtualSensorStream.cs ​-> custom I2C peripheral +
-renode/sensor_i2c.repl ​              -> virtual wiring overlay +
-renode/​run_test.resc ​                -> Renode automation script+
 </​code>​ </​code>​
  
-==== RESC Files ==== +After computing ​the output, it is saturated to the safety limits of the steering servo
- +<​code ​c
-''​.resc''​ files are Renode monitor scripts. They automate what an instructor +if (output > max_output) output = max_output; 
-could otherwise type manually in the Renode monitor. +if (output < min_output) ​output ​= min_output;
- +
-The lab script ​is ''​renode/​run_test.resc''​. It performs these jobs: +
- +
-  * makes the RP2040 Renode support visible; +
-  * loads the custom C# sensor peripheral;​ +
-  * creates a Raspberry Pi Pico machine; +
-  * applies the I2C wiring overlay; +
-  * loads the compiled firmware; +
-  * captures UART output; +
-  * runs the emulation for a fixed time. +
- +
-Typical commands in this scenario: +
- +
-<​code>​ +
-path add @/​opt/​renode-rp2040 +
-include @/​workspace/​renode/​peripherals/​VirtualSensorStream.cs +
-EnsureTypeIsLoaded "​Antmicro.Renode.Peripherals.I2C.VirtualSensorStream"​ +
-include @boards/​initialize_raspberry_pico.resc +
-machine LoadPlatformDescription @/​workspace/​renode/​sensor_i2c.repl +
-sysbus LoadELF @/​workspace/​build/​firmware.elf +
-sysbus.uart0 CreateFileBackend @/​workspace/​output/​uart_output.txt true +
-emulation RunFor "​00:​00:​05"​+
 </​code>​ </​code>​
  
-Key idea: ''​.resc''​ files describe the experiment procedure.+===== Project Layout =====
  
-==== REPL Files ====+The workspace is organized into three functional directories:​
  
-''​.repl'' ​files describe platform topologywhich peripherals exist and where +  * **''​pid_tuning/''​** — PlatformIO project for configuring and flashing the physical vehicle. 
-they are connected.+    * ''​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''​).
  
-This lab uses a small overlay instead of redefining ​the whole Pico:+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.
  
-<​code>​ +---
-sensor: I2C.VirtualSensorStream @ i2c0 0x52 +
-</​code>​+
  
-Read it as:+===== Exercise 1Steering PID Controller Flashing & Tuning =====
  
-  * create a peripheral instance named ''​sensor'';​ +==== Objective ==== 
-  * instantiate ​the Renode type ''​I2C.VirtualSensorStream'';​ +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.
-  * attach it to bus ''​i2c0'';​ +
-  * expose it at I2C address ''​0x52''​.+
  
-Key idea: ''​.repl'' ​files describe ​the virtual wires.+==== 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.
  
-==== Custom Virtual Peripheral ​====+==== 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.
  
-''​VirtualSensorStream.cs'' ​is a minimal Renode I2C peripheralIt models only +==== Tuning Recommendations ==== 
-the behavior needed by this lab:+  * **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.
  
-  * firmware writes register ''​0x00'';​ +==== Telemetry & Diagnostics over USB Serial ==== 
-  * firmware reads four bytes; +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 stand and open the PlatformIO Serial Monitor, you can observe the real-time CSV output
-  * the sensor returns a frame: ''​seq:​uint16_be''​ and ''​value:​int16_be'';​ +<​code ​text
-  * each complete frame advances to the next sample. +CSV format: time,​state,​vecs,​side,​lat,​heading,​curv,​conf,​steer,​motor,​dt
- +
-The component implements ​the Renode I2C peripheral ​interface. ​It is intentionally +
-not complete ​real sensor. For this exercise, deterministic behavior is more +
-important than detailed physical realism. +
- +
-The virtual wiring path is: +
- +
-<​code>​ +
-run_test.resc +
-  loads VirtualSensorStream.cs +
-  initializes Raspberry Pi Pico +
-  applies sensor_i2c.repl +
- +
-sensor_i2c.repl +
-  connects VirtualSensorStream to i2c0 address 0x52 +
- +
-firmware/​main.c +
-  initializes i2c0 on the Pico pins +
-  writes register 0x00 +
-  reads 4-byte sample frames+
 </​code>​ </​code>​
 +This is useful for verifying that the camera sees the track and the steering controller reacts correctly.
  
-==== Validation Surface ====+Test the vehicle on the track and document your findings:
  
-The validation harness does not inspect C variables directly. It checks the +^ Run ^ Kp ^ Ki ^ Kd ^ Observations ^ 
-observable firmware behavior through UART output.+| 1 | | | | | 
 +| 2 | | | | | 
 +| 3 | | | | | 
 +| 4 | | | | |
  
-Important UART lines:+==== 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.
  
-<​code>​ +---
-SAMPLE seq=... value=... +
-THRESHOLD seq=... decision=... +
-MODEL seq=... decision=... score=... +
-DISAGREE seq=... +
-SUMMARY threshold_keep=... threshold_drop=... model_keep=... model_drop=... disagreements=... +
-</​code>​+
  
-This is close to a real board workflowthe observable interface is serial +===== Exercise 2PixyCam2 Vector Error Estimation =====
-output plus emulator logs and generated reports.+
  
-===== Part 2: Running The Starter =====+==== 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.
  
-From the browser IDEpress **Run** in the side panel.+==== 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 pathyou 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$.
  
-From shell:+The function must return ​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.
  
-<code bash> +If the input ''​frame_width ​<= 1'',​ return ''​0.0f''​. 
-./run.sh up --build digital-twin +Clamp the selected $x$ coordinate to the valid image boundaries $[0, \text{frame\_width} ​1]$ before normalization.
-</​code>​+
  
-The starter code should ​build and read the sensor stream. The filter checks fail +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]$.
-until students implement ​the TODO functions.+
  
-Expected final passing summary after implementation:​ 
  
-<​code>​ +==== Examples for frame_width = 79 ====
-SUMMARY threshold_keep=8 threshold_drop=2 model_keep=6 model_drop=4 disagreements=+
->>>​ ALL CHECKS PASSED - sensor filters behave as expected <<<​ +
-</​code>​+
  
-The HTML report is written to: +Vector ​Result ​Explanation ​
- +''​{39, ​0, 39, 51}'' ​''​0.0'' ​| Bottom endpoint is exactly in the center | 
-<​code>​ +''​{39, 0, 0, 51}'' ​''​-1.0'' ​| Bottom endpoint ​is at the far-left edge | 
-output/​report.html +''​{39, 0, 78, 51}'' ​''​1.0'' ​| Bottom endpoint is at the far-right edge | 
-</​code>​ +''​{39, 0, 52, 51}'' ​| approx. ''​0.333''​ | Bottom endpoint is slightly ​to the right 
- +''​{20,​ 20, 58, 20}'' ​| ''​0.0'' ​| Horizontal vectoruses average x |
-===== Part 3: Exercise Data ===== +
- +
-The virtual sensor emits this deterministic stream: +
- +
-Seq Value Intended role +
-| 0 | 500 | normal baseline | +
-| 1 | 506 | small normal movement | +
-| 2 | 612 | borderline jump | +
-| 3 | 520 | return to normal | +
-| 4 | 785 | high outlier | +
-| 5 | 532 | normal | +
-| 6 | 340 | low outlier | +
-| 7 | 650 | borderline jump | +
-| 8 | 545 | normal | +
-| 9 | 498 | normal | +
- +
-The threshold filter should reject only the gross high and low outliers: +
- +
-<​code>​ +
-seq=4 +
-seq=6 +
-</​code>​ +
- +
-The tiny model should reject the two gross outliers and two borderline jumps: +
- +
-<​code>​ +
-seq=2 +
-seq=4 +
-seq=6 +
-seq=7 +
-</​code>​ +
- +
-Thereforethe two methods disagree at: +
- +
-<​code>​ +
-seq=2 +
-seq=7 +
-</​code>​ +
- +
-===== Part 4: Exercises ===== +
- +
-==== Exercise 1: Identify The Renode Scenario ==== +
- +
-Open ''​renode/​run_test.resc''​. +
- +
-Tasks: +
- +
-  - Find the command that loads ''​VirtualSensorStream.cs''​. +
-  - Find the command that initializes the Raspberry Pi Pico machine. +
-  - Find the command that applies ​''​sensor_i2c.repl''​+
-  - Find the command that loads ''​firmware.elf''​+
-  - Find where UART output ​is written. +
- +
-Questions:​ +
- +
-  - Which file describes ​the virtual sensor wiring? +
-  ​Which bus is the sensor attached to? +
-  - What I2C address does the sensor use? +
-  - Which output file contains firmware UART logs? +
- +
-Expected answers: +
- +
-  * wiring file: ''​renode/​sensor_i2c.repl''​+
-  * bus: ''​i2c0'';​ +
-  * I2C address: ''​0x52'';​ +
-  * UART output: ''/​workspace/​output/​uart_output.txt''​+
- +
-==== Exercise 2: Follow One Sensor Sample End To End ==== +
- +
-Files to inspect: +
- +
-<​code>​ +
-renode/​peripherals/​VirtualSensorStream.cs +
-renode/​sensor_i2c.repl +
-firmware/​main.c +
-</​code>​ +
- +
-Tasks: +
- +
-  - In ''​VirtualSensorStream.cs'',​ find the deterministic sample table. +
-  ​Find the code that returns a 4-byte sample frame. +
-  - In ''​firmware/​main.c''​, find the code that reads one sample from I2C. +
-  - Run the validation and locate the UART line for ''​seq=0''​+
- +
-Fill the table: +
- +
-^ Step ^ File ^ Evidence ^ +
-Sensor provides sample table |  |  | +
-| REPL connects sensor ​to I2C |  |  ​+
-Firmware reads sample frame  ​| ​ | +
-| Firmware prints sample |  |  | +
-| Harness validates sample count |  |  | +
- +
-==== Exercise 3: Implement The Threshold Filter ==== +
- +
-Open ''​firmware/​main.c'' ​and implement:+
  
 +==== Interface ====
 +Implement the function in ''​exercise2_pixy_vector/​pixy_vector.c'':​
 <code c> <code c>
-threshold_filter_should_keep +typedef struct { 
-</​code>​+    int x0; 
 +    int y0; 
 +    int x1; 
 +    int y1; 
 +} PixyVector;
  
-Rules: +float estimate_pixy_vector_error(PixyVector vector, int frame_width);
- +
-  * drop values below ''​THRESHOLD_MIN_VALUE''​; +
-  * drop values above ''​THRESHOLD_MAX_VALUE'';​ +
-  * drop values whose absolute jump from ''​previous_kept''​ is greater than ''​THRESHOLD_MAX_JUMP'';​ +
-  * keep all other values. +
- +
-Expected threshold drops: +
- +
-<​code>​ +
-seq=4 +
-seq=6+
 </​code>​ </​code>​
  
-After this exercise, some checks may still fail because the model filter is not +==== Local Validation ​==== 
-implemented yet. +Compile and run the local unit tests from the workspace
- +<​code ​bash
-==== Exercise 4: Implement The Tiny Fixed-Point Model Score ==== +cd nxp_car_lab_skeleton 
- +make test-pixy
-Open: +
- +
-<​code>​ +
-firmware/​main.c +
-firmware/​model_weights.h+
 </​code>​ </​code>​
  
-Implement:+---
  
-<code c> +===== Exercise 3: Servo Command Conversion =====
-model_filter_score +
-</​code>​+
  
-The model uses two features:+==== 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.
  
-<​code>​ +==== Theoretical Context ==== 
-abs_center ​abs(value ​MODEL_CENTER_VALUE) +The PID controller produces an abstract output intended to represent steering direction. The function must: 
-abs_jump ​  = abs(value - previous_kept) +  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. 
-</​code>​+  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).
  
-The score formula ​is:+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.
  
-<code c> 
-score = MODEL_BIAS_Q0 
-      + MODEL_WEIGHT_ABS_CENTER_Q0 * abs_center 
-      + MODEL_WEIGHT_ABS_JUMP_Q0 * abs_jump; 
-</​code>​ 
  
-This model is intentionally tiny:+==== Examples ====
  
-  * it uses integer arithmetic; +^ pid_output ^ Expected PWM (us) ^ 
-  * there is no runtime training; +| ''​-1.0''​ | ''​1000''​ | 
-  * all weights are already provided; +| ''​-0.5''​ | ''​1250''​ | 
-  * the goal is to understand how a compact model can replace hand-written thresholds+| ''​0.0''​ | ''​1500''​ | 
- +| ''​0.5''​ | ''​1750''​ | 
-==== Exercise ​5: Implement The TinyML Keep/Drop Decision ==== +| ''​1.0''​ | ''​2000''​ | 
- +| ''​2.0''​ | ''​2000''​ (clamped) | 
-Implement:+| ''​-2.0''​ | ''​1000''​ (clamped) |
  
 +==== Interface ====
 +Implement the function in ''​exercise3_steering/​steering.c'':​
 <code c> <code c>
-model_filter_should_keep+int pid_output_to_servo_us(float pid_output);​
 </​code>​ </​code>​
  
-Rule: +==== Local Validation ​==== 
- +Compile ​and run the local unit tests:
-  * keep the sample if ''​score >MODEL_KEEP_THRESHOLD_Q0'';​ +
-  * drop it otherwise. +
- +
-Expected model drops: +
- +
-<​code>​ +
-seq=+
-seq=+
-seq=+
-seq=+
-</​code>​ +
- +
-Run the validation again. The final summary should be: +
- +
-<​code>​ +
-SUMMARY threshold_keep=8 threshold_drop=2 model_keep=6 model_drop=4 disagreements=2 +
-</​code>​ +
- +
-==== Exercise 6: Compare The Two Methods ==== +
- +
-Use ''​output/​report.html'' ​and UART output to answer: +
- +
-  - Which samples are rejected by both methods? +
-  - Which samples are accepted by the threshold filter but rejected by the model? +
-  - Why do the two methods disagree at ''​seq=2''​ and ''​seq=7''?​ +
-  - Which method is easier to explain? +
-  - Which method is easier to tune if the data distribution changes? +
- +
-Expected discussion:​ +
- +
-  * the threshold filter catches large absolute outliers and large immediate jumps; +
-  * the model uses both distance from a learned center and distance from the previous accepted model value; +
-  * the model is stricter on borderline jump samples because both features contribute to the score. +
- +
-==== Exercise 7: Optional Extension ==== +
- +
-Choose one: +
- +
-  * change one threshold constant and explain how the final summary changes; +
-  * add one more sample to ''​VirtualSensorStream.cs''​ and update the expected summary; +
-  * change one model weight and explain which samples become more or less likely to be kept; +
-  * update ''​docker/​scripts/​generate_report.py''​ to make disagreements easier to inspect in the HTML report. +
- +
-===== Instructor Timing ===== +
- +
-Suggested 3-hour schedule: +
- +
-^ Time ^ Topic ^ +
-| 0:00 - 0:15 | Digital twin motivation and project layout | +
-| 0:15 - 0:35 | ''​.resc''​ walkthrough with ''​renode/​run_test.resc''​ | +
-| 0:35 - 0:55 | ''​.repl''​ and virtual wiring with ''​renode/​sensor_i2c.repl''​ | +
-| 0:55 - 1:15 | Custom I2C peripheral walkthrough with ''​VirtualSensorStream.cs''​ | +
-| 1:15 - 1:30 | IDE run loop, UART output, HTML report | +
-| 1:30 - 1:45 | Exercise 1 | +
-| 1:45 - 2:05 | Exercise 2 | +
-| 2:05 - 2:25 | Exercise 3 | +
-| 2:25 - 2:45 | Exercises 4 and 5 | +
-| 2:45 - 3:00 | Exercise 6 discussion or optional extension | +
- +
-===== Instructor Reference ===== +
- +
-The completed solution is stored separately from the student starter: +
- +
-<​code>​ +
-reference/​firmware/​main.c +
-</​code>​ +
- +
-The student TODO file remains: +
- +
-<​code>​ +
-firmware/​main.c +
-</​code>​ +
- +
-To validate the reference without modifying the starter permanently:​ +
 <code bash> <code bash>
-sg docker -c '​DOCKER_HOST=unix:///​var/​run/​docker.sock docker run --rm --entrypoint /bin/bash \ +cd nxp_car_lab_skeleton 
-  -v "​$PWD":/​host:​ro renode_dt-digital-twin:​latest \ +make test-steering
-  -lc "cp /​host/​reference/​firmware/​main.c /​workspace/​firmware/​main.c && /​workspace/​scripts/​entrypoint.sh"'​+
 </​code>​ </​code>​
  
-If the current shell already has Docker group membership, the outer ''​sg docker +---
--c''​ wrapper is not needed. Keep ''​DOCKER_HOST=unix:///​var/​run/​docker.sock''​ if +
-Docker points at a stale rootless socket. +
- +
-===== Common Problems ===== +
- +
-==== Docker Socket Errors ==== +
- +
-If Docker cannot connect to the daemon, try: +
- +
-<code bash> +
-DOCKER_HOST=unix:///​var/​run/​docker.sock ./run.sh up --build digital-twin +
-</​code>​ +
- +
-If group membership was just changed and the current shell has not picked it up, +
-use: +
- +
-<code bash> +
-sg docker -c '​DOCKER_HOST=unix:///​var/​run/​docker.sock ./run.sh up --build digital-twin'​ +
-</​code>​ +
- +
-==== Firmware Builds But Samples Are Wrong ==== +
- +
-Check: +
- +
-  * ''​renode/​sensor_i2c.repl''​ connects the sensor to ''​i2c0''​ at ''​0x52'';​ +
-  * firmware uses the same I2C address; +
-  * the virtual sensor preserves a whole sample frame across byte-wise reads. +
- +
-==== Validation Fails After Editing ==== +
- +
-Use evidence in this order: +
- +
-  - ''​output/​report.html''​ for the high-level failing check; +
-  - ''​output/​uart_output.txt''​ for firmware-side behavior; +
-  - ''​renode/​run_test.resc''​ and ''​renode/​sensor_i2c.repl''​ for wiring issues; +
-  - ''​VirtualSensorStream.cs''​ for sample stream issues. +
- +
-==== Starter Code Fails Filter Checks ====+
  
-This is expected. The starter code reads the sensor but does not yet implement +===== Deliverables =====
-the threshold and model decisions correctly.+
  
-===== What To Submit =====+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'';​
  
-For the practical part, submit:+===== Grading Criteria =====
  
-  * answers to Exercises 1 and 2; +^ Component ^ Percentage ^ 
-  ​* ​the implementation ​of the threshold filter; +| PID tuning analysis ​and track characterization | 30% | 
-  * the implementation ​of the model score and model keep/drop decision; +| Functional PID parameters on the physical track | 25% | 
-  * the final summary line; +| Exercise 2: PixyCam2 error estimation ​implementation ​| 20% | 
-  * a short explanation of why the two methods disagree at ''​seq=2'' ​and ''​seq=7''​.+| 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.1781989137.txt.gz · Last modified: 2026/06/20 23:58 by cezar.zlatea
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