Jetson deployment
From a freshly flashed Jetson Orin Nano to a self-starting Haller — clone, build, scripts/install.sh, and the three systemd services.
This is the orchestration page. It assumes the hardware is built (build) and walks through everything software between "Jetson boots into Ubuntu" and "Haller bringup + HMI come up on every power-on, on its own Wi-Fi network."
You can also use this page as a checklist for re-imaging — every step is idempotent.
What the deployment does
Three systemd services boot in sequence on the Jetson:
| Service | What it does | When it runs |
|---|---|---|
haller-ap.service | Brings up the HallerRobot Wi-Fi AP (10.42.0.1/24) so an operator laptop can connect to the robot anywhere, no infrastructure. | First, before the robot service. |
haller-robot.service | ROS 2 hardware stack — motors over CAN, RPLIDAR, robot state publisher. Wrapper script scripts/haller_bringup.sh. | After haller-ap. |
haller-hmi.service | The unified HMI (FastAPI on :8000, Next.js on :3000). | After network-online + haller-ap. |
Once installed, all three start at boot — power on the robot, wait ~30 s, connect to HallerRobot, open http://10.42.0.1:3000, you're operating the robot.
Prerequisites
- Jetson Orin Nano (8 GB) flashed with JetPack 6 (Ubuntu 22.04 base, JetPack 6 ships ROS 2 Jazzy-compatible userspace).
- User account
orin(the unit files hard-code this — change them if your username differs). - Internet access for the initial clone + dependency install. After install, the AP fallback lets you work without infrastructure Wi-Fi.
- All the physical USB devices plugged in: CANable2 adapter, RPLIDAR A1M8, both SO-101 bus adapters, any USB cameras.
1. Clone the repo
sudo apt update
sudo apt install -y git git-lfs
git clone --recurse-submodules https://github.com/oscardvs/haller_ws.git ~/haller_ws
cd ~/haller_wsThe --recurse-submodules is important — src/sllidar_ros2/ is a git submodule (Slamtec's driver). If you forget, git submodule update --init --recursive fixes it.
2. Build the ROS 2 stack
Follow Mobile base / Prerequisites for the ROS 2 Jazzy + Nav2 + slam_toolbox apt installs and rosdep install, then:
cd ~/haller_ws
colcon build --symlink-install3. Set up the arm software environment
Per LeRobot environment, create the HMI venv at ~/venvs/haller-hmi/ (the path the HMI service expects). Skip this if the robot only carries the base.
4. Run scripts/install.sh
The provisioning script does four things, all idempotent:
cd ~/haller_ws
sudo ./scripts/install.shWhat it does:
- Installs udev rules (
scripts/99-haller-devices.rules→/etc/udev/rules.d/, reloads + triggers). This creates stable/dev/haller_*symlinks:haller_can,haller_lidar,haller_arm_follower,haller_arm_leader. - Enables
haller-ap.serviceso the Wi-Fi AP comes up at boot. - Enables
haller-robot.serviceso the ROS bringup launches at boot. - Adds
orinto thedialoutgroup for serial-port access.
It does not start the services — that happens at next boot, or you start them manually (step 6).
It does not install the HMI service. The HMI service is currently a manual step (see step 5), partly because it depends on the venv from step 3, which install.sh doesn't manage.
Re-running scripts/install.sh after edits to any of the unit files is safe and recommended — it overwrites the /etc/systemd/system/ copies and reloads systemd.
5. Install the HMI service
The HMI runs alongside the robot bringup. The unit file is scripts/haller-hmi.service; its ExecStart is scripts/run_hmi.sh, which launches both uvicorn (:8000) and the prebuilt Next.js server (:3000).
First, build the frontend standalone bundle:
cd ~/haller_ws/hmi/frontend
pnpm install
pnpm buildThen install + enable the unit:
sudo cp ~/haller_ws/scripts/haller-hmi.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now haller-hmi.serviceSee HMI overview / Production for what run_hmi.sh does at startup (copies .next/static and public/ into the standalone tree before launching).
6. Start everything (without rebooting)
After install.sh + the HMI install, services are enabled but not running yet. Start them in order:
sudo systemctl start haller-ap.service
sudo systemctl start haller-robot.service
sudo systemctl start haller-hmi.serviceOr just reboot — systemd brings them up in the right order on its own.
sudo reboot7. Verify
After reboot, from your laptop:
- Wi-Fi. Connect to
HallerRobotwith passwordhaller2024. Your laptop should get a10.42.0.xlease from the Jetson. - HMI. Browse to
http://10.42.0.1:3000. The "live" badge should turn green within a few seconds; the base panel and arm card should populate. - ROS stack. SSH to
orin@10.42.0.1, thenros2 topic list— you should see/cmd_vel,/odom,/scan,/tf,/joint_states. - Services. All three units should be
active (running):systemctl status haller-ap haller-robot haller-hmi
If any of those four fail, the Troubleshooting section below walks through what to check.
Updating the deployment
After pulling new code or editing config:
cd ~/haller_ws
git pull
colcon build --symlink-install # if ROS code changed
(cd hmi/frontend && pnpm install && pnpm build) # if frontend changed
sudo systemctl restart haller-robot haller-hmiFor unit-file edits, re-run sudo ./scripts/install.sh (or sudo cp the file directly), then sudo systemctl daemon-reload before restarting.
Disabling autostart
For benchwork or development on the Jetson where you want full manual control:
sudo systemctl disable --now haller-ap haller-robot haller-hmiRe-enable when you're done:
sudo systemctl enable --now haller-ap haller-robot haller-hmiTroubleshooting
systemctl status haller-robot→ "Could not open port" or "device not found". A required USB device isn't enumerated.ls -l /dev/haller_can /dev/haller_lidar /dev/haller_arm_*— any missing symlink points to an unplugged device or missing udev rule. Re-runsudo ./scripts/install.shto (re)install the rules.haller-ap.servicefails on thenmcliline. TheWIFI_DEVinscripts/setup_ap.shis hard-coded towlP1p1s0— the Orin Nano dev kit's default. On other hardware runnmcli deviceand edit that constant. See Wi-Fi AP fallback.- HMI service immediately exits. Tail the journal:
journalctl -u haller-hmi.service -e. The two most common causes are (a)~/venvs/haller-hmi/doesn't exist (run the LeRobot environment install), or (b)hmi/frontend/.next/standalone/server.jsdoesn't exist (runpnpm buildinhmi/frontend). - HMI loads but
/healthreturns 503. ROS bringup hasn't finished yet, or it failed.systemctl status haller-robot.servicewill tell you. Topics need to be present for the HMI base panel to function. - Connected to
HallerRobotbut can't reach10.42.0.1:3000. Confirm the AP came up:nmcli con show --activeon the Jetson should listHallerAP. Confirm the HMI is bound to0.0.0.0(not127.0.0.1):ss -tlnp | grep 3000.
Related pages
- Mobile base (ROS 2) — what
haller-robot.serviceactually launches. - HMI overview — what
haller-hmi.serviceactually launches. - Wi-Fi AP fallback — the standalone story for the AP.
- LeRobot environment — the venv the HMI service expects.
- SO-101 arms — udev rules + dialout setup overlap with this page.
- Troubleshooting — cross-cutting symptom-indexed reference for when something here breaks.
RunPod inference and finetuning
Rent a cloud GPU, smoke-test π0.5 / pi0 / GR00T on an SO-101 dataset, replay-eval against your recordings, and LoRA-finetune to your task.
Wi-Fi AP fallback
Standalone story for the HallerRobot access point — what it is, how to start/stop it from the CLI, how to change SSID/password/interface, and how to debug it.