Installation Setup - Forestry-Robotics-UC/fruc_dataset_apparatus GitHub Wiki

Installation and Setup Guide

System Requirements

Minimum Hardware Specifications

Component Minimum Recommended
CPU Quad-core (2.0 GHz) 8-core (3.0+ GHz)
RAM 8 GB 16 GB+
Storage 256 GB SSD 1 TB NVMe SSD
USB Ports 3x USB 3.0 4+ USB 3.0+
Ethernet 1 Gbps 10 Gbps (optional)
GPU (optional) - NVIDIA Jetson / RTX

Operating System

Desktop/Workstation:

  • Primary: Ubuntu 22.04 LTS (Jammy Jellyfish)
  • Supported: Ubuntu 24.04 LTS (Noble Numbat)
  • Runtime: Docker and Docker Compose
  • Kernel: 5.15+ recommended

SteamDeck:

  • Base OS: SteamOS (Holo)
  • Runtime: Podman (pre-installed, no Docker installation needed)
  • Setup: Enter Linux desktop mode (see Steam Deck guide)
  • Repository: Usually mounted at /home/deck/fruc_dataset_apparatus

Network Requirements

  • Local Network Access: For DDS communication between containers
  • Ouster LiDAR Link-Local: 169.254.0.0/16 subnet
  • Optional Internet: For Docker image pulls

Pre-Installation Checklist

Before starting, ensure:

  • Operating system installed and up-to-date
  • System has stable power
  • At least 50 GB free disk space initially
  • All sensors purchased and available
  • USB cables and adapters on hand
  • Network connectivity working
  • Sudo access or root permission
  • Terminal/console access available

Step 1: System Preparation

Update Package Manager

# Update package lists
sudo apt update

# Upgrade installed packages
sudo apt upgrade -y

# Install essential utilities
sudo apt install -y \
    curl \
    wget \
    git \
    build-essential \
    net-tools \
    htop \
    openssh-server

System Configuration

Increase File Descriptor Limits

For large-scale recording sessions:

# Edit limits file
sudo nano /etc/security/limits.conf

# Add at end of file:
* soft nofile 65536
* hard nofile 65536
* soft nproc 65536
* hard nproc 65536

Apply immediately:

ulimit -n 65536

Configure Swap Space (if needed)

For systems with limited RAM:

# Check current swap
free -h

# Create 4GB swap file
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# Make permanent
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab

Step 2: Install Container Runtime

For Desktop/Workstation (Docker)

Option A: Using Official Docker Repository (Recommended)

# Add Docker's official GPG key
sudo apt install -y ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# Add Docker repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \
  https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# Update package index
sudo apt update

# Install Docker
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

Option B: Using Distribution Packages

sudo apt install -y docker.io docker-compose

For SteamDeck (Podman)

Podman is pre-installed on SteamDeck. No additional installation needed!

Verify that Podman is available:

podman --version
podman-compose --version

Both commands should return version information. If podman-compose is not installed, install it:

sudo pacman -S podman-compose  # On SteamOS (pacman-based)

Verify Installation

For Docker (Desktop):

# Check versions (Docker)
docker --version
docker-compose --version

# Test Docker daemon
sudo docker run hello-world  # May require sudo initially

# Output should show: "Hello from Docker!"

For Podman (SteamDeck):

# Check versions (Podman)
podman --version
podman-compose --version

# Test Podman daemon
podman run hello-world

# Output should show: "Hello from Podman"

Configure Container Runtime for Non-Root Access

For Docker (Desktop):

# Create docker group (usually already exists)
sudo groupadd docker 2>/dev/null || true

# Add current user to docker group
sudo usermod -aG docker $USER

# Apply group changes (option 1: restart session)
newgrp docker

# Or option 2: command-specific
sudo docker ps

# Test without sudo (after restart)
docker ps

For Podman (SteamDeck):

Podman on SteamDeck typically allows non-root access by default. If you encounter permission issues:

# Check if rootless mode is available
podman ps  # This should work without sudo

# If sudo is required, check your user's sudoers configuration
sudo -l

Step 3: Configure Serial Port Access

