KAIST Deployment

Site-specific instructions and updates for KAIST Mobile Robots

Overview

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.

Running the Robots

Follow these steps for the KAIST mobile robot configuration.

1

Power on the robots

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.

2

Start the operator GUI

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

3

Start the operator DDS Communication

Navigate to the dds_robot_platform/dds/ repository and run ./start_scripts.sh

cd dds_robot_platform/dds
./start_scripts.sh
4

Start the Robot Software (From DDS Robot GUI)

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
5

Stopping the Robot

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.

6

Power off the robots

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).

  • Operator workstation and robots must be on the same routable network (or configured for DDS discovery).
  • Allow inbound/outbound traffic to robot IP addresses — blocked firewalls are a common cause of connection failures.

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.

Mapping

One Time Updates

Required software, script, and hardware updates for the KAIST deployment. Most recent updates appear at the top.

2026-06-01 Script

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"}

2026-06-01 Software

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.

2026-06-01 Script

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:

  • Include this Jetson’s IP address (the same value you set for ROS_IP in robot_env.sh).
  • Add the IP addresses of every other KAIST robot and any operator machines running DDS on the mesh.
  • Remove any placeholder entries that do not correspond to a real device.

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.

2026-06-01 Software

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
2026-06-01 Script

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.

One Time Installs

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.

Firewall: Allow inbound and outbound traffic to your robot IP addresses. Blocked firewall rules are a common cause of connection failures.

Pre-built installers are produced by GitHub Actions (recommended; no Node.js required).

  1. Go to dds_robot_platform Actions
  2. Open the most recent successful workflow run
  3. Under Artifacts, download one ZIP for your system (you must be logged in to GitHub):
    • Windows: gui-installer-windows-latest — unzip, run DDS Robot GUI Setup … .exe, launch from the Start menu. Unsigned builds may show SmartScreen — More infoRun anyway if you trust the source.
    • macOS: gui-installer-macos-latest — open .dmg, drag DDS Robot GUI to Applications. First launch may need right-click → Open.
    • Linux: gui-installer-ubuntu-latest — unzip .AppImage, chmod +x, run. Install FUSE / libfuse2 if the AppImage will not start.
Backend: The desktop app is only the UI. You still need the Docker stack and host DDS scripts running so the GraphQL API is available at 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
  • Network interface — set <NetworkInterface name="…"/> to the interface that reaches the robot fleet (run ip link; common names include wlan0, wlp2s0, eth0).
  • Peer addresses — replace placeholder <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 → DockerStart (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.