Beneath are links because the website puts them there, you can ignore them. They are there because they are in the level beneath the Setupguide.
1 - Useful Ubuntu Commands
Cheatsheet for Ubuntu commands
cat filename.txt Opens the entire file. You cannot scroll so this is good for short files.
less filename.txt Opens the file and allows you scroll through
nano filename.tct Opens the file and allows you to edit
cd
ls
cd ..
nano
conda
2 - ORCA Setup
Aquiring dependencies and setting up the repository
The following instructions are for Windows devices. There may be different processes for different OS systems. If you find out how to set ORCA up for different devices, feel free to add to this documentation.
Installing dependencies
If you are using a Raspberry Pi, you will want to get miniconda for the Raspberry Pi. This will be done later after SSH is set up. You can skip this section and go to Connecting to GitHub
Install WSL (Windows Subsystem for Linux)
From the Start menu, open Powershell and type “wsl –install”.
Install VSCode (or some other code editor of choice).
If you’re using VSCode, open the Extensions tab and install the following extensions: Python, C/C++, and CMake Tools
Within VSCode, open a new Ubuntu (WSL) terminal
Create a username and password for the Linux system if prompted. This password is used when running Linux commands with administrator permissions (sudo).
Download Miniconda for Linux, but do not open the .sh file.
In the WSL terminal, run bash \_path-to-Downloads/\_Miniconda3-latest-Linux-x86_64.sh and accept the default options in the installer (select yes when prompted about auto_activate_base, though we will change this later).
After Miniconda has been installed, close and reopen the WSL terminal.
To ensure it has been installed, run conda list and you should see a list of the installed dependencies printed out.
We are now going to change one of the default settings with the command 1conda config –set auto_activate_base false`
Go to the ORCA repository and click “Branch” to create your own copy of the code. Name this new repository whatever you want.
If you’ve already made an SSH key aand connected it to github, you can skip the next few steps. If you have no clue what SSH and want to learn more, you can read Basics of SSH.
To securely connect your laptop to GitHub, we will create an SSH key. In the Git Bash terminal, run ssh-keygen -t ed25519 -C [your@email.com](mailto:your@email.com) and accept the default location.
Create a password that you will input every time you pull or push code to GitHub from your terminal, so make sure it is memorable. A new public key file should be made
Run cat file_you_just_made.pub to print out the key to the terminal, and copy it.
If that command doesn’t work, you can also try and run cat ~/.ssh/id_ed25519.pub
In GitHub, open settings and go to the SSH and GPG keys tab, and add a new SSH key.
Name this whatever you want and paste the key into the correct field.
Now we need to install Git for Windows. Follow the installer prompts
Once installed open a Git Bash terminal in VSCode. This is where you will run all the Git commands.
If you need more help with making an SSH key, here is a helpful GitHub link
SSH Agent Forwarding
After making your SSH key, you need to add it to your SSH agent on your lapotp. First we need the SSH agent to be running. In powershell run Get-Service -Name ssh-agent. If it says the status is stopped, run Start-Service ssh-agent. Then run Get-Service -Name ssh-agent again and check it says the status is running.
Now to add your key, run ssh-add C:/Users/YOU/.ssh/id_ed25519. You will need to insert the secure passphrase you made when you originally made your SSH key. The key should now be added. You can test this by running ssh -T git@github.com.
Cloning the Repository
We will now clone the code from GitHub onto your computer so that it can be accessed locally. Go to your fork that you just created.
Click the green Code button and within the dropdown go to the SSH tab.
Copy the repository link which should end in .git
In the Git Bash terminal, navigate to whichever folder you would like the code to be copied into, and run git clone link_to_repo.git.
In VSCode, you can now open this folder to see all the code
If you haven’t worked with Git before, read the Basics of Git
Setting up Conda
We now need to use Conda to install the required dependencies for ORCA.
Before we create the conda environment, check that GCC is installed by running gcc --version in the WSL terminal. If the gcc command is not found then install it with sudo apt update and sudo apt install gcc
In the WSL terminal, navigate to the folder you just cloned the code to and run conda env create -f environment-rpi.yaml
Once the environment is installed, run conda activate uhd
The code is now installed and ready to run or modified.
If you already know how SSH works you don’t need to read this. The goal is to gain a basic understanding of what SSH is. This is NOT a tutorial on how to set up SSH.
SSH stands for secure shell. This is another way to connect to other cloud services or devices without needing to login each time. SSH is being used here with GitHub and the Raspberry Pi. You can clone a repository using SSH and you can connect to your Raspberry Pi’s terminal from your laptop using SSH.
Whenever you generate a key on your laptop, it creates both a public and private version. The public version is what you give to things like GitHub or the Raspberry Pi. The private key is what you keep on your laptop and don’t share with anyone.
Whenever you try to connect to something, like GitHub with the SSH key, something happens where the public and private key are compared and verified. Then GitHub is like cool, you’re you, and allows you to clone repositories.
To connect to your Raspberry Pi’s terminal from your laptop, you first give it the public key. After it is connected to the wifi, it is able to copy it from GitHub. Further details are in the setting up your Raspberry Pi page. Then when you try to connect to the Raspberry Pi, the two keys are compared. After verification, you then can access the Pi’s terminal. If verification fails, you can’t access the terminal.
If you already know how Git works you don’t need to read this. The goal is to gain a basic understanding of how to use Git.
Using Git
Git is a version control system that is used to keep track of changes to code, work on separate branches, and collaborate with other developers on the same codebase. It connects your local (offline) code to the remote (cloud) repository on GitHub. Below is basic information on how to use Git.
Cloning and pulling
To initially copy a repository from GitHub, use the git clone <repo-link> (you may need to include the https:// portion of the link or use SSH which is explained above) command as shown above. After you’ve cloned a repository, you can update your local repository with the latest version available on GitHub with the git pull command. When multiple people are working on the same branch, it is important to pull the latest code before pushing anything new.
Comitting Changes
When you have made new changes you want to push to GitHub, you will need to make a commit. First, add all the files you changed using git add -A which adds all modified files. If you only want to add a few specific ones, you can do git add file1.txt file2.txt. The terminal does need to be in the correct folder to add specific files. If the terminal is in a folder above the editted files, you can run git add ./folder/file.txt to add them. Another option is to change the terminal’s location with cd folder.
After adding files, create a new commit using git commit -m "Commit message". To make this commit available on GitHub, push the changes with git push. Git may ask you to explicitly define the upstream branch you are trying to push to, in this case follow the suggestions given such as git push -u origin branchname or git push --set-upstream origin branchname. This process is to link your local branch to a branch on the cloud. You can make multiple commits locally before pushing it to GitHub, or you can push right away after making a commit.
Branches
Git allows you to have multiple branches of the code. Each branch keeps different changes and commits, then the two branches can be merged back together. It is standard practice to make a new branch for each new feature that is being added, as it avoids problems introduced by having multiple partially implemented features conflicting with each other, as well as conflicts introduced by multiple developers working on the same file at the same time. A new branch can be created with git checkout -b branchname. Once the branch is created, you can switch between branches with git checkout branchname (the default branch is called “main”). If changes were made to the main branch after you created your branch and you want to include them in your branch, you can merge the main branch into yours. First make sure you are on your branch (git branch will tell you what branch you are on, to exit hit q), then run git fetch origin and git merge origin/main. You may run into merge conflicts which occur when each branch makes changes to the same lines of code. VS Code has a nice built-in GUI for resolving merge conflicts, which allows you to select which change to make.
VS Code also a different UI to do all of the items mentioned above instead of using a terminal if you want to search it up.
In order to standardize between units, much of the Pi setup is automated or semi-automated. This guide will walk you through the steps of setting up your Pi the way we do. Along the way, there are also links for more information on how to customize this setup. This is an area where you will almost certainly need to customize some aspects of the setup.
Imaging your Pi
To start, download the Raspberry Pi Imager tool (or use your preferred software
for imaging SD cards). Imaging is basically giving the Raspberry Pi an operating system. On Ubuntu, you can install it like this:
sudo apt install rpi-imager
For other operating systems, download the tool from here.
Remember to choose your microSD card carefully as mentioned in hardware options
Launcher the imager
Select what version of Raspberry Pi you are using
Under “OS” select “Other general-purpose OS”
Select Ubuntu
Scroll until you find Ubuntu Server 24.04.xx LTS (64-bit). Make sure you get 64-bit, 32-bit will not work. Also make sure that the Raspberry Pi you are using is supported.
You want Ubuntu Server 24.04 LTS 64-bit and make sure your Pi is supported as shown in the highlight
Insert your SD card if you haven’t already done so, and select it
Skip customization, we will create our own user-data file to insert
Image the SD card
After imaging is complete, you should see a system-boot drive and maybe a writable drive. system-boot is more important.
Can't find system-boot?
If you see a different drive from the SD card that tells you to format it in order to read it, do not format it. The following information is likely Windows specific. If you can’t see the system-boot drive, it is likely because it wasn’t assigned a letter. You need admin privliages to fix this. Hit WIN + X and select “Disk Manager”. You will see the system-boot drive there, it just doesn’t have a letter. Right click on it and assign a letter. Click “add” on the pop up and assign it a letter. The drive should now be visible in your file explorer.
Cloud-init
Setup of the Raspberry Pi is semi-automated using cloud-init.
Cloud-init customization
The cloud-init setup is controlled by two files: user-data and network-config.
(You’ll use these files a couple of steps down.)
Examples of each are shown below, but you will likely need to modify these to suit
your purpose. We have pages on how to customize
network-config and user-data.
user-data Example
#cloud-config# This is the user-data configuration file for cloud-init.# The cloud-init documentation has more details:## https://cloudinit.readthedocs.io/system_info:default_user:name:ubuntu# Allow the default user to shutdown or reboot the system without entering a password (used by our automated scripts)sudo:"ALL=(ALL) NOPASSWD: /sbin/poweroff, /sbin/reboot, /sbin/shutdown"# On first boot, set the (default) ubuntu user's password to "cryosphere"chpasswd:expire:falseusers:- name:ubuntupassword:$6$rounds=4096$aQ7tu0.beL3WAL32$fKxKYvZpY7EMCoxAU1heRomA3v8WvgbqBhhz08QwOtQdlP/DJOP2BThqZFoRW8d2a9PaIKK9BC9NHs1qNnkya1type:hash# Enable password authentication with the SSH daemonssh_pwauth:true# Set a default timezonetimezone:Etc/UTC## Update apt database and upgrade packages on first bootpackage_update:truepackage_upgrade:true## Install additional packages on first bootpackages:- net-tools- git- cmake- g++- mosh- exfat-fuse- i2c-tools- rpi.gpio-common- util-linux-extra- gpsd- gpsd-clients## Write arbitrary files to the file-systemwrite_files:- path:/home/ubuntu/initial_setup.shcontent:| #!/bin/bash
exec > >(tee -a "initial_setup_output.log") 2>&1
# Miniconda Setup
wget --progress=bar:force:noscroll "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh" -O $HOME/miniconda.sh
bash $HOME/miniconda.sh -b -p $HOME/miniconda
cd $HOME
source .profile
source miniconda/etc/profile.d/conda.sh
conda init bash
# Setup logger environment
git clone git@github.com:thomasteisberg/uav_radar_logger.git
# Clone uhd_radar repo
git clone git@github.com:radioglaciology/uhd_radar.git
cd uhd_radar
#git checkout thomas/dask # Uncomment if you want to check out a specific branch other than main
conda env create -n uhd -f environment-rpi.yaml
conda activate uhd
python /home/ubuntu/miniconda/envs/uhd/lib/uhd/utils/uhd_images_downloader.py
systemctl --user enable radar.service
systemctl --user enable logger.service
ifconfig
sudo rebootappend:true- path:/home/ubuntu/.profilecontent:| PATH=/home/ubuntu/miniconda/bin:$PATH
source /home/ubuntu/.bashrcappend:true- path:/home/ubuntu/.ssh/known_hostscontent:| github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=- path:/etc/security/limits.conf# Recommended by Ettus https://kb.ettus.com/USRP_Host_Performance_Tuning_Tips_and_Trickscontent:| ubuntu - rtprio 99append:true- path:/etc/systemd/user/radar.servicecontent:| [Unit]
Description=Service to run the radar code on startup
[Service]
Type=simple
WorkingDirectory=/home/ubuntu/uhd_radar/
ExecStart=/home/ubuntu/uhd_radar/manager/radar_service.sh
Restart=always
RestartSec=10
KillSignal=SIGINT
[Install]
WantedBy=default.target- path:/etc/systemd/user/logger.servicecontent:| [Unit]
Description=Service to log data from I2C sensors and automatically shutdown below a voltage threshold
[Service]
Type=simple
WorkingDirectory=/home/ubuntu/uav_radar_logger/
ExecStart=/home/ubuntu/uav_radar_logger/logger_service.sh
Restart=always
RestartSec=60
KillSignal=SIGINT
[Install]
WantedBy=default.target# Run arbitrary commands at rc.local like time# These commands are run with root permissions# If you want commands run as a normal user, put them in initial_setup.sh (see above)# which is run as the "ubuntu" user (see below)runcmd:- chown -R ubuntu:ubuntu /home/ubuntu- chmod +x /home/ubuntu/initial_setup.sh- wget -O /etc/udev/rules.d/uhd-usrp.rules https://raw.githubusercontent.com/EttusResearch/uhd/master/host/utils/uhd-usrp.rules- usermod -a -G i2c ubuntu- usermod -a -G dialout ubuntu- usermod -a -G tty ubuntu- apt remove -y modemmanager- systemctl stop serial-getty@ttyS0.service && systemctl disable serial-getty@ttyS0.service- i2cdetect -y 1- echo "dtoverlay=i2c-rtc,pcf8523" >> /boot/firmware/config.txt- loginctl enable-linger ubuntu- mkdir /media/ssd- chown ubuntu /media/ssd- chgrp ubuntu /media/ssd- echo "/dev/sda2 /media/ssd exfat defaults,nofail,uid=1000,gid=1000 0 2" | tee -a /etc/fstab
network-config Example
# This file contains a netplan-compatible configuration which cloud-init will# apply on first-boot (note: it will *not* update the config after the first# boot). Please refer to the cloud-init documentation and the netplan reference# for full details:## https://cloudinit.readthedocs.io/en/latest/topics/network-config.html# https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v2.html# https://netplan.io/referenceversion:2ethernets:eth0:# Your ethernet name.dhcp4:noaddresses:[192.168.11.137/24]gateway4:192.168.11.1nameservers:addresses:[8.8.8.8,8.8.4.4]wifis:renderer:networkdwlan0:dhcp4:trueoptional:trueaccess-points:"<YOUR WIFI SSID HERE>":password:"<YOUR WIFI PASSWORD HERE>"
network-config Example for Laptop Mobile Hotspot and Possibly Normal Wifi
# This file contains a netplan-compatible configuration which cloud-init will# apply on first-boot (note: it will *not* update the config after the first# boot). Please refer to the cloud-init documentation and the netplan reference# for full details:## https://cloudinit.readthedocs.io/en/latest/topics/network-config.html# https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v2.html# https://netplan.io/referencenetwork:version:2renderer:networkdwifis:wlan0:dhcp4:yesaccess-points:"<WIFI SSID HERE>":password:"<PASSWORD HERE>"
If your wifi SSID or password has slashes, it might freak the Raspberry Pi out and the network-config won’t run properly.
After you edit the user-data and network-config files and add them to your SD card. You can now put the card back into the Pi.
# This file contains a netplan-compatible configuration which cloud-init will# apply on first-boot (note: it will *not* update the config after the first# boot). Please refer to the cloud-init documentation and the netplan reference# for full details:## https://cloudinit.readthedocs.io/en/latest/topics/network-config.html# https://cloudinit.readthedocs.io/en/latest/topics/network-config-format-v2.html# https://netplan.io/referenceversion:2ethernets:eth0:# Your ethernet name.dhcp4:noaddresses:[192.168.11.137/24]gateway4:192.168.11.1nameservers:addresses:[8.8.8.8,8.8.4.4]wifis:renderer:networkdwlan0:dhcp4:trueoptional:trueaccess-points:"<YOUR WIFI SSID HERE>":password:"<YOUR WIFI PASSWORD HERE>"
The above configuration sets up a static IP over the ethernet interface. It
also configures 192.168.11.1 as the default gateway. This allows for sharing
an internet connection from a computer over this interface if desired.
The configuration also provides an SSID and password for a WiFi network. In practice,
we configure this to the settings for a phone hotspot that can be used to get
internet when WiFi is not otherwise available. This is also a simpler setup for
getting the Pi on the internet when needed.
Reconfiguring with netplan
By default, network interfaces are configured with netplan. See
the netplan documentation
for more details.
By default, the cloud-init script sets up a static IP of 192.168.11.137, but
you could choose to configure this to something different for each payload box.
Our usual way of connecting is by plugging an ethernet cable into the Pi and
connecting it to a laptop. You can read about
all the networking options here.
Understanding the user-data file and any edits you may want to make
Use this when setting up your Raspberry Pi on initial boot-up.
The default user-data we start from is as shown below. You will likely need to
tweak many of these settings. Descriptions and tips for the most important
sections are below.
Note that this is one of two key configuration files. You can read about
network-config here.
Starting point user-data file
#cloud-config# This is the user-data configuration file for cloud-init.# The cloud-init documentation has more details:## https://cloudinit.readthedocs.io/system_info:default_user:name:ubuntu# Allow the default user to shutdown or reboot the system without entering a password (used by our automated scripts)sudo:"ALL=(ALL) NOPASSWD: /sbin/poweroff, /sbin/reboot, /sbin/shutdown"# On first boot, set the (default) ubuntu user's password to "cryosphere"chpasswd:expire:falseusers:- name:ubuntupassword:$6$rounds=4096$aQ7tu0.beL3WAL32$fKxKYvZpY7EMCoxAU1heRomA3v8WvgbqBhhz08QwOtQdlP/DJOP2BThqZFoRW8d2a9PaIKK9BC9NHs1qNnkya1type:hash# Enable password authentication with the SSH daemonssh_pwauth:true# Set a default timezonetimezone:Etc/UTC## Update apt database and upgrade packages on first bootpackage_update:truepackage_upgrade:true## Install additional packages on first bootpackages:- net-tools- git- cmake- g++- mosh- exfat-fuse- i2c-tools- rpi.gpio-common- util-linux-extra- gpsd- gpsd-clients## Write arbitrary files to the file-systemwrite_files:- path:/home/ubuntu/initial_setup.shcontent:| #!/bin/bash
exec > >(tee -a "initial_setup_output.log") 2>&1
# Miniconda Setup
wget --progress=bar:force:noscroll "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh" -O $HOME/miniconda.sh
bash $HOME/miniconda.sh -b -p $HOME/miniconda
cd $HOME
source .profile
source miniconda/etc/profile.d/conda.sh
conda init bash
# Setup logger environment
git clone git@github.com:thomasteisberg/uav_radar_logger.git
# Clone uhd_radar repo
git clone git@github.com:radioglaciology/uhd_radar.git
cd uhd_radar
#git checkout thomas/dask # Uncomment if you want to check out a specific branch other than main
conda env create -n uhd -f environment-rpi.yaml
conda activate uhd
python /home/ubuntu/miniconda/envs/uhd/lib/uhd/utils/uhd_images_downloader.py
systemctl --user enable radar.service
systemctl --user enable logger.service
ifconfig
sudo rebootappend:true- path:/home/ubuntu/.profilecontent:| PATH=/home/ubuntu/miniconda/bin:$PATH
source /home/ubuntu/.bashrcappend:true- path:/home/ubuntu/.ssh/known_hostscontent:| github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCj7ndNxQowgcQnjshcLrqPEiiphnt+VTTvDP6mHBL9j1aNUkY4Ue1gvwnGLVlOhGeYrnZaMgRK6+PKCUXaDbC7qtbW8gIkhL7aGCsOr/C56SJMy/BCZfxd1nWzAOxSDPgVsmerOBYfNqltV9/hWCqBywINIR+5dIg6JTJ72pcEpEjcYgXkE2YEFXV1JHnsKgbLWNlhScqb2UmyRkQyytRLtL+38TGxkxCflmO+5Z8CSSNY7GidjMIZ7Q4zMjA2n1nGrlTDkzwDCsw+wqFPGQA179cnfGWOWRVruj16z6XyvxvjJwbz0wQZ75XK5tKSb7FNyeIEs4TT4jk+S4dhPeAUC5y+bDYirYgM4GC7uEnztnZyaVWQ7B381AK4Qdrwt51ZqExKbQpTUNn+EjqoTwvqNj4kqx5QUCI0ThS/YkOxJCXmPUWZbhjpCg56i+2aB6CmK2JGhn57K5mj0MNdBXA4/WnwH6XoPWJzK5Nyu2zB3nAZp+S5hpQs+p1vN1/wsjk=- path:/etc/security/limits.conf# Recommended by Ettus https://kb.ettus.com/USRP_Host_Performance_Tuning_Tips_and_Trickscontent:| ubuntu - rtprio 99append:true- path:/etc/systemd/user/radar.servicecontent:| [Unit]
Description=Service to run the radar code on startup
[Service]
Type=simple
WorkingDirectory=/home/ubuntu/uhd_radar/
ExecStart=/home/ubuntu/uhd_radar/manager/radar_service.sh
Restart=always
RestartSec=10
KillSignal=SIGINT
[Install]
WantedBy=default.target- path:/etc/systemd/user/logger.servicecontent:| [Unit]
Description=Service to log data from I2C sensors and automatically shutdown below a voltage threshold
[Service]
Type=simple
WorkingDirectory=/home/ubuntu/uav_radar_logger/
ExecStart=/home/ubuntu/uav_radar_logger/logger_service.sh
Restart=always
RestartSec=60
KillSignal=SIGINT
[Install]
WantedBy=default.target# Run arbitrary commands at rc.local like time# These commands are run with root permissions# If you want commands run as a normal user, put them in initial_setup.sh (see above)# which is run as the "ubuntu" user (see below)runcmd:- chown -R ubuntu:ubuntu /home/ubuntu- chmod +x /home/ubuntu/initial_setup.sh- wget -O /etc/udev/rules.d/uhd-usrp.rules https://raw.githubusercontent.com/EttusResearch/uhd/master/host/utils/uhd-usrp.rules- usermod -a -G i2c ubuntu- usermod -a -G dialout ubuntu- usermod -a -G tty ubuntu- apt remove -y modemmanager- systemctl stop serial-getty@ttyS0.service && systemctl disable serial-getty@ttyS0.service- i2cdetect -y 1- echo "dtoverlay=i2c-rtc,pcf8523" >> /boot/firmware/config.txt- loginctl enable-linger ubuntu- mkdir /media/ssd- chown ubuntu /media/ssd- chgrp ubuntu /media/ssd- echo "/dev/sda2 /media/ssd exfat defaults,nofail,uid=1000,gid=1000 0 2" | tee -a /etc/fstab
Password-less shutdown
system_info:
default_user:
name: ubuntu # Allow the default user to shutdown or reboot the system without entering a password (used by our automated scripts)
sudo: "ALL=(ALL) NOPASSWD: /sbin/poweroff, /sbin/reboot, /sbin/shutdown"
One of the features supported by the uav_radar_logger utility is to automatically
cleanly shutdown the system if the measured battery voltage drops below a
threshold. To facilitate this, the default user must be able to shutdown the
system without needing additional authentication. This gives permission for the
ubuntu user to call sudo shutdown or sudo reboot without entering a password.
Password authentication
# On first boot, set the (default) ubuntu user's password to "cryosphere"
chpasswd:
expire: false
list:
- ubuntu:$6$rounds=4096$aQ7tu0.beL3WAL32$fKxKYvZpY7EMCoxAU1heRomA3v8WvgbqBhhz08QwOtQdlP/DJOP2BThqZFoRW8d2a9PaIKK9BC9NHs1qNnkya1
# Enable password authentication with the SSH daemon
ssh_pwauth: true
This sets up a default password for the ubuntu user. You should change this to
something else (or disable password authentication completely, if you prefer).
Passwords are stored in a hashed format. You can generate password hashes using
this utility:
mkpasswd --method=SHA-512 --rounds=4096
Timezone
# Set a default timezone
timezone: Etc/UTC
You could set this to other time zones (i.e. `America/Los_Angeles"), but really
it would make everyone’s life easier if you just set your clock to UTC.
Add SSH keys through GitHub
## On first boot, use ssh-import-id to give the specific users SSH access to
## the default user
ssh_import_id:
- gh:thomasteisberg
- gh:albroome
- gh:dfxmay
You can very conveniently enable key-based authentication for specific GitHub
user names. If your username is in here and you have a public key setup with GitHub,
this public key will be imported and you will be able to SSH into your Pi
with no additional setup. You might want to remove us from your list, though. :)
Files
Arbitrary files can be written to the system with cloud-init. Some of these are
important.
initial_setup.sh
- path: /home/ubuntu/initial_setup.sh
content: |
#!/bin/bash
exec > >(tee -a "initial_setup_output.log") 2>&1
# Miniconda Setup
wget --progress=bar:force:noscroll "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-aarch64.sh" -O $HOME/miniconda.sh
bash $HOME/miniconda.sh -b -p $HOME/miniconda
cd $HOME
source .profile
source miniconda/etc/profile.d/conda.sh
conda init bash
# Setup logger environment
git clone git@github.com:thomasteisberg/uav_radar_logger.git
# Clone uhd_radar repo
git clone git@github.com:radioglaciology/uhd_radar.git
cd uhd_radar
#git checkout thomas/dask # Uncomment if you want to check out a specific branch other than main
conda env create -n uhd -f environment.yaml
conda activate uhd
python /home/ubuntu/miniconda/envs/uhd/lib/uhd/utils/uhd_images_downloader.py
systemctl --user enable radar.service
systemctl --user enable logger.service
ifconfig
sudo reboot
append: true
The initial_setup.sh script grabs copies of our code and sets up the radar and
logging services. This script is intended to be manually run the first time you
SSH into the system. This enables you to use
SSH agent forwarding
to provide any needed GitHub authentication to get the code.
This is also where you would customize the repositories to check out (if, for
example, you’ve forked our code) and where you can pick a branch to automatically
checkout.
Radar and Logger services
- path: /etc/systemd/user/radar.service
content: |
[Unit]
Description=Service to run the radar code on startup
[Service]
Type=simple
WorkingDirectory=/home/ubuntu/uhd_radar/
ExecStart=/home/ubuntu/uhd_radar/manager/radar_service.sh
Restart=always
RestartSec=10
KillSignal=SIGINT
[Install]
WantedBy=default.target
- path: /etc/systemd/user/logger.service
content: |
[Unit]
Description=Service to log data from I2C sensors and automatically shutdown below a voltage threshold
[Service]
Type=simple
WorkingDirectory=/home/ubuntu/uav_radar_logger/
ExecStart=/home/ubuntu/uav_radar_logger/logger_service.sh
Restart=always
RestartSec=60
KillSignal=SIGINT
[Install]
WantedBy=default.target
Two systemd services are used to manage everything. One run the radar code in
its default button-controlled setup. The other runs basic logging of I2C-connected
sensors and handles automatic low-battery shutdown.
Some final setup is done by running arbitrary commands. These are run as the root
user.
One aspect of this you may wish to customize are the last two lines, which add
settings to automatically mount an ExFAT-formatted SSD plugged into the Pi. This
can be (optionally) used as a storage location for radar data.
Testing changes
You may want to test your changes before using them on your Pi. Options for doing
that are described here.
Note that the initial_setup.sh script downloads miniconda for the aarch64
architecture, which probably won’t work on your computer. If you want to test that
part, you’ll need to change this.
Options for connecting to the Raspberry Pi in order to transmit desired data or set parameters.
Connecting to the Pi
We will be using SSH to connect your laptop to the Pi. You can do this either over wifi or ethernet. Before doing this, we need to get the IP address of the Pi and import your public SSH key onto the Pi.
Direct Control
This is the process to get the IP address of the Pi and import your public SSH key.
If you use your laptop’s mobile hotspot, you will be able to see the IP address of the PI but you still need to do direct control to import your SSH key.
This method requires a monitor and keyboard, cannot be used to share files between a laptop and the Pi, and is more difficult to use. However, we need to use this, mainly to import your SSH key. This is also useful in case the network-config isn’t working. Direct control allows you to edit the file that controls this.
To access the Pi’s terminal directly you will need:
Raspberry Pi 5
Pi Power Supply (plugged into wall)
Monitor (plugged into wall)
HDMI to Micro-HDMI cable
Keyboard
Ethernet cable connected to a router (or ethernet port on the wall of the lab) or just connect the Pi to wifi
Simply connect the ethernet (or just use WiFi), micro-HDMI, keyboard, and power supply to the Raspberry Pi. When it boots, you will see the cloud-init running a bunch of things and the Pi’s Ubuntu Server terminal on the monitor.
If the Pi get stuck on a boot page and keeps cycling through booting through USB-MSD, SD, and NVME, it can’t find the boot files. You may have imaged the SD card for something that doesn’t support the type of Pi you have so you’ll have to reimage it. If you have a small light on your Pi, you may have a tiny button next to it which you can hold to power it off.
Running Cloud-init
Power up the Pi and wait for cloud-init to run.
Within about a minute, your Pi should connect to whatever network interface(s)
are described in network-config and you should be able to find it on the
network. If you setup some sort of key-based authentication (such as by
importing a key from GitHub), it may take an extra couple of minutes for
this to be ready.
After the network setup is complete, you should be able to login over SSH.
In particular, please note that you need to have SSH agent forwarding working on your laptop.
You should have already done this under ORCA Setup when you first made your SSH key. You can test that everything is working by running ssh -T git@github.com.
When you first login, cloud-init may not have finished running. To check the status, run:
cloud-init status --long
There are also logs in /var/log/cloud-init-output.log.
To keep an eye on the entire process, you can run:
watch "cloud-init status --long && tail -n 10 /var/log/cloud-init-output.log"
Expect this process to take a few minutes to complete.
Initial Setup
When you are able to start running commands, run ./initial_setup.sh. This will log to /home/ubuntu/initial_setup_output.log. It may take around 10 minutes to complete. It will automatically reboot your Pi at the end. If you don’t want this, feel free to comment out the last line.
After this process finishes running, run ping 8.8.8.8 to test if it is connected to wifi/ethernet. If the Pi isn’t connected, it will say “Network is unreachable”. If the Pi is connected, it will start detecting bytes sent by the address. Hit CTRL + C to stop the pinging.
Not connecting to your wifi/ethernet?
If the Pi isn’t connecting to the wifi, the network-config file might not be formatted properly. One issue that I ran into was using “wlp2s0b1:” under the “wifis:” section (I was connecting to a laptop’s mobile hotspot). If you run ip link it will list the different formats that it is looking for. In my case, it was looking for “wlan0” for wifi or “eth0” for ethernet.
Here is how to edit your network-config files without having to take the SD card out.
Run ls /etc/netplan/. It should show a .yaml.
Run sudo nano /etc/netplan/FILENAME.yaml. This allows you to open and edit the file.
Change whatever you need to, then hit CTRL + X, then y, then hit enter. This saves your edits.
Run sudo netplan apply to apply these changes
Try pinging 8.8.8.8 again to see if is connected now
You may need to run sudo reboot
You can log in and run commands directly with the keyboard (no mouse inputs). There is no way to scroll up through this terminal however, so if you want to be able to read a long output from a command you must pipe it into a file (ex. python run.py >> terminal_output.txt), then read the text file using nano.
Importing Your SSH Key
You then need to add this SSH to the Pi. The simplest method is to first add the key to your GitHub account, then import it onto the Pi from there. If you don’t want to set up GitHub, you can add the key directly with a little extra work.
With GitHub:
You should have already added the SSH key to your GitHub account.
Run ssh-import-id gh:<your-github-username> on the Raspberry Pi with the direct control
If you haven’t yet, do the following:
Create an account on GitHub and sign in.
In GitHub, open settings and go to the SSH and GPG keys tab and add a new SSH key.
Name this key whatever you want and paste the key into the correct field.
Log into the Pi using the direct control method above.
Run ssh-import-id gh:<your-github-username>.
Without GitHub:
Log into the Pi using the direct control method above.
Open the authorized keys file with sudo nano ~/.ssh/authorized_keys.
Manually copy your key (starts with ssh-ed25519, ends with your email) into the file
Hit Ctrl+X followed by Y, then Enter to save the changes.
You should now have permission to SSH into the Pi from your laptop using one of the following methods (wifi or ethernet).
Modify your ~/.ssh/config file (use nano ~/.ssh/config) and add an entry like this enabling SSH agent forwarding (or don’t, you likely already set up SSH agent forwarding on your laptop so I don’t think you need to do this):
Host 192.168.11.137
HostName 192.168.11.137
User ubuntu
ForwardAgent yes
Note that if your username or host IP address is different, you should adjust it accordingly.
Remote host identification has changed
If you use the same static IP for multiple Pi’s (which, presumably, you only
ever use one of at a time), you may encounter an error stating:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
This is because your computer thinks its connecting to a different Raspberry Pi.
You can manually add the fingerprint for the currently connected Pi like this:
(This would be a bad idea to do at random for a remote computer. I’m assuming
here that you’ve just plugged in a new Pi right in front of you and you
know exactly why you’re getting this error. You should only have to do this once
per new Pi.)
You might be able to just run ssh ubuntu@<pi-ip-address> on your Pi to SSH connect. The direct connect and internet connection should already exist since you needed them previously to import your GitHub key. You can get your Pi’s IP address by running hostname -I or ip a (in my opinion, using hostname -I is easier cause you don’t need to hunt for the ip info).
SSH over Ethernet:
This is the preferred method for connecting to and controlling the Pi , and the only method that does not require the Pi to be connected to a router or Wi-Fi network. However, it does take a bit of setup the first time.
For this method, you will need:
Laptop connected to Wi-Fi
Raspberry Pi 5
Pi Power Supply (plugged into wall)
Ethernet cable
Ethernet to usb-c adapter (if your laptop doesn’t have an ethernet port)
Plug the power supply into the Pi and plug one end of the ethernet cable into the Pi, and the other into your laptop.
Connect your laptop to any Wi-Fi network.
If your laptop’s public SSH key is not already on the Pi, see the section above for how to add it. (Using direct connect)
If this is your first time setting up this method, you will now need to enable internet sharing on your laptop. If you have done this before, then skip this step.
a. Windows:
i. Open Control Panel and go to the Network section.
ii. Find the Wi-Fi connection and right click on it, then go to Properties.
iii. At the top, click on the Sharing tab.
iv. Check “Allow other network users to connect…”
v. In the dropdown, select “Ethernet2” (not the ethernet for WSL).
vi. Apply the changes.
b. Linux:
i. Install Network Manager Command-line Interface (nmcli) with sudo apt install network-manager .
ii. Find the connection name with nmcli con show . Find the entry with type ethernet, it should have a name like “Wired connection 1”.
iii. Run nmcli con modify “Wired connection 1” ipv4.method shared .
If you are on Linux, run nmcli con up “Wired connection 1”
Find the Pi’s IP address on your local subnet.
a. If you are on Windows, open PowerShell and run arp -a. You should see an interface for 192.168.137.1 and within that section should be an IP address that starts with 192.168.137 and ends with something other than .0 or .1 (ex. 192.168.137.27).
b. If you are on Linux, then Pi #1 always has the IP 10.42.0.10, and Pi #2 always has the IP 10.42.0.20. If for some reason you cannot find the IP, confirm the subnet is 10.42.0 by running ip a . Under the enxc… section should say “state UP” and you should see “inet 10.42.0.1/24”. You can then scan the subnet to find the pi by running nmap -sn 10.42.0.1/24 and looking for a device that’s not 10.42.0.1. You may need to restart the Pi and give it a minute to boot.
Run ssh ubuntu@<pi-ip-address> to connect to the Pi. You can now run commands on the Pi, and transfer files to and from your laptop using SCP (will be explained below).
SSH over Wi-Fi:
This method is nice as it requires less cables and can be used for connecting multiple devices, however you will have to use one of the other methods such as SSH over Ethernet initially to find the Pi’s internet IP address.
For this method, you will need:
Laptop connected to Wi-Fi
Raspberry Pi 5
Pi Power Supply (plugged into wall)
Ethernet cable connected to a router (or to the ethernet port on the wall of the lab) if not connecting the Pi to Wi-Fi
Plug the ethernet and power cable into the Pi and turn it on.
If you do not know what the Pi’s current IP address is, you must first use the Direct Control method above to get access to the terminal. When the Pi first boots, system information is printed to the terminal. In the bottom right corner of this message, you should see a section that says “IPv4 address for eth0: 128.138.189.xxx”. You can also find the IP address by running ip a and looking for the address under the eth0This address may change each time the Pi is reconnected to the internet.
Connect your laptop to a wifi network.
Check if you can find the Pi over the internet by running the command
ping -c 1 your.pi.ip.address. On Windows, this must be done in PowerShell with admin privileges, not WSL. If it says 0 packets received, then either the IP address is incorrect, or you are not on the same network as the Pi.
If your laptop’s public SSH key is not already on the Pi, see the section above (Importing Your SSH Key section) for how to add it.
Run ssh ubuntu@your.pi.ip.address to connect to the Pi. If you chose a different login username, replace ubuntu with that. You can now run commands on the Pi, and transfer files to and from your laptop using SCP (see below).
If you SSH into your pi from your laptop, you can type exit or logout to turn your powershell back to normal.
Cloning the Repository onto the Pi
Run git clone https://github.com/username/repositoryname to add the uhd-radar github repository to the Pi. If you don’t have the https:// it won’t work. Using SSH (the link that ends with .git) also won’t work because your Pi doesn’t have your laptop’s private key. Don’t give your Pi your private SSH key.
Transferring files to and from the Pi:
The Raspberry Pi 5 unfortunately does not support data transfer (USB OTG) over its USB 3.0 ports, only the USB C port which we currently use for power. Fortunately, we can make use of the SSH connection to send files to and from the Pi using SCP and/or GitHub.
If you have committed changes to the code and pushed them to GitHub, you can just checkout the correct branch and run git pull on the Pi to see them. However, if you are debugging or making small changes to a file that aren’t worthy of a commit, you can send files directly with SCP (secure copy protocol) by running the following command on your laptop.
Send a single file with scp <my-file-path> ubuntu@<pi-ip-address>:<pidirectory-path>
The "." in windows and the "~" in ubuntu act the same way. They both make it start in the home directory so you don’t have to type all of it out. The "." for windows puts you in C:/Users/YourName and the "~" for ubuntu puts you in /home/AccountUsername.
You can also send a whole folder with scp -r <my-directory-path> ubuntu@<piip-address>:<pi-directory-path>
To send files from the Pi back to your laptop, reverse the two arguments ensuring the first is one or more files, or directory, and the second is a directory for where the file should go.
This pulled from /home/username and put it in C:/Users/Name/Downloads
If you push or pull a file that has the same name in the other device, the new file pushed/pulled will overwrite the old file.
When using these commands, you are typing them on your laptop powershell. You are either pushing from your laptop to the Pi, or you are using your laptop to pull from the Pi. You can also push from the Pi but that’s a different command.
Installing Miniconda
First go to Anaconda’s website and scroll to the bottom to download Miniconda. You will want the Linux 64-Bit ARM64 version.
Once the file is downloaded, you will want to use SCP to get the file onto the Pi. Make sure you have connected to the Pi using SSH. The command might look something like scp .\Downloads\Miniconda3-latest-Linux-aarch64.sh ubuntu@192.168.137.131:~/.
Within the Raspberry Pi’s terminal, run bash location-to-file/Miniconda3-latest-Linux-aarch64.sh and accept the default options in the installer (select yes when prompted about auto_activate_base, though we will change this later)
After Miniconda is installed, reboot the Raspberry Pi with sudo reboot now
To ensure it has been installed, run “conda list” and you should see a list of the installed dependencies printed out.
We are now going to change one of the default settings with the command conda config --set auto_activate_base false
5 - Runtime overview
Overview of the code’s architecture
Conda environment setup
All of the required dependencies can be installed as a conda environment using
the environment.yaml file in the repository. More instructions can be found
in the README
file. When creating the environment, make sure your directory is in the right spot where environment.yaml can be found. You don’t need to run the code yet, we will go over that in the next step.
Startup scripts
The X series devices require some initial network configuration. For convenience,
a startup script
is provided to automate this setup. You may need to tweak this file to your setup.
Runner scripts
The basic steps required to run the radar are:
Build the C++ code
Generate a chirp file to transmit based on your configuration
Run the compiled radar code
Move the collected data to an appropriate location
The main interface for running the radar code is through run.py, a Python
script designed to automate the above process. This script is run as follows (you don’t need to run this now, we go into more detail in the next step):
python run.py config/my_radar_configuration.yaml
At the end of the data collection, data will be saved with the current date
to a location specified in the YAML config file.
Generally, three files are saved:
YYYYMMDD_hhmmss_rx_samps.bin - This is a binary file containing the raw
samples recorded the SDR. Note that this file is not interpretable unless you
also have the config file used.
YYYYMMDD_hhmmss_config.yaml - This is the YAML config file passed to run.py.
It defines all parameters of the data collection, allowing for the rx_samps.bin
file to be interpreted and processed.
YYYYMMDD_hhmmss_uhd_stdout.log - This is a text file containing the output
of running the radar code. This is helpful for debugging and also contains a log
of any errors encountered, which may be required to reconstruct the timing of
each recording.
More details on the files stored and how these can be re-processed into a Zarr
file are on the file formats page.
Note that there are also settings available to break rx_samps.bin into multiple
files as needed.
SDR interface code
For performance reasons, the code directly interfacing with the SDR is written
in C++. This code is all located in the sdr/ directory of the repository.
The main radar code is contained in main.cpp (with some SDR setup code located
in rf_settings.cpp). The radar code runs in two threads, as shown in the
figure below.
General architecture of the ORCA code
One thread is responsible for scheduling
timed commands
that are enqueued into FIFO queues within the SDR’s FPGA.
The other thead is responsible for pulling received samples from the SDR and
writing them to a file on the host computer.
For a more complete overview, please refer to our paper:
T. O. Teisberg, A. L. Broome and D. M. Schroeder, “Open Radar Code Architecture (ORCA): A Platform for Software-Defined Coherent Chirped Radar Systems,” in IEEE Transactions on Geoscience and Remote Sensing, vol. 62, pp. 1-11, 2024, Art no. 5109411, doi: 10.1109/TGRS.2024.3446368.