Site-specific instructions and updates for KAIST Mobile Robots
This page collects configuration details and ongoing updates for the robot fleet at KAIST. Use the general Setup and Operation guides for baseline procedures; this page covers what is specific to your deployment.
Follow these steps for the KAIST mobile robot configuration.
Power on the robots. Turn on the big 12V power bank for the Jetson, the switch at the bottom for the electronics/motors. The Jetson should have a small green light turn on and the LED indicator next to the switch on the bottom should turn red. Wait a few minutes, the display screen should power on and you should see the desktop.
On your workstation, launch the DDS Robot GUI and start the local Docker stack. See Operation → Starting User GUI / DDS for the full workflow.
These steps should just include pressing the "Start" button next to the Docker
Navigate to the dds_robot_platform/dds/ repository and run ./start_scripts.sh
cd dds_robot_platform/dds ./start_scripts.sh
I have tried to make this as simple as possible and possible all from the DDS Robot GUI. For each robot in the right hand side selection, you must "Start Docker", select the KAIST checkbox and then click "Start ROS". The robot LiDAR sensor should begin spinning and the robot should appear on the left side column indicating an active robot.
If you prefer to manually start the robot via SSH to the Jetson:
SSH into the Jetson (username/password = jetson):
ssh jetson@<jetson_ip_address>
Then start the docker container:
sudo docker run --runtime nvidia --network=host -v ~/workspaces/catkin_ws:/workspace/catkin_ws -v ~/gemini_api:/gemini_code -v /dev/bus/usb:/dev/bus/usb -v /dev/video0:/dev/video0 -v /dev/video1:/dev/video1 -it --device=/dev/ttyUSB0 --device=/dev/spidev0.0 --rm --privileged --name ros_noetic ghcr.io/satomm1/ml_ros:latest bash -lc 'python3 /workspace/catkin_ws/src/startup_script.py & exec bash'
Then start the ROS node via the kaist.launch file:
roslaunch mattbot_bringup kaist.launch
From the GUI, select the robot and click "Shut down" or "Shut down all".
To manually stop the robot via SSH to the Jetson, press Ctrl+C in the terminal where you ran roslaunch, then stop the Docker container by typing exit into the terminal.
Use the GUI "Power Off" button for graceful shutdown when possible. Turn off the 12V battery and switch off the electronics/motor switch.
To manually power off the Jetson, run sudo shutdown now -h in the terminal. Wait for the Jetson to fully power down before cutting power.
I think these are the IP addresses assigned on the KAIST network. However, the exact addresses might be different and you should double check.
| Robot ID | Jetson IP |
|---|---|
| Robot 1 | 192.168.52.2 |
| Robot 2 | 192.168.52.3 |
| Robot 3 | 192.168.52.4 |
| Robot 4 | 192.168.52.5 |
robot_env.sh: Each Jetson should have /workspace/catkin_ws/src/robot_env.sh configured with the correct ROBOT_ID, IP, and sensor settings. See the Setup Guide → Jetson for details.
Document SSID, VLAN, static IP reservations, and any firewall rules required for DDS, GraphQL (port 8000), and the Jetson host service (port 8081).
Use the GUI Power Off button for graceful shutdown when possible. Charge batteries before extended storage. See Operation Guide → Powering down for manual shutdown steps.
Required software, script, and hardware updates for the KAIST deployment. Most recent updates appear at the top.
On each Jetson (outside Docker), install the Jetson host service so the operator GUI Robot Startup panel can start/stop the ros_noetic container and power off the Jetson over HTTP on port 8081. ROS launch and software updates remain on port 8080 inside the container (startup_script.py).
1. Download the install script on the Jetson:
cd ~ wget "https://raw.githubusercontent.com/satomm1/Robot/main/Jetson/jetson-host-install.sh" chmod +x jetson-host-install.sh
2. Run the installer on the Jetson:
sudo ./jetson-host-install.sh
The installer writes /opt/robot/host_service.py and enables the robot-host-service systemd unit so the service starts on boot. Re-running the installer replaces the service file and restarts it.
If you see /usr/bin/env: 'bash\r': No such file or directory, the script has Windows (CRLF) line endings. On the Jetson run sed -i 's/\r$//' ~/jetson-host-install.sh and try again.
3. Verify the service is running:
curl -s http://127.0.0.1:8081/status
Expected response (example): {"host_service": true, "docker_running": false, "container": "ros_noetic"}
On each Jetson, remove the old Docker image and pull the updated ml_ros image from GitHub Container Registry. The pull can take a long time — use tmux so it keeps running if your SSH session disconnects.
Install tmux:
sudo apt update sudo apt install tmux
Start a tmux session (on the Jetson host, outside Docker):
tmux new -s docker-pull
Inside tmux, stop the ROS container if it is running, remove the old image, and pull the new one:
sudo docker stop ros_noetic sudo docker rmi ros_ml:latest sudo docker pull ghcr.io/satomm1/ml_ros:latest
Verify the new image is present:
sudo docker images ghcr.io/satomm1/ml_ros:latest
When the pull finishes, detach from tmux without stopping it: press Ctrl+B, then D. To reattach later — or if your SSH terminal disconnects during the pull — run tmux attach -t docker-pull. Exit the session when done: type exit inside tmux.
If docker rmi fails because the image is still in use, ensure ros_noetic is stopped (sudo docker stop ros_noetic) and retry. No docker login is required — the package is public on GHCR.
On each Jetson, download these files into ~/workspaces/catkin_ws/src:
cd ~/workspaces/catkin_ws/src sudo wget -O robot_env.sh "https://raw.githubusercontent.com/satomm1/Robot/main/Jetson/robot_env.sh" sudo wget -O startup_script.py "https://raw.githubusercontent.com/satomm1/dds_robot_platform/main/robot/startup_script.py" sudo wget -O cyclonedds.xml "https://raw.githubusercontent.com/satomm1/Robot/main/Jetson/cyclonedds.xml"
Edit robot_env.sh on each robot (inside the Docker container this path is /workspace/catkin_ws/src/robot_env.sh):
sudo nano ~/workspaces/catkin_ws/src/robot_env.sh
Update these lines with the values below. Set ROS_IP and ROBOT_ID uniquely for each robot; the other values are the same for all KAIST units:
export ROS_IP= # this Jetson's IP address export ROBOT_ID= # unique ID for this robot (match MCU robot ID) export MCU_SPI=3 export CAMERA_TYPE=astra_pro_plus export ROBOT_HEIGHT=tall
Use the arrow keys to move the cursor. Type each value after the = on the lines above (leave export and the variable names unchanged).
Save and exit nano: press Ctrl+O, then Enter to confirm the filename, then Ctrl+X to close the editor.
Configure cyclonedds.xml on each robot (host path ~/workspaces/catkin_ws/src/cyclonedds.xml; inside Docker, /workspace/catkin_ws/src/cyclonedds.xml). This file disables multicast and uses an explicit peer list for WiFi mesh discovery. robot_env.sh sets CYCLONEDDS_URI to this path — leave that line unchanged.
sudo nano ~/workspaces/catkin_ws/src/cyclonedds.xml
You must update the <Peer Address="…"/> entries so they list the actual IP addresses of every robot and device that should participate in DDS discovery on your network:
ROS_IP in robot_env.sh).The default file assumes the wlan0 interface; change <NetworkInterface name="…"/> only if your WiFi interface has a different name (run ip link or ifconfig to check).
Save and exit nano: Ctrl+O, Enter, Ctrl+X.
See Setup Guide → ROS workspace for sourcing robot_env.sh in ~/.bashrc if not already configured.
Each Jetson must load the spidev kernel module at boot so the robot can communicate with the MCU over SPI. Perform this on every robot unit.
Edit /etc/modules-load.d/spidev.conf on the Jetson host (outside Docker):
sudo nano /etc/modules-load.d/spidev.conf
Add this line to the file (create the file if it does not exist):
spidev
Save and exit nano: Ctrl+O, Enter, then Ctrl+X. Reboot the Jetson for the change to take effect:
sudo reboot
Configure WiFi roaming so each Jetson can switch access points when signal is weak. The Intel AC9260 is already installed on your robots — download and run the setup script on every Jetson host (outside Docker).
Download the script:
cd ~ wget "https://raw.githubusercontent.com/satomm1/Robot/main/Jetson/wifi_roaming_setup.sh" chmod +x wifi_roaming_setup.sh
Run the installer:
sudo ~/wifi_roaming_setup.sh
Follow the prompts for your lab SSID, password, and regulatory domain (KR for Korea). Then reboot:
sudo reboot
After reboot, verify the services are running (replace wlan0 if your interface name differs):
sudo systemctl status wpa_supplicant@wlan0 custom_wifi.service
Assign a fixed DHCP reservation for each Jetson’s WiFi MAC on your router for a stable IP. Revert steps are in the Jetson README.
No previous updates yet.
Complete these steps once on each operator workstation (not on the Jetson). After setup, use Running the Robots for day-to-day operation.
Prerequisites: Docker Desktop (daemon running), git, and Miniconda or Anaconda.
Pre-built installers are produced by GitHub Actions (recommended; no Node.js required).
gui-installer-windows-latest — unzip, run DDS Robot GUI Setup … .exe, launch from the Start menu. Unsigned builds may show SmartScreen — More info → Run anyway if you trust the source.gui-installer-macos-latest — open .dmg, drag DDS Robot GUI to Applications. First launch may need right-click → Open.gui-installer-ubuntu-latest — unzip .AppImage, chmod +x, run. Install FUSE / libfuse2 if the AppImage will not start.http://localhost:8000/graphql.
Clone the repository on your workstation:
git clone https://github.com/satomm1/dds_robot_platform.git cd dds_robot_platform
Windows: Clone into your WSL filesystem (e.g. under ~/ in Ubuntu) so docker compose and DDS scripts run where the README expects. Run the GUI from Windows (desktop app) or from source.
Copy and edit the DDS environment file:
cp dds/dds_env.sh.example dds/dds_env.sh nano dds/dds_env.sh
Set AGENT_ID, INFLUXDB_TOKEN, and any other operator variables. The example file also sets CYCLONEDDS_URI to dds/cyclonedds.xml. Save and exit nano: Ctrl+O, Enter, Ctrl+X.
Edit dds/cyclonedds.xml for your network:
nano dds/cyclonedds.xml
<NetworkInterface name="…"/> to the interface that reaches the robot fleet (run ip link; common names include wlan0, wlp2s0, eth0).<Peer Address="…"/> entries with the IP address of each KAIST robot and any other DDS participant on the network.Save and exit nano: Ctrl+O, Enter, Ctrl+X.
Pull images and start the Docker services (GraphQL, InfluxDB, Ignite) from the repo root:
docker compose pull docker compose up -d
Alternatively, use the GUI Local Stack panel → Docker → Start (requires compose.yaml and dds/dds_env.sh).
DDS Python scripts run on the host (WSL on Windows), not inside Docker. Create the dds conda environment from the dds_robot_platform repo root:
cd dds_robot_platform conda env create -f environment.yml conda activate dds
Note: This is the step I am least confident is fully covered by environment.yml. If scripts fail with missing-module errors, install the reported package into the dds env (e.g. pip install <package> with conda activate dds) and let me know so the requirements file can be updated.
Environment creation can take several minutes. If the environment already exists and you need to refresh it:
conda env update -f environment.yml --prune
Verify CycloneDDS is available:
conda activate dds
python -c "import cyclonedds; print('OK')"
Start DDS scripts from the dds directory (start_scripts.sh activates the dds conda env automatically when needed):
cd dds ./start_scripts.sh
Verify scripts are running:
pgrep -af python
You should see publisher/subscriber scripts such as entry_exit.py, heartbeat_publisher.py, and goal_publisher.py. Stop them with ./stop_scripts.sh when finished.
Full reference: dds_robot_platform README and Setup Guide → User GUI / communication.