Check Available Serial Ports

# List serial devices
ls -la /dev/ttyUSB*
ls -la /dev/ttyACM*

# Or use udevadm
udevadm info -n /dev/ttyUSB0

# Use tool to list all devices
dmesg | tail -20  # Check kernel messages for device detection

Grant Serial Port Permission

Method 1: Temporary (this session only)

# Make serial ports accessible
sudo chmod 666 /dev/ttyUSB*
sudo chmod 666 /dev/ttyACM*

Method 2: Permanent (recommended)

# Add user to dialout group
sudo usermod -aG dialout $USER

# Log out and back in for changes to take effect
exit

Method 3: Using tty-perms.sh Script

cd fruc_dataset_apparatus
sudo bash tty-perms.sh

Verify Serial Access

# Check permissions (should show rw for your user)
ls -la /dev/ttyUSB0

# Test with minicom (optional)
sudo apt install -y minicom
minicom -D /dev/ttyUSB0 -b 460800

Step 4: Clone Repository

Clone from Git

# Create workspace directory
mkdir -p ~/Development
cd ~/Development

# Clone the repository
git clone https://github.com/[org]/fruc_dataset_apparatus.git
cd fruc_dataset_apparatus

# Display directory structure
tree -L 2 -a

Or Extract from Archive

# If you have a ZIP or TAR file
unzip fruc_dataset_apparatus.zip
# or
tar -xzf fruc_dataset_apparatus.tar.gz

cd fruc_dataset_apparatus

Initialize Submodules (if applicable)

# If repository uses submodules
git submodule init
git submodule update

# Or combined
git clone --recurse-submodules <repository-url>

Verify Repository Structure

# Check key directories exist
ls -la docker/
ls -la rosbags/
ls -la rviz/

# Verify scripts are present
ls -la launch-system.sh stop-system.sh tty-perms.sh

Step 5: Install Sensor-Specific Prerequisites

RealSense udev Rules

# Navigate to RealSense rules directory
cd realsense-udev-rules/

# Review the installation script
cat README.md

# Install udev rules
sudo bash realsense-udev-install.sh

# Unplug and replug RealSense camera for rules to take effect
# Verify with:
lsusb | grep RealSense
realsense-viewer  # If installed

Xsens Serial Configuration

# Check which serial port Xsens is connected to
dmesg | grep -i xsens
dmesg | grep -i ftdi  # Xsens uses FTDI chip

# Example output:
# [    12.345678] usb 1-1: cp210x converter now attached to ttyUSB0

# Remember this port number for later configuration

Ouster LiDAR Network Setup

Configure Link-Local Network

On Ubuntu 22.04+, use netplan:

# Backup original config
sudo cp /etc/netplan/00-installer-config.yaml \
        /etc/netplan/00-installer-config.yaml.bak

# Edit netplan configuration
sudo nano /etc/netplan/00-installer-config.yaml

Add Ouster interface configuration:

network:
  version: 2
  ethernets:
    # Existing network (DHCP)
    eth0:
      dhcp4: true
    
    # Add Ouster link-local (replace eth1 with your interface)
    eth1:
      dhcp4: no
      addresses:
        - 169.254.50.1/16  # Host IP in link-local range
      optional: true

  renderer: networkd

Apply configuration:

sudo netplan apply

# Verify interface is configured
ip addr show eth1

# Should show: inet 169.254.50.1/16 brd 169.254.255.255

Test Ouster Connectivity

# Ping Ouster at default address
ping 169.254.49.182

# Or discover with ARP scan
sudo arp-scan -l | grep -i ouster

# Or use Ouster's discovery tool (if available)
# Install: https://github.com/ouster-lidar/sdk

Emlid GNSS Configuration

For serial connection:

# Check serial device
ls -la /dev/ttyUSB*

# For network connection, note the assigned IP
# Usually available via mDNS: reach.local
ping reach.local

Step 6: Build Docker Containers

Full Build

cd docker/

# Build all containers (takes 15-30 minutes)
docker-compose build

# Or with progress output
docker-compose build --progress=plain 2>&1 | tee build.log

