Week 8 · Coding Period

Off the emulator — the pipeline runs on the Jetson

The plan from Week 7, executed. The board moved to NVMe, and the entire pipeline that had only ever run into a QEMU virtual machine now runs into real silicon over a real network. Same cargo, same channel — a different machine at the end of it.

Every week of this project up to now has ended with a live CARLA LiDAR stream arriving somewhere. In Weeks 1 through 3, that somewhere was an AGL virtual machine running in QEMU on the same server that generated the data. It proved the transport worked, but it proved it on a single box, over emulated networking, into emulated hardware.

This week that setup was replicated on the Jetson Orin Nano. The stream now leaves the server, crosses an actual network, and arrives on an actual automotive-grade Linux board.

1. NVMe — the change that unblocked everything

Week 7 diagnosed the wall precisely: the SD-card root filesystem had 47.9 MB free. That single number was why nothing could move forward. There was no room to add ROS2, no room for a graphics stack, no room for anything.

Moving root to NVMe removed that ceiling, and it removed something else along with it. Week 6 was spent almost entirely on a failing 3.3 V→1.8 V UHS voltage switch on the SD bus, fixed by patching no-1-8-v and nvidia,vmmc-always-on into the mmc@3400000 device-tree node. NVMe is a PCIe device — there is no SDMMC controller anywhere in that path, and therefore no voltage negotiation to fail. The bug that consumed a week simply stopped being reachable.

The fix still ships  The device-tree patch stays in the machine config. It's no longer load-bearing for my boot path, but it's correct, it matters to anyone booting an Orin Nano from SD, and it's still worth sending upstream to meta-tegra. Removing a problem doesn't make the fix for it wrong — and the SD card remains a working fallback image, which is what made attempting the migration reasonable rather than reckless.

2. What "replicating the QEMU setup" actually means

It's worth being precise about what moved and what didn't, because the interesting part is how little had to change.

The server side is untouched: CARLA running headless on lavapipe software rendering, a 32-channel ray-cast LiDAR at 120,000 points per second, the two-process bridge republishing raw sensor bytes as sensor_msgs/PointCloud2 on /carla/lidar, and rosbridge exposing that as WebSocket JSON. Not a line of it changed.

The client side is the same standard-library WebSocket client from Week 1 — 73 lines, no dependencies, taking host, port and topic as arguments. It was written that way deliberately, and this week is the payoff: moving it from an emulated VM to a real board required editing nothing. It takes a different address and does the same thing.

BEFORE (Weeks 1–3) AFTER (Week 8) ┌────────────────────┐ ┌──────────────┐ real ┌──────────────────┐ │ one server │ │ SERVER │ network │ JETSON ORIN NANO│ │ CARLA + AGL VM │ │ CARLA │ ────────► │ AGL 21 on NVMe │ │ QEMU slirp NAT │ │ ROS2 │ │ rosbridge client│ └────────────────────┘ └──────────────┘ └──────────────────┘

That is the transport leg of the ideal architecture from the project's opening diagram — workstation to real target, over a real LAN — running on real silicon for the first time. Week 6 closed by naming this as the payoff. This is it.

3. Where it stands, and what's next

Status: AGL 21 boots from NVMe on a Jetson Orin Nano with room to grow, and receives a live CARLA LiDAR stream over a real network. The hardware arc that began in Week 3 with a Raspberry Pi that wouldn't boot is closed.

Week 7 was a planning week and it's worth noting it paid off as intended: bundling the storage migration together with the rest meant one recovery-mode cycle instead of several, and keeping the known-good SD image as a fallback is why the attempt was worth making. Slowing down to sequence the work turned out to be the fastest way through it.

← Week 7
Home →