-
Notifications
You must be signed in to change notification settings - Fork 4
ODroid Setup
Things you will need:
- USB A - Micro B OTG cable
- Power for the ODroid
- Balena Etcher
- SD card (8GB or above)
- PC (will be called groundstation throught the rest of the document)
Caution
The ODroid M1s features onboard eMMC storage. To gain read/write permissions for uploading the OS onto the ODroid M1s, a special SD card with a flashed image is required.
Warning
Please ensure that the image transfer process in Balena Etcher is fully completed before unplugging the ODroid from power.
Tip
Balena Etcher is used as the example software here. However, you can use other tools as well, such as Raspberry Pi Imager if you are comfortable with the software.
Procedure:
-
Download the
ODROID-M1S_EMMC2UMS.imgand flash it to the SD card using Balena Etcher. This SD card is analogous to a hardware key that puts the ODroid's eMMC in read/write mode. - Ensure the ODroid M1S is powered off. Plug the SD card with the newly flashed image into the card slot of the ODroid M1S. Then power the board using the power adapter or by plugging it into the groundstation PC.
- Plug in the USB A - Micro B OTG cable into the OTG port of the ODroid M1s and connect it to the groundstation pc. You should then see the ODroid M1s eMMC show up as a mass storage device. i.e, it lets you write directly to the eMMC on board.
- Download the latest image from the ODroid Wiki. Please take care to download the server flavor of the Ubuntu distros that are available.
- Follow the normal flashing procedure, using the image from Step 4 to flash the mass storage device from Step 3.
- Once it is done flashing the new image onto the eMMC, disconnect power to the ODroid M1s and only then unplug the SD card. Your ODroid is now flashed.
Things you will need:
- Keyboard
- HDMI cable
- Monitor
- Ethernet connection
- USB-UART Module
- ODroid M1s RTC battery
Note
The username is odroid and the password is odroid. You'll be prompted to login on boot.
Caution
- During the first boot, connect only the HDMI port and the Ethernet cable. Wait for the system to boot, then connect the keyboard to the USB 3.1 port and the WiFi module to the middle USB 2.0 port. You can distinguish between the ports by their color: USB 3.0 is blue, and USB 2.0 is black.
- Have the RTC battery unplugged.
Connect the ODroid to a monitor and keyboard, power it on via the USB‑C port, then connect it to the internet using an Ethernet cable. Once logged in, verify the time by running
dateIt should show an output that is similar to
Fri May 16 13:30:44 EDT 2025We need to pay attention to the time zone here, EDT. Make sure it's on the right time-zone, if not set it using,
sudo dpkg-reconfigure tzdataA dialogue box will pop up with the various countries and time zones. Use the arrow keys to navigate and the Enter key to select, then verify that the time zone is set correctly with the date command again.
Note
Since Virginia Tech follows New York time, the output, once the date is set looks like this
Current default time zone: 'America/New_York'
Local time is now: Fri May 16 13:32:35 EDT 2025.
Universal Time is now: Fri May 16 17:32:35 UTC 2025.Be sure to add yourself in the tty and dialout groups via usermod to avoid having to execute scripts as
root.
sudo usermod -a -G tty odroid
sudo usermod -a -G dialout odroidReboot the system after by typing in
sudo reboot nowTip
If the Odroid has trouble booting up, remove the power, disconnect the keyboard and WiFi module, and then reconnect the power. Once it has booted up, plug the keyboard and WiFi module back into their respective ports.
Update the system using
Important
- Use the exact commands given below to upgrade the system.
- Have the Wifi 5BK module pluggedd in.
sudo apt update
sudo apt-get upgradeNote
If prompted enter the password and if there is a query that asks to "accept changes" input y using the keyboard and press the enter key. That should start the update.
Update the repositories first
sudo apt-get updateInstall the following packages
sudo apt-get install -y git nano libasio-dev usbutils linux-firmware dkms software-properties-common lsb-release build-essential make g++ gccafter this step is completed, install the linux-headers.
sudo apt-get install linux-headers-$(uname -r)Now, do a full system upgrade
sudo apt-get update
sudo apt-get full-upgradeNote
git: Distributed version control system for tracking changes in source code during software development.
nano: Simple, user-friendly command-line text editor for editing files in the terminal.
libasio-dev: Development headers for Asio, a modern C++ library for asynchronous network and low-level I/O programming.
usbutils: Utilities for inspecting and listing devices connected to the USB bus, such as lsusb.
linux-firmware: Collection of binary firmware files required for the proper operation of various hardware devices.
dkms: Framework that automatically rebuilds and installs kernel modules when the kernel is upgraded.
software-properties-common: Scripts and tools for managing software repositories and PPAs on Debian-based systems.
lsb-release: Utility to display Linux Standard Base and distribution-specific information.
build-essential: Meta-package that installs essential tools (like gcc, g++, make) needed to compile C/C++ software.
make: Utility that automates the building and compilation of programs using instructions from a Makefile.
g++: GNU C++ compiler for compiling C++ source code.
gcc: GNU Compiler Collection’s C compiler for compiling C source code.
linux-headers-$(uname -r): Installs the Linux kernel header files for your current running kernel, which are required to compile kernel modules and interface properly with kernel APIs
Warning
Please setup the time by following the instructions in section 2.1 before proceeding with setting up the RTC clock. Furthermore, make sure the Ethernet cable is plugged in.
Installing the RTC Battery on ODroid M1S
-
Locate the RTC Battery Connector
The RTC battery connector is on the back of the board. The plug is keyed, meaning it can only be inserted in one direction. -
Install the Battery Plug Carefully
- Gently insert the plug into the connector.
⚠️ The RTC plug is fragile — handle it with care to avoid damage.
- Mount the Battery
- Use the double-sided tape provided on the back of the battery.
- Stick the battery to the back of the board.
- Avoid areas with PCB traces or other components.
Tip
Do not place the battery in the rectangular space allocated for the PCIe slot if you plan on using it for storage on a later date.
Caution
Ensure the battery is secure and nothing is obstructing other connections or components on the board.
Note
We want a RTC clock as the logs and udp communications utilized by the flightstack need accurate real-time timestamps.
Once the battery is mounted, it should power up the RTC circuit and have it started. We can now proceed to configure the ODroid to use the clock for time keeping.
sudo hwclock -w -f /dev/rtc0This should write our system time to the RTC. We now need to switch off the option to sync time from the internet.
sudo timedatectl set-ntp falseImportant
Do not forget to switch off the option to sync from the internet. This ensures that the OS does not look for a network time sync during boot time. This makes booting up faster and also provides us the ability to have accurate times without relying on the internet which we will not be accessing during tests.
Now run the following command to ensure that the RTC and the system time are sync'd up.
sudo hwclock -r; dateImportant
Make sure the time and date on the first line matches the second line of the output in the terminal
The final step is to write some code that makes the system time sync to the time of the RTC clock upon boot and not the internet. Run the following code in the terminal.
sudo nano /etc/rc.localThis will open up a file in nano. Scroll down all the way to the end and add the following before the exit 0 line.
# Start RTC sync on bootup
if [ -f /aafirstboot ]; then /aafirstboot start ; fi
hwclock -s -f /dev/rtc0
exit 0 # <------ Already there. Do not copy this. Here to provide context.Caution
Do not copy the exit 0 in the previous code block into the /etc/rc.local file.
The RTC is now set, shut down the ODroid, remove the ethernet cable and the power, wait for a while (5 min should be good). Power it up again and ensure the time and date are correct.
We need a very particular version of CMake from Kitware, the maintainers of CMake, to have everything work well. Let's install it. Start with some pre-requisite packages:
sudo apt-get update
sudo apt-get install -y ca-certificates gpg wgetAdd the Kitware GPG key using the trusted-gpg location
Get the Kitware key using wget
wget https://apt.kitware.com/keys/kitware-archive-latest.ascCheck that the file is not empty:
ls -lh kitware-archive-latest.asc
cat kitware-archive-latest.asc | headYou should see the -----BEGIN PGP PUBLIC KEY BLOCK----- header.
Now convert the key to a GPG keyring and move it:
gpg --dearmor kitware-archive-latest.asc
sudo mv kitware-archive-latest.asc.gpg /usr/share/keyrings/kitware-archive-keyring.gpgAdd the Kitware repository and update our local repository cache
Note
press enter after the \ in the command below and that will get you to the next line to continue typing in the command. This is done as the command is really long to type in one go.
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ focal main' | \
sudo tee /etc/apt/sources.list.d/kitware.list >/dev/nullsudo apt-get updateNow, we can proceed to the installation. List available CMake versions from Kitware's repository:
apt-cache policy cmake | grep 3.26.*This will check if CMake 3.26 is available. If it isn't available, you will have to build it from source, the instructions for which are in the troubleshooting section. We can now proceed to install cmake-3.26 and cmake-data-3.26 which is the dependency to have it all work.
sudo apt-get install cmake=3.26.* cmake-data=3.26.*Once this is done, we need to pin this version in the apt-repository to prevent it from upgrading when we run package updates later on down the line
echo -e "Package: cmake\nPin: version 3.26*\nPin-Priority: 1001" | \
sudo tee /etc/apt/preferences.d/cmake-pinecho -e "Package: cmake-data\nPin: version 3.26*\nPin-Priority: 1001" | \
sudo tee /etc/apt/preferences.d/cmake-data-pinFinally, check if the version of cmake is valid:
cmake --versionIt should output cmake version 3.26.x, here the x is the latest release of 3.26 and isn't important.
First, let's check if the Wi-Fi module is detected
lsusb | grep "Realtek"It should show you an output, then we need to make sure our kernel is running the module for the 8821cu module.
sudo modprobe 8821cuIf there is no output, do the following:
echo 8821cu | sudo tee -a /etc/modules
sudo modprobe 8821cuThen reboot the system
sudo reboot nowRun the following to check if the module is loaded on reboot
lsmod | grep 8821cuYou will get two lines with 8821cu highlighted. Then you can check if the wlan0 interface is up by typing in
ip aIt will show you the wlan0 in DOWN state at the third line by default. Then you can proceed to turn it on by writing the following:
sudo nano /etc/systemd/system/wlan0-up.serviceEnter the following code into the file and save and exit:
[Unit]
Description=Bring up wlan0 at boot
After=network-pre.target
Wants=network-pre.target
[Service]
Type=oneshot
ExecStart=/sbin/ip link set wlan0 up
RemainAfterExit=yes
[Install]
WantedBy=multi-user.targetStart the service by running:
sudo systemctl daemon-reload
sudo systemctl enable wlan0-up.service
sudo systemctl start wlan0-up.serviceReboot the system
sudo reboot nowThen confirm it is up using
ip aIt will show you the wlan0 in UP state on the third line. We can now finally start with getting the access point installed. Install some prerequisites.
Note
Some of the necessary packages are installed in section 2.4. If you didn't install them go back and do so.
sudo apt install -y libgtk-3-dev pkg-config hostapd libqrencode-dev libpng-devsudo apt install -y iw iptablesThen finally, install dnsmasq
sudo apt install -y dnsmasqImportant
If you faced “FAILED” message when starting up the dnsmasq.service like the below “port 53: Address already in use”,
invoke-rc.d: initscript dnsmasq, action "start" failed.
● dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
Loaded: loaded (/lib/systemd/system/dnsmasq.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Mon 2018-12-10 01:59:06 UTC; 22ms ago
Process: 2073 ExecStart=/etc/init.d/dnsmasq systemd-exec (code=exited, status=2)
Process: 2072 ExecStartPre=/usr/sbin/dnsmasq --test (code=exited, status=0/SUCCESS)
Dec 10 01:59:06 odroid systemd[1]: Starting dnsmasq - A lightweight DHCP and caching DNS server...
Dec 10 01:59:06 odroid dnsmasq[2072]: dnsmasq: syntax check OK.
Dec 10 01:59:06 odroid dnsmasq[2073]: dnsmasq: failed to create listening socket for port 53: Address already in use
Dec 10 01:59:06 odroid dnsmasq[2073]: failed to create listening socket for port 53: Address already in useHere we see that port 53 is busy. We need to stop the process there. Let's find out the process that is taking up that port by running
# Check that systemd-resolve service is listening port 53 now(127.0.0.53:53)
sudo netstat -alnp | grep -w LISTEN | grep 53You will find the process listed at the end of the line, for us it was systemd-resolve at the time of writing, to stop it type:
sudo systemctl disable systemd-resolved.service
sudo systemctl stop systemd-resolvedNow, enable dnsmasq again
sudo systemctl enable dnsmasq
sudo systemctl start dnsmasqConfirm it is running by typing int
sudo netstat -alnp | grep -w LISTENSet your system to use dnsmasq by pointing /etc/resolv.conf to localhost:
sudo nano /etc/resolv.confIn that file, type and save the following
nameserver 127.0.0.1Then, for connecting to the internet with a DHCP, create a file as follows
sudo nano /etc/resolv.dnsmasqInput and save the following int resolv.dnsmasq
nameserver 8.8.8.8
nameserver 8.8.4.4Then, in /etc/dnsmasq.conf:
sudo nano /etc/dnsmasq.confGo to the end of the file and input the following
# Resolve file pointer for upstream network resolution
resolv-file=/etc/resolv.dnsmasqSave and exit. Reboot the system using sudo reboot now. Once you're logged back in,
sudo systemctl status dnsmasqMake sure there are no error or warning messages. The output should look something like this
● dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
Loaded: loaded (/lib/systemd/system/dnsmasq.service; enabled; vendor preset: enabled)
Active: active (running) since Sun 2025-05-18 21:46:55 EDT; 11min ago
Process: 387 ExecStartPre=/usr/sbin/dnsmasq --test (code=exited, status=0/SUCCESS)
Process: 401 ExecStart=/etc/init.d/dnsmasq systemd-exec (code=exited, status=0/SUCCESS)
Process: 461 ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf (code=exited, status=0/SUCCESS)
Main PID: 460 (dnsmasq)Now, we can proceed to clone the repository for creating the AP
git clone https://github.com/lakinduakash/linux-wifi-hotspot.gitStart building by
cd linux-wifi-hotspot/src/scripts/
nano create_ap.confand modify the following as you please
SSID=MyAccessPoint
PASSPHRASE=12345678to the following
SSID=odroid_hil_ap
PASSPHRASE=odroid_hil_apTip
Choose your SSID and password as you prefer. We recommend using "NameOfPlatform_ap" as the SSID. For example, I have the ODroid M1S in this example to work for HIL, so I chose the SSID "odroid_hil_ap." We also strongly recommend setting the password to be the same as the SSID.
Caution
Make sure that both your SSID and PASSPHRASE are more than 6 characters in length. Otherwise, the code will not create the access point.
You can now proceed to compile and install the access point
# Navigate to the root of the cloned repo - here we are assuming you cloned it in the root directory as per previous instructions
cd ~/linux-wifi-hotspot
# Compile the code
sudo make install-cli-only
# Create teh AP
sudo create_ap --no-virt wlan0 eth0 odroid_hil_ap odroid_hil_apNote
Make sure you enter the SSID and PASSPHRASE to the one you had in the create_ap.conf file
This will have the service running, to make it persistent, open another terminal instance by pressing ctrl + alt + f2. Put your login and password, which are both odroid, and then proceed to type in the following
sudo systemctl enable create_ap
sudo systemctl start create_apThen reboot the system sudo reboot now, once you are logged back in, check if your access point service is running
sudo systemctl status create_apIt should look something like this
● create_ap.service - Create AP Service
Loaded: loaded (/lib/systemd/system/create_ap.service; enabled; vendor pre>
Active: active (running) since Sun 2025-05-18 21:46:54 EDT; 10min ago
Main PID: 383 (create_ap)You can now connect to the access point like using its name and password, and log in to the ODroid remotely using the following command
ssh odroid@192.168.12.1The password is odroid.
In this section, we will focus on the communication protocol between the ODroid and the Pixhawk and the initial setup for the Wifi Module.
Important
Plug the FTDI module into the USB 3.0 port on the ODroid, which can be identified by the blue plastic inside the port. The WiFi module should be connected to the USB 2.0 port, which has a black plastic insert. Make sure each module is securely connected to its respective port.
Tip
If you have the breakout board for the ODroid that provides an extra USB port, plug the Wifi Module into that. You can purchase that here.
With the Wifi and the FTDI usb-uart module plugged in, run the following command:
# List all the attached USB peripherals
lsusbNow, all the USB devices connected to the ODroid will be displayed.
Important
Make sure a "Realtek" wifi module device is present and a "FTDI" serial device is present.
Next, we need to check the status of the serial communication kernel headers. Use the following command to list all the kernel headers for the USB devices connected.
ls -al /dev/ttyUSB*This should display something similar to /dev/ttyUSB0 on the terminal. The number 0 is usually assigned to serial communication modules. If it is not present, we need to debug further.
Tip
If /dev/ttyUSB0 is not present, check if /dev/ttyACM0 is present. If not, proceed to the next steps.
Note
Troubleshooting steps:
Check if the usbserial and ftdi_sio system routines are running:
lsmodIf they aren't running, do the following
cd /etc/modules-load.d/
sudo nano modules.confAdd the following lines to the file at the very bottom, save and exit
usbserialNext, we need to create another .conf file
# Create the file /etc/modules-load.d/ftdi_sio.conf
sudo touch ftdi_sio.conf
# Open the configuration file in nano
sudo nano ftdi_sio.confAdd the following line to the file, save and exit
ftdi_sioReboot the system, and the modules should load automatically. After rebooting, ensure that the modules are running by typing in lsmod in the terminal.
To ensure robust and consistent serial communication between the Pixhawk 6C and the ODroid M1S, we will create a custom symlink for the FTDI-based UART connection. This avoids issues caused by changing device names (like /dev/ttyUSB0, /dev/ttyUSB1, etc.) each time you plug or reboot your system.
Note
This setup assumes only one FTDI to USB module is used to connect the Pixhawk 6C to the ODroid M1S, as shown in the reference image. If you haven't already got the FTDI-USB module to the ODroid, connect it to the USB 3.0 port.
Tip
If you have multiple FTDI-to-USB cables, make sure the cable connecting Pixhawk to ODroid is plugged in last. This helps ensure the alias we create points to the correct device.
Next, we need to identify the FTDI-USB module. When connected, the FTDI module is typically assigned a device name like /dev/ttyUSB0. If you connect another FTDI, it may show up as /dev/ttyUSB1, and so on.
To identify your FTDI device’s vendor and product ID, run:
lsusbYou should see an output similar to:
Bus 005 Device 006: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) ICFrom the above, we need to single out the following component IDs
-
idVendor:0403 -
idProduct:6001
Finally, we can proceed to create the custom system rule. Navigate to the udev rules directory:
cd /etc/udev/rules.d/Create a new udev rule file:
sudo nano 99-pixhawk.rulesAdd the following line to the file (replace the idVendor and idProduct values with your own if they differ):
SUBSYSTEM=="tty", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", SYMLINK+="ttyPixhawk"Reboot your ODroid for the changes to take effect:
sudo rebootAfter rebooting, the Pixhawk FTDI interface will now consistently appear as:
/dev/ttyPixhawkYou can now reference this path in your scripts or serial communication setups instead of using /dev/ttyUSB0, ensuring stability and avoiding conflicts.
Clone the GitHub repository
git clone https://github.com/eProsima/Micro-XRCE-DDS-Agent.gitCreate the build folder
# Navigate into the cloned folder
cd Micro-XRCE-DDS-Agent
# Create the build folder
mkdir build && cd buildCompile
# Run Cmake
cmake ..
# Compile using all 4 cores present on the ODroid M1s
make -j$(nproc)
# Finally install
sudo make installOnce installation is complete, refresh the linkers
sudo ldconfig /usr/local/lib/Run the following commands to download and compile the latest version of Boost
# Update the apt repo
sudo apt-get updateInstall some prerequisites
sudo apt install -y python3-dev autotools-dev libicu-dev libbz2-devNote
python3-dev: Development headers and static libraries needed for building Python modules or embedding Python in applications.
autotools-dev: Infrastructure scripts and files for GNU Autotools, used to build and configure software from source.
libicu-dev: Development files for ICU (International Components for Unicode), providing Unicode and locale support for C/C++ applications.
libbz2-dev: Development files and libraries for bzip2, enabling compression and decompression features in software.
Clone the repository in the home folder. Go to the home folder by typing in cd ~.
git clone --recursive --branch boost-1.86.0 https://github.com/boostorg/boost.git boost-1.86.0Navigate into the folder using
cd boost-1.86.0Start the bootstrap system
./bootstrap.sh --prefix=/usr/localCompile and install
sudo ./b2 install -j$(nproc)After the installation is done, refresh the linkers
sudo ldconfigVerify the installation
grep "#define BOOST_LIB_VERSION" /usr/local/include/boost/version.hppThis should show 1_86_0.
Choosing a ROS 2 Distribution: Single vs. Multiple Installs
When using ROS 2, decide whether you want a single distribution or multiple versions installed. This choice affects how you set up your environment. The rest of the information in this subsection is only valid AFTER the installation of a ROS2 distro.
Warning
You can only source one ROS 2 distribution per terminal session or codebase. Sourcing multiple ROS 2 versions in the same terminal or codebase can cause conflicts and unexpected behavior.
Caution
The .bashrc file is a startup script that runs every time you open a new terminal. If you add a source command for a specific ROS 2 distribution in .bashrc, that version will load by default — and you won't be able to switch to a different ROS 2 distro unless you manually remove or comment out that line. Use this only if you're sticking to one ROS 2 version.
✅ Recommended: Use a Single ROS 2 Distribution
If you're only using one version (e.g., ROS 2 Galactic, recommended for ACSL-flightstacks), you can safely add the source command to your .bashrc after the installation steps covered in the sections below:
echo "source /opt/ros/galactic/setup.bash" >> ~/.bashrc
source ~/.bashrcThe above example sets up your terminal automatically for ROS 2 Galatic and will differ for Foxy and Humble.
If you install more than one ROS 2 version (e.g., Galactic and Humble), do not add any sourcing to your .bashrc after installation. Instead, you will need to source the version you need manually each time:
# Please note that only one of the these source commands can be used at a time.
# ROS2 Foxy
source /opt/ros/foxy/setup.bash
# ROS2 Galactic
source /opt/ros/galactic/setup.bash
# ROS2 Humble
source <path-to-ros2-humble-build-directory>/install/local_setup.bashNote
The sourcing command for ROS 2 Humble differs because Humble must be built from source on Ubuntu 20.04, whereas Foxy and Galactic can be installed using apt with precompiled binaries available for Ubuntu 20.04. This difference impacts how you install and manage the environment setup.
This avoids path conflicts and ensures you’re using the correct ROS 2 environment.
🛠️ Summary
| Use Case |
.bashrc Sourcing |
Manual Sourcing | Notes |
|---|---|---|---|
| Single ROS 2 distro | ✅ Yes | ❌ No | Easier workflow |
| Multiple ROS 2 distros | ❌ No | ✅ Yes | Avoid version mix-ups |
Tip
Installing ROS2 Galatic is the best balance of ease of setup, performance and features for Ubuntu 20.04.
Check and Set Locale (UTF-8)
Ensure your system is using a UTF-8 locale. On full Linux environments (non-Docker), this is typically already set. To verify:
localeMake sure all values output use UTF-8. If not, or if you want to be sure, run the following:
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8Add the ROS2 Repository
Ensure the Universe repository is enabled:
sudo apt install software-properties-common
sudo add-apt-repository universeAdd the ROS2 GPG key and repository:
sudo apt update && sudo apt install curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] \
http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | \
sudo tee /etc/apt/sources.list.d/ros2.list > /dev/nullThen, update your package list:
sudo apt updateInstall ROS2
Choose ONE of the following installations based on the Ubuntu flavor you installed (GUI or server):
# Full desktop version (recommended for GUI Ubuntu 20.04 setup)
sudo apt install ros-foxy-desktop python3-argcomplete
# OR minimal base install (recommended for SERVER Ubuntu 20.04 setup)
sudo apt install ros-foxy-ros-base python3-argcompleteInstall ROS2 Development Tools
sudo apt install ros-dev-toolsVerify ROS2 Installation
Open two terminal instances on the ODroid (or SSH into it from your PC in two terminals).
In Terminal 1:
source /opt/ros/foxy/setup.bash
ros2 run demo_nodes_cpp talkerIn Terminal 2:
source /opt/ros/foxy/setup.bash
ros2 run demo_nodes_py listenerYou should see messages being published and received—this confirms that both the C++ and Python ROS2 nodes are working correctly.
Make Sourcing Persistent
Caution
Make it persistent ONLY if you are going to use ROS2 Foxy and not any other distro of ROS2 on the ODroid.
To avoid manually sourcing ROS2 every time, add it to your .bashrc:
echo "source /opt/ros/foxy/setup.bash" >> ~/.bashrcApply the change:
source ~/.bashrcCheck if ROS environment variables are properly set:
printenv | grep -i ROSYou should see variables like ROS_VERSION, ROS_DISTRO, and related paths listed.
Fix Deprecation Warnings (Optional but Recommended)
sudo apt-get install python3-testresources python3-pip
pip3 install setuptools==58.2.0
sudo rebootCheck and Set Locale (UTF-8)
Ensure your system is using a UTF-8 locale. On full Linux environments (non-Docker), this is typically already set. To verify:
localeMake sure all values output use UTF-8. If not, or if you want to be sure, run the following:
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8Add the ROS2 Repository
Ensure the Universe repository is enabled:
sudo apt install software-properties-common
sudo add-apt-repository universeAdd the ROS2 GPG key and repository:
sudo apt update && sudo apt install curl -y
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/nullThen, update your package list:
sudo apt updateInstall ROS2
Choose ONE of the following installations based on the Ubuntu flavor you installed (GUI or server):
# Full desktop version (recommended for GUI Ubuntu 20.04 setup)
sudo apt install ros-galactic-desktop python3-argcomplete
# OR minimal base install (recommended for SERVER Ubuntu 20.04 setup)
sudo apt install ros-galactic-ros-base python3-argcompleteInstall ROS2 Development Tools
sudo apt install ros-dev-toolsVerify ROS2 Installation
Open two terminal instances on the ODroid (or SSH into it from your PC in two terminals).
In Terminal 1:
source /opt/ros/galactic/setup.bash
ros2 run demo_nodes_cpp talkerIn Terminal 2:
source /opt/ros/galactic/setup.bash
ros2 run demo_nodes_py listenerYou should see messages being published and received—this confirms that both the C++ and Python ROS2 nodes are working correctly.
Make Sourcing Persistent
Caution
Make it persistent ONLY if you are going to use ROS2 Galactic and not any other distro of ROS2 on the ODroid.
To avoid manually sourcing ROS2 every time, add it to your .bashrc:
echo "source /opt/ros/galactic/setup.bash" >> ~/.bashrcApply the change:
source ~/.bashrcCheck if ROS environment variables are properly set:
printenv | grep -i ROSYou should see variables like ROS_VERSION, ROS_DISTRO, and related paths listed.
Fix Deprecation Warnings (Optional but Recommended)
sudo apt-get install python3-testresources python3-pip
pip3 install setuptools==58.2.0
sudo rebootMake sure you have a locale that supports UTF-8. If you are in a minimal environment (such as a Docker container), the locale may be something minimal like POSIX. We test with the following settings. However, it should be fine if you’re using a different UTF-8 supported locale.
locale # check for UTF-8
sudo apt update && sudo apt install locales
sudo locale-gen en_US en_US.UTF-8
sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
export LANG=en_US.UTF-8
locale # verify settingsYou will need to add the ROS 2 apt repository to your system. First, ensure that the Ubuntu Universe repository is enabled.
sudo apt install software-properties-common
sudo add-apt-repository universeNow add the ROS 2 GPG key with apt.
# Update and install curl
sudo apt update && sudo apt install curl -y
# Add the GPS key
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpgThen, add the repository to your sources list.
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(. /etc/os-release && echo $UBUNTU_CODENAME) main" |
sudo tee /etc/apt/sources.list.d/ros2.list > /dev/nullInstall common packages.
sudo apt update && sudo apt install -y \
python3-flake8-docstrings \
python3-pip \
python3-pytest-cov \
ros-dev-toolsCreate a workspace and clone all repos:
# Create a directory in the home folder to build ROS2
mkdir -p ~/ros2_humble/src
cd ~/ros2_humble
# Import the repo
vcs import --input https://raw.githubusercontent.com/ros2/ros2/humble/ros2.repos src
ROS 2 packages are built on frequently updated Ubuntu systems. It is always recommended that you ensure your system is up to date before installing new packages.
Note
Make sure you are in the ~/ros2_humble root folder before running the following code.
sudo apt upgrade
sudo rosdep init
rosdep update
rosdep install --from-paths src --ignore-src -y --skip-keys "fastcdr rti-connext-dds-6.0.1 urdfdom_headers"Tip
If you’re using a distribution that is based on Ubuntu (like Linux Mint) but does not identify itself as such, you’ll get an error message like Unsupported OS [mint]. In this case, append --os=ubuntu:jammy to the above command.
Note
This part of the installation is only applicable if you install the Server version of Ubuntu onto the ODroid M1s.
Before we build, we need to minimize the number of packages we are building; we do not need rqt, rviz, and a few of the examples associated with them as this will be on the drone. Create a script in the root folder by doing the following.
# Navigate to the root folder of the ros2 build repo
cd ~/ros2_humble/
# create and open script
touch minimize_ros2_packages.sh
nano minimize_ros2_packages.shThen copy and paste the code below into the script. Pay attention to your root directory if it is different.
#!/bin/bash
# ANSI color codes
GREEN='\033[0;32m'
RED='\033[0;31m'
CYAN='\033[0;36m'
ORANGE='\033[0;33m'
NC='\033[0m' # No Color
# Define the root directory of your ROS 2 workspace
ROS2_DIR="/home/odroid/ros2_humble"
# Array of exact directories to create COLCON_IGNORE in
DIRECTORIES=(
"$ROS2_DIR/src/ros2/rviz/rviz_assimp_vendor"
"$ROS2_DIR/src/ros2/rviz/rviz_default_plugins"
"$ROS2_DIR/src/ros2/rviz/rviz_rendering"
"$ROS2_DIR/src/ros2/rviz/rviz_visual_testing_framework"
"$ROS2_DIR/src/ros2/rviz/rviz2"
"$ROS2_DIR/src/ros2/rviz/rviz_common"
"$ROS2_DIR/src/ros2/rviz/rviz_ogre_vendor"
"$ROS2_DIR/src/ros2/rviz/rviz_rendering_tests"
"$ROS2_DIR/src/ros2/demos/action_tutorials"
"$ROS2_DIR/src/ros2/demos/demo_nodes_cpp_native"
"$ROS2_DIR/src/ros2/demos/intra_process_demo"
"$ROS2_DIR/src/ros2/demos/logging_demo"
"$ROS2_DIR/src/ros2/demos/quality_of_service_demo"
"$ROS2_DIR/src/ros2/demos/composition"
"$ROS2_DIR/src/ros2/demos/pendulum_control"
"$ROS2_DIR/src/ros2/demos/topic_monitor"
"$ROS2_DIR/src/ros2/demos/dummy_robot"
"$ROS2_DIR/src/ros2/demos/pendulum_msgs"
"$ROS2_DIR/src/ros2/demos/lifecycle"
"$ROS2_DIR/src/ros2/demos/topic_statistics_demo"
"$ROS2_DIR/src/ros2/demos/image_tools"
"$ROS2_DIR/src/ros2/demos/lifecycle_py"
"$ROS2_DIR/src/ros-visualization/interactive_markers"
"$ROS2_DIR/src/ros-visualization/qt_gui_core"
"$ROS2_DIR/src/ros-visualization/rqt_action"
"$ROS2_DIR/src/ros-visualization/rqt_console"
"$ROS2_DIR/src/ros-visualization/rqt_msg"
"$ROS2_DIR/src/ros-visualization/rqt_publisher"
"$ROS2_DIR/src/ros-visualization/rqt_reconfigure"
"$ROS2_DIR/src/ros-visualization/rqt_shell"
"$ROS2_DIR/src/ros-visualization/rqt_topic"
"$ROS2_DIR/src/ros-visualization/python_qt_binding"
"$ROS2_DIR/src/ros-visualization/rqt"
"$ROS2_DIR/src/ros-visualization/rqt_bag"
"$ROS2_DIR/src/ros-visualization/rqt_graph"
"$ROS2_DIR/src/ros-visualization/rqt_plot"
"$ROS2_DIR/src/ros-visualization/rqt_py_console"
"$ROS2_DIR/src/ros-visualization/rqt_service_caller"
"$ROS2_DIR/src/ros-visualization/rqt_srv"
"$ROS2_DIR/src/ros-visualization/tango_icons_vendor"
# Add more directories here as needed
)
# Function to ensure COLCON_IGNORE files exist and display messages
ensure_colcon_ignore() {
local dir="$1"
local ignore_file="$dir/COLCON_IGNORE"
# Check if COLCON_IGNORE file exists
if [ -f "$ignore_file" ]; then
echo -e "${CYAN}COLCON_IGNORE already exists in ${dir}"
else
echo -e "${ORANGE}Creating COLCON_IGNORE in ${dir}"
touch "$ignore_file"
fi
}
# Function to count existing COLCON_IGNORE files
count_colcon_ignores() {
local count=0
# Loop through each directory in DIRECTORIES array
for dir in "${DIRECTORIES[@]}"; do
local ignore_file="$dir/COLCON_IGNORE"
if [ -f "$ignore_file" ]; then
((count++))
fi
done
echo "$count"
}
# Main script logic
# Loop through each directory in DIRECTORIES array and ensure COLCON_IGNORE
for dir in "${DIRECTORIES[@]}"; do
ensure_colcon_ignore "$dir"
done
# Count existing COLCON_IGNORE files
num_colcon_ignores=$(count_colcon_ignores)
num_directories=${#DIRECTORIES[@]}
# Compare counts and output result
if [ "$num_colcon_ignores" -ge "$num_directories" ]; then
echo -e "${GREEN}${num_colcon_ignores} COLCON_IGNORE files present for ${num_directories} directories specified. Packages minimized for compilation.${NC}"
else
echo -e "${RED}Failed to minimize packages for compilation.${NC}"
fisave it with ctrl + o and exit with ctrl + x. Make it executable by running
chmod +x minimize_ros2_packages.shand run it with
./minimze_ros2_packages.shIf successful, the output should look something like this
Creating COLCON_IGNORE in /home/odroid/ros2_humble/src/ros2/rviz/rviz_assimp_vendor
.
.
.
.
Creating COLCON_IGNORE in /home/odroid/ros2_humble/src/ros-visualization/rqt_srv
.
.
40 COLCON_IGNORE files present for 40 directories specified. Packages minimized for compilation.This should tell the compiler to ignore the packages we don't want in the next step. We can now build the code in the workspace
Please follow the instructions in the above note if you have the server version of Ubuntu installed. We can now proceed to build ros2 humble.
cd ~/ros2_humble && colcon build --symlink-installTip
if you are having trouble compiling all examples and this is preventing you from completing a successful build, you can use COLCON_IGNORE in the same manner as CATKIN_IGNORE to ignore the subtree or remove the folder from the workspace. Take, for instance, you would like to avoid installing the large OpenCV library. Well, then simply run touch COLCON_IGNORE in the cam2image demo directory to leave it out of the build process.
Now, we don’t want to have to source the setup file every time we open a new shell. We can add the command to our shell startup script, which makes it easier while we SSH in:
Caution
Make it persistent ONLY if you are going to use ROS2 Humble and not any other distro of ROS2 on the ODroid.
echo "source ~/ros2_humble/install/local_setup.bash" >> ~/.bashrcAfter running the above command, verify the installation
printenv | grep ROSyou should get an output similar to this
ROS_VERSION=2
ROS_PYTHON_VERSION=3
ROS_LOCALHOST_ONLY=0
ROS_DISTRO=humble Now, the bash shell will automatically source the packages for ROS2 Humble and we do not have to source it every time we try to do anything with ROS2 on the ODroid M1s.
Kernel 5.15.x is the last supported kernel version for the librealsense2 developer sdk. Therefore, before installation, run the following code in the terminal to verify that the kernel is the correct version.
uname -rNote
your output should look something like 5.15.0-051500-generic, the first digit and the following two digits after the period are what matter.
If you followed the instructions in section 1, the Ubuntu version installed should be 20.04 with the kernel version 5.15. If that is not the case, please follow the instructions in troubleshooting 1.2 and change the kernel version to 5.15
Caution
The latest stable version of the development environment that supports the Intel RealSense T265 is librealsense2 SDK v2.53.1. Other versions are not compatible, so please ensure you download this specific version.
Before proceeding further, make sure the system is up to date and that we are on the latest stable version of the 15.5 kernel. Update the system and upgrade any necessary packages.
sudo apt-get -y update && sudo apt-get -y upgradeNow we need to clone the exact version of the firmware that supports both the Intel Realsense T265 and Intel Realsense D435i cameras that are used in the lab.
# go to the home directory
cd
# download recursively the v2.53.1 branch
git clone --branch v2.53.1 --recurse-submodules https://github.com/IntelRealSense/librealsense.git
# go to the librealsense directory
cd librealsense
# check if this is the right tag
git describe --tagsNext, we need to set up the Linux backend for the development environment. Install the essential packages required to build the librealsense binaries and the necessary kernel modules:
sudo apt-get install libssl-dev libusb-1.0-0-dev libudev-dev pkg-config libgtk-3-devNow install some distribution-specific packages:
sudo apt-get install libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev atNow, run the Intel RealSense permissions script from the root directory.
Caution
Make sure all the cameras are disconnected before proceeding.
# go to the root directory
cd ~/librealsense
# Run the permissions script
sudo ./scripts/setup_udev_rules.shTip
One can always remove permissions by running:
sudo ./scripts/setup_udev_rules.sh --uninstallNow build the binaries with cmake
# go to librealsense root
cd ~/librealsense
# build and cd into build directory
mkdir build && cd build
# run cmake
cmake ../ -DFORCE_RSUSB_BACKEND=TRUERecompile and install Librealsense binaries:
sudo make uninstall && make clean && make -j8 && sudo make installNote
The shared object will be installed in /usr/local/lib, header files in /usr/local/include.
The binary demos, tutorials, and test files will be copied into /usr/local/bin.
Run the following command to refresh the object linker in Linux
sudo ldconfigACSL-flightstack — PX4-compatible offboard flight stack designed for multi-rotor UAVs Developed by Mattia Gramuglia, Giri Mugundan Kumar and Andrea L'Afflitto