# Check for errors
tail -50 build.log

Build Status Monitoring

# In separate terminal, monitor Docker daemon
watch -n 1 docker ps

# Or check individual build progress
docker-compose build sensor_name --progress=plain

Troubleshoot Build Failures

If a build fails:

# Rebuild with no cache
docker-compose build --no-cache sensor_name

# Check specific Dockerfile for syntax
docker build -f Dockerfile.xsens -t test:latest .

# View detailed error output
docker-compose build xsens --verbose 2>&1 | grep -A 10 "ERROR"

# Try building individual stages
docker build --target base -f Dockerfile.realsense .

Verify Build Success

# List built images
docker images | grep ros2-apparatus

# Expected output:
# REPOSITORY                    TAG       IMAGE ID
# ros2-apparatus-xsens          jazzy     abc123def456
# ros2-apparatus-realsense      jazzy     xyz789uvw456
# ros2-apparatus-ouster         jazzy     ...
# etc.

Step 7: Create Docker Network

Create Link-Local Network (for Ouster)

# Create custom network
docker network create \
  --driver bridge \
  --subnet=169.254.0.0/16 \
  link-local-net

# Verify network
docker network ls | grep link-local
docker network inspect link-local-net

Step 8: Test System

Pre-Recording Diagnostic Test

cd docker/

# Run automated diagnostics (takes ~7 minutes)
bash pre_recording_test.sh

# Expected output shows:
# - Container startup
# - Topic frequencies
# - Data validation
# - Diagnostic results

Manual Sensor Test

cd docker/

# Start containers
docker-compose up -d

# Wait for initialization (30 seconds)
sleep 30

# List active topics
docker exec ros2-apparatus-xsens ros2 topic list

# Check specific sensor
docker exec ros2-apparatus-realsense ros2 topic hz /camera/color/image_raw

# Monitor system resources
docker stats

# Stop when done
docker-compose down

Network Connectivity Test

# Test inter-container communication
docker-compose up -d xsens publisher

# From publisher, check IMU topic
docker exec ros2-apparatus-publisher ros2 topic echo /imu/data --once

docker-compose down

Step 9: Configure Scripts

Make Scripts Executable

chmod +x launch-system.sh
chmod +x gnome-launch-system.sh
chmod +x stop-system.sh
chmod +x gnome-stop-system.sh
chmod +x tty-perms.sh

# Verify
ls -la *.sh | head -5

Test Launch Scripts

# For KDE/KDialog:
./launch-system.sh --help 2>/dev/null || echo "Help not available"

# For GNOME:
./gnome-launch-system.sh --help 2>/dev/null || echo "Help not available"

# Dry-run (don't actually launch)
bash -n launch-system.sh  # Syntax check only

Step 10: Initial Recording

First Recording Test

# Start from repository root
cd ~/Development/fruc_dataset_apparatus

# Launch interactive system
./launch-system.sh

# Follow the dialogs:
# 1. Accept default recording name (or enter custom)
# 2. Select few topics for quick test
# 3. Choose "Size" split, enter 1 GB
# 4. Select "fastwrite" compression
# 5. Confirm to start

# Recording will begin...
# Let it run for 60-120 seconds
# Stop via dialog prompt

Verify First Recording

# Check recorded data
ls -lh rosbags/

# View recording metadata
ros2 bag info rosbags/2026-*/

# Playback recording
ros2 bag play rosbags/2026-*/ --loop

# Check topic data
ros2 topic echo /imu/data --once

Post-Installation Configuration

optional: Install Additional Tools

# RealSense viewer
sudo apt install -y realsense-viewer

# Point cloud visualization
sudo apt install -y pcl-tools

# RViz for visualization
sudo apt install -y ros-jazzy-rviz2

# Dev tools
sudo apt install -y vim nano gedit python3-pip

optional: Configure GUI Shortcuts

for desktop environment, create launch shortcuts:

# Create .desktop file
mkdir -p ~/.local/share/applications/

cat > ~/.local/share/applications/fruc-launch.desktop << 'EOF'
[Desktop Entry]
Type=Application
Name=FRUC Recording
Exec=bash -c 'cd ~/Development/fruc_dataset_apparatus && ./launch-system.sh'
Icon=media-record
Categories=Utility;
Terminal=true
EOF

# Make executable
chmod +x ~/.local/share/applications/fruc-launch.desktop

# Refresh desktop
update-desktop-database ~/.local/share/applications/

optional: Set Up Automated Backups

# Create backup script
cat > backups_rosbags.sh << 'EOF'
#!/bin/bash
# Backup rosbags to external drive weekly

BACKUP_DIR="/mnt/backup/rosbags"
SOURCE_DIR="rosbags"

# Check if backup drive is mounted
if [ ! -d "$BACKUP_DIR" ]; then
    echo "Backup drive not found!"
    exit 1
fi

# Copy recent recordings
rsync -av --delete "$SOURCE_DIR/" "$BACKUP_DIR/"
echo "Backup complete at $(date)"
EOF

chmod +x backups_rosbags.sh

# Add to crontab for weekly execution
crontab -e
# Add: 0 2 * * 0 ~/fruc_dataset_apparatus/backups_rosbags.sh

optional: Enable X11 Forwarding (for Remote Sessions)

# Install X11 server
sudo apt install -y xvfb x11-utils

# In SSH session, forward display
ssh -X user@remote_host

# Or add to ~/.ssh/config
cat >> ~/.ssh/config << 'EOF'
Host remote_host
    ForwardX11 yes
    ForwardX11Trusted yes
EOF

Final Verification

Comprehensive System Check

# Create verification script
cat > system_check.sh << 'EOF'
#!/bin/bash

echo "=== FRUC Dataset Apparatus System Check ==="
echo ""

echo "1. Docker Status:"
docker ps -a | head -3

echo ""
echo "2. Storage:"
df -h | grep -E "^/dev|^Filesystem"

echo ""
echo "3. Network - Ouster:"
ping -c 1 -W 1 169.254.49.182 && echo "✓ Ouster reachable" || echo "✗ Ouster not found"

echo ""
echo "4. Serial Ports:"
ls -la /dev/ttyUSB* /dev/ttyACM* 2>/dev/null || echo "No serial devices found"

echo ""
echo "5. Repository Structure:"
[ -d docker ] && echo "✓ Docker directory found" || echo "✗ Docker directory missing"
[ -f launch-system.sh ] && echo "✓ launch-system.sh found" || echo "✗ launch-system.sh missing"
[ -d rosbags ] && echo "✓ rosbags directory found" || echo "✗ rosbags directory missing"

echo ""
echo "=== Check Complete ==="
EOF

chmod +x system_check.sh
./system_check.sh

Sensor Connectivity Status

# Summary of sensor status
./docker/pre_recording_test.sh  # 7-minute diagnostic

# Or quick check
cd docker
docker-compose up -d
sleep 10
docker-compose exec publisher ros2 topic list -v | head -20
docker-compose down

Troubleshooting Installation

Common Issues

Problem Solution
Docker daemon not running sudo systemctl start docker
Permission denied on /dev/docker.sock sudo usermod -aG docker $USER + logout/login
Docker compose not found sudo apt install docker-compose-plugin
Ouster not reachable Check link-local IP configuration with ip addr
Serial port permission denied sudo bash tty-perms.sh or sudo usermod -aG dialout $USER
Build fails with dependency error docker-compose build --no-cache or rosdep update
Out of disk space during build Reduce Docker image size: docker system prune -a

Check Logs

# Docker daemon logs
sudo journalctl -u docker -f

# Specific container logs
docker logs ros2-apparatus-xsens

# Build logs
docker-compose build 2>&1 | tee build.log

Next Steps

After successful installation:

  1. Read the User Manual: User Manual
  2. Test recording: Run ./launch-system.sh
  3. Review scripts: See Scripts Reference
  4. Explore topics: List active topics with ros2 topic list
  5. Visualize data: Use Foxglove Bridge on port 9092
  6. Develop custom tools: See Developer Guide

Online Resources


Last Updated: 2026-03-30
Related Docs: User Manual | Technical Architecture | Developer Guide