KEEEKE

0 comments0 reviews

#Ubuntu 20.04 + ROS Noetic: installation and command reference

Different computers: use your own disk names, partition sizes, GPU driver, Bluetooth address, username, timezone, and serial port. ~ means your home directory; $USER means your current username. Text such as REPLACE_WITH_... must be replaced. Output examples are not commands.

#Contents

#1.1 Identify the boot mode and disks

Purpose: identify the existing Windows boot mode. Run in Windows; read BIOS Mode in System Information.

msinfo32

#1.2 Check BitLocker before editing Windows partitions

Purpose: report encryption state for every volume. Run in an Administrator terminal.

manage-bde -status

Alternative, where the BitLocker PowerShell module is available:

Get-BitLockerVolume

Before GParted resizes an NTFS volume, verify Fully Decrypted and 0% encrypted. Protection Off alone is insufficient: protection can be suspended while the data is still encrypted. Microsoft BitLocker operations.

decrypt a volume you intend to resize with GParted, only if it is encrypted. C: is an example; check each affected volume separately.

#1.3 Disable Fast Startup and hibernation

Purpose: prevent Windows leaving NTFS in a hibernated state. Run as Administrator.

powercfg /h off

This also disables Windows Hibernate. Alternatively, disable only Turn on fast startup in Control Panel → Power Options → Choose what the power buttons do → Change settings that are currently unavailable.

#1.4 Check the filesystems that will be resized

Purpose: check the Windows filesystem online.

chkdsk C: /f

If Windows asks to schedule the check, answer Y and restart Windows. Repeat for an affected data volume, substituting its actual letter:

#2.3 Run the installer

  1. Close GParted and launch Install Ubuntu from the live desktop; no reboot is needed first.
  2. Select language, keyboard, and Normal installation. Download updates while installing Ubuntu
  3. Choose Something else for the manually prepared layout. Do not choose Erase disk when retaining Windows. “Install alongside” is another valid option only when its proposed layout matches your intention.
  4. In the allocated Linux space, create/select an ext4 partition and set its mount point to /. Format only the new Linux partition intended for installation.
  5. A single / partition already contains /home; a separate /home is optional. It is not required for ROS and does not replace backups. On MBR disks, account for the primary-partition limit; a logical Linux partition may be needed.
  6. UEFI: reuse the appropriate existing EFI System Partition at /boot/efi without formatting it. On an empty UEFI disk, let the installer create an appropriate ESP. Legacy BIOS: install GRUB to the intended boot disk, not a numbered Linux partition. BIOS-on-GPT needs a BIOS boot partition. Multiple disks need an explicitly checked bootloader destination.
  7. Choose your actual timezone, username, hostname, and password. Matching the Windows username is unnecessary. For Hebron use Asia/Hebron; nearby timezones can have different daylight-saving rules.
  8. Review the changes, install, restart, and remove the USB when prompted. Check that both Ubuntu and Windows boot.

#2.4 Optional: follow the lecturer's separate / and /home layout

Purpose: reproduce the two-partition example on PDF page 14, illustrated on pages 17–19. Choose this instead of assigning all Linux space to / in section 2.3. A working single-root installation does not need to be repartitioned for ROS.

In the installer's Something else screen, use only the free space reserved for Linux:

SettingFirst new partitionSecond new partition
Size in the lecturer's example50000 MBRemaining allocated Linux space
TypePrimary, where appropriate for the disk layoutPrimary, where appropriate for the disk layout
LocationBeginning of this spaceBeginning of the remaining space
Use asExt4 journaling file systemExt4 journaling file system
Mount point//home

Select the free-space row, click +, enter the first partition's settings, and click OK. Repeat on the remaining free space for /home. Check the existing EFI partition and bootloader destination as described in section 2.3, then review the changes before Install Now.

The written 50000 MB recommendation and screenshot sizes differ; follow your planned allocation, not a screenshot's disk numbers. 50000 MB is the lecturer's example, not a fixed ROS requirement. Installed packages under /opt and /usr consume root space, while a workspace under ~/catkin_ws consumes home space. Increase / if your planned system software needs more room. On an MBR disk, the primary-partition limit still applies; do not force two additional primary partitions if the table cannot accommodate them.

Purpose: inspect the resulting mounts after installation.

findmnt -T /
findmnt -T "$HOME"
df -h / "$HOME"

With separate partitions, the root and home paths should resolve to different filesystem sources. With a single / partition, both resolving to the same filesystem is expected.

Result: Ubuntu, ROS, your workspace, and the boot files live on the external drive. Plug it in and choose it in the laptop's boot menu; unplug it after shutdown and Windows can boot from its internal disk. This is a full installed system, not “Try Ubuntu,” a persistent live USB, or a Windows program.

Scope: ordinary 64-bit Intel/AMD PCs with 64-bit UEFI. Section 2E.10 adds optional Legacy BIOS support. ARM/Snapdragon laptops, Apple Silicon, 32-bit UEFI devices, and vendor-specific platforms need different images/boot procedures. No single Ubuntu 20.04 drive is guaranteed to work on every laptop.

#2E.1 Prepare the two separate drives

  • Installer USB: 8 GB or larger, prepared with the Ubuntu 20.04.6 Desktop amd64 ISO using section 2.1. Creating this media erases that USB.
  • Destination external HDD/SSD: the drive that will contain the installed Ubuntu system. Plan for the lab's 100 GB or more allocation plus your data. An SSD connected directly through USB 3.x is preferable for builds; a hard disk also works but can be slower. A normal low-cost flash stick is less suitable for sustained OS writes.
  • Back up the destination's existing files. The fresh-disk layout below erases that destination. If you must retain its data, use verified unallocated space and preserve its existing partition table; do not use Create Partition Table.
  • Use a reliable data cable, direct USB port, and adequate power. Some HDD enclosures need their own power adapter. Avoid an unreliable hub during installation.
  • Keep the Windows BitLocker recovery key available before firmware changes. An external-only install does not require decrypting the internal Windows disk. Disable Windows Fast Startup only if you plan to mount/write its NTFS volumes from Linux; otherwise leave those volumes alone.

Do not use the destination external disk as the active installer medium in this procedure. If you only have one removable drive, obtain a second installer USB or use a separately planned network/VM installation method.

#2E.2 Choose firmware mode and protect the internal drive

For modern laptops use UEFI + GPT on the external destination. The internal disk's MBR/GPT layout does not require the external disk to match it. What matters for independent boot is the target laptop's firmware support. The earlier “match Windows' boot mode” advice is primarily for one GRUB menu managing an internal dual boot.

Preferred route A: make the internal disk unavailable during installation. With the laptop shut down, disconnect the internal drive only if the manufacturer provides a safe user-serviceable procedure, or use a firmware option that actually disables that storage device. Do not open a laptop unnecessarily or switch RAID/VMD/AHCI modes as a substitute. Changing boot priority alone does not hide the internal disk from the installer. Verify in the live session that the disk is absent.

Alternative route B: leave the internal drive connected, but install without a bootloader and configure the external bootloader explicitly afterward. Section 2E.5 explains this route. It avoids relying on the old installer's bootloader selector. You must still select the destination partitions correctly; it is not a substitute for checking the disk identity.

Why the extra care: Ubiquity has a documented history of writing to the first EFI System Partition even when another location was selected. Do not assume the Device for boot loader installation dropdown protects the internal ESP in UEFI mode. Ubuntu installer bug record.

Boot the installer USB's UEFI entry and choose Try Ubuntu. For this UEFI path, the following must report UEFI:

if [ -d /sys/firmware/efi ]; then
    echo "UEFI - continue with the external UEFI instructions"
else
    echo "Legacy BIOS - reboot the installer in UEFI mode for this path"
fi

Secure Boot can remain enabled with Ubuntu's signed boot chain. A firmware that rejects old installation media may need newer supported signed media or a deliberate Secure Boot policy change; never clear platform keys to bypass an error. Section 2E.11 covers failures and device-specific limitations.

#2E.3 Identify the external destination, not just its drive letter

Purpose: distinguish the installer USB, external destination, and any internal disks by model, serial number, capacity, transport, and filesystem.

lsblk -o NAME,PATH,SIZE,MODEL,SERIAL,TRAN,FSTYPE,LABEL,UUID,MOUNTPOINT
ls -l /dev/disk/by-id/

Record the destination's whole-disk path, its model/serial, and later its partition UUIDs. A USB enclosure may report usb, but do not rely on that field alone. Names such as /dev/sda and /dev/sdb can swap after reboot or when using another port. The removable flag can be 0 for a perfectly valid external drive.

If uncertain, compare the listings before and after connecting the not-mounted destination while still in the live session. Never unplug a drive that is mounted or being written. In every subsequent command, replace REPLACE_WITH_EXTERNAL_... using the current verified listing; these placeholders deliberately are not usable device names.

#2E.4 Partition only the external destination

Purpose: open the partition editor in the live session.

sudo gparted

Select the external destination by its checked model and capacity. For a fresh drive whose contents may be erased, choose Device → Create Partition Table → GPT. This destroys that drive's existing partition layout. Do not do this on the installer USB or internal Windows disk.

Create the following on the external drive, with normal MiB alignment:

PartitionSuggested sizeFormat / flagInstaller use
External EFI System Partition (ESP)512 MiBFAT32; esp and boot flagsEFI System Partition; mounted at /boot/efi
Optional BIOS boot partition2 MiBUnformatted; bios_grub flagNo mount point; only for section 2E.10
Ubuntu rootRemaining intended Linux spaceext4/

Label the ESP UBUNTU_EFI and root UBUNTU_EXT if useful. Labels aid identification; they are not a replacement for checking model/serial/UUID. A single root partition keeps free space flexible and includes /home. To follow the lab's separate-home layout, split the Linux space as in section 2.4; both partitions must remain on the external drive.

A dedicated swap partition is not required for this basic installation. Keep any swap file on the external root; do not select internal Windows/Linux swap. This guide does not configure hibernation. An optional NTFS/exFAT shared-data partition can be created from space reserved in advance, but Ubuntu's root and Catkin workspace should remain on ext4.

Apply the checked changes, close GParted, and record the new partitions:

lsblk -f
sudo blkid

External-drive exception to section 2.3: use the external drive's own ESP. Do not reuse the internal Windows ESP. Ubuntu ESP requirements.

#2E.5 Install Ubuntu onto those external partitions

Choose one launch route:

Route A, internal disk unavailable: start Install Ubuntu from the live desktop normally.

Route B, internal disk still visible: close any running installer. Confirm that the Ubuntu 20.04 Ubiquity help lists the no-bootloader option:

ubiquity --help

Purpose: start the installer with automatic bootloader installation disabled.

sudo ubiquity --no-bootloader

This option applies to Ubuntu 20.04's Ubiquity, not every newer Ubuntu installer. It leaves bootloader work for section 2E.6. Canonical discussion of the Ubiquity option.

In either route:

  1. Select language, keyboard, and Normal installation. Updates during installation are optional.
  2. Choose Something else. Do not choose an automatic “alongside Windows” layout for this external-only setup.
  3. Assign the verified external ext4 partition to /. Format it only if this is the intended new installation. Assign a separate external /home only if you created one.
  4. Select the external FAT32 ESP as the EFI System Partition. The installer may assign /boot/efi automatically. Leave every internal partition as do not use, with no format checkbox.
  5. If the bootloader-device dropdown is present, choose the external whole disk, but still use route A or B: the dropdown alone is not sufficient in UEFI mode.
  6. Review the final partition changes: every format/create operation must belong to the external destination. Abort if an internal partition is listed for modification.
  7. Create your account and complete installation. Choose Continue Testing / remain in the live session; do not reboot yet. Route B has no bootloader until the next steps finish. Route A also benefits from explicitly setting up portable boot files.

If the installer exits with an error, resolve it first; a completed file copy does not guarantee a completed installation.

#2E.6 Mount the installed external system for bootloader setup

These commands run in a live-session terminal, after the installer has finished and closed. They also serve as a recovery method if the external installation exists but does not boot. This recipe assumes ext4 root with /boot inside it, not encrypted root or a separate /boot partition.

Purpose: verify mount state. If the installer left the external partitions mounted under /target or /media/..., unmount those specific external mounts in the Disks application first. Do not unmount the live installer medium or run a blanket “unmount all disks” command.

lsblk -o NAME,SIZE,MODEL,FSTYPE,UUID,MOUNTPOINT
findmnt

Purpose: mount the installed root and its own ESP at explicit paths. Substitute your actual external partition paths.

sudo mkdir -p /mnt/ubuntu-external
sudo mount /dev/REPLACE_WITH_EXTERNAL_ROOT_PARTITION /mnt/ubuntu-external
sudo mkdir -p /mnt/ubuntu-external/boot/efi
sudo mount /dev/REPLACE_WITH_EXTERNAL_ESP_PARTITION /mnt/ubuntu-external/boot/efi
findmnt /mnt/ubuntu-external
findmnt /mnt/ubuntu-external/boot/efi
cat /mnt/ubuntu-external/etc/os-release

Expect the new installed Ubuntu 20.04 root and the external FAT32 ESP, both on the intended external physical disk. If either is wrong, stop and unmount/correct it before continuing.

Purpose: verify persistent mounts reference external filesystem UUIDs.

sudo blkid /dev/REPLACE_WITH_EXTERNAL_ROOT_PARTITION
sudo blkid /dev/REPLACE_WITH_EXTERNAL_ESP_PARTITION
cat /mnt/ubuntu-external/etc/fstab
sudo cp -n /mnt/ubuntu-external/etc/fstab /mnt/ubuntu-external/etc/fstab.before-external-boot
sudo nano /mnt/ubuntu-external/etc/fstab

Keep the existing valid options. Check that / uses the external root UUID and /boot/efi uses the external ESP UUID; add/correct the ESP entry if missing/wrong. If you created separate /home, check its external UUID too. Do not duplicate mount entries. For the FAT32 ESP, the expected entry has this shape (file content, replace the UUID):

UUID=REPLACE_WITH_EXTERNAL_ESP_UUID /boot/efi vfat umask=0077 0 1

Remove only unintended dependencies on internal disks; a valid /swapfile entry is fine. Do not add nofail to hide a required ESP/root configuration error.

Purpose: expose the live kernel's device/proc/sys interfaces to the installed system and enter it.

for directory in dev proc sys run; do
    sudo mount --rbind "/$directory" "/mnt/ubuntu-external/$directory"
    sudo mount --make-rslave "/mnt/ubuntu-external/$directory"
done
sudo chroot /mnt/ubuntu-external /bin/bash

You are now root inside the installed external system. The next blocks have no sudo for that reason. Commands such as apt install now change the external installation, not the live USB. Connect the live session to the Internet first; stop on DNS/APT errors.

Purpose: install/update the UEFI boot utilities and Ubuntu's signed boot chain.

apt update
apt install grub2-common grub-efi-amd64-bin grub-efi-amd64-signed shim-signed

If a package configuration dialog asks for an ESP or install destination, select only the verified external destination. APT maintainer scripts may update the current laptop's firmware boot entry; that is separate from disk contents. The explicit command below uses --no-nvram, and portable boot will not rely on that laptop-specific entry.

Purpose: install the signed Ubuntu UEFI loader to the mounted external ESP without explicitly registering a new firmware entry.

grub-install --target=x86_64-efi \
  --efi-directory=/boot/efi --boot-directory=/boot \
  --bootloader-id=ubuntu --uefi-secure-boot --no-nvram
update-initramfs -u -k all
update-grub

Focal's --uefi-secure-boot option requires grub-efi-amd64-signed. If it reports missing signed files or fails, stop and resolve the package issue; do not add --force or silently substitute an unsigned loader while expecting Secure Boot to work. Ubuntu 20.04 grub-install options.

#2E.7 Add the portable UEFI fallback boot path

Continue inside the chroot. A firmware “ubuntu” entry belongs to one laptop's NVRAM; it does not travel with the external disk. The standard x86-64 removable-media location is EFI/BOOT/BOOTX64.EFI. For this signed path, that file must be Ubuntu's shim, with the matching signed GRUB beside it. GRUB removable-media installation, Ubuntu signed boot-chain explanation.

Purpose: inspect the files generated in the previous step.

ls -l /boot/efi/EFI/ubuntu/

Before proceeding, confirm shimx64.efi, grubx64.efi, and grub.cfg exist there. Inspect the small grub.cfg; for this layout it should locate the external root filesystem by UUID and load /boot/grub/grub.cfg:

cat /boot/efi/EFI/ubuntu/grub.cfg
blkid

Purpose: preserve an existing fallback directory if present, then install the signed fallback files on this external ESP. This changes that drive's default fallback loader; use it for the dedicated Ubuntu external disk described here, not a shared multiboot ESP without a separate plan.

if [ -d /boot/efi/EFI/BOOT ]; then
    cp -a /boot/efi/EFI/BOOT "/boot/efi/EFI/BOOT.backup-$(date +%Y%m%d-%H%M%S)"
fi
mkdir -p /boot/efi/EFI/BOOT
cp /boot/efi/EFI/ubuntu/shimx64.efi /boot/efi/EFI/BOOT/BOOTX64.EFI
cp /boot/efi/EFI/ubuntu/grubx64.efi /boot/efi/EFI/BOOT/grubx64.efi
cp /boot/efi/EFI/ubuntu/grub.cfg /boot/efi/EFI/BOOT/grub.cfg
if [ -f /boot/efi/EFI/ubuntu/mmx64.efi ]; then
    cp /boot/efi/EFI/ubuntu/mmx64.efi /boot/efi/EFI/BOOT/mmx64.efi
fi

Keep EFI/ubuntu as well: the signed loader's configuration lookup may use that vendor directory. Do not rename/remove it after creating EFI/BOOT.

Purpose: verify the fallback copies and leave the installed-system shell.

cmp /boot/efi/EFI/ubuntu/shimx64.efi /boot/efi/EFI/BOOT/BOOTX64.EFI
cmp /boot/efi/EFI/ubuntu/grubx64.efi /boot/efi/EFI/BOOT/grubx64.efi
test -s /boot/grub/grub.cfg && echo "Main GRUB configuration exists"
sync
exit

cmp produces no output when files match. These checks confirm file placement, not firmware compatibility; actual boot tests follow.

Back in the live-session terminal, close any file-manager windows or terminals browsing the installed mounts, then unmount only this mounted external tree:

sudo umount -R /mnt/ubuntu-external
sync
sudo poweroff

If unmount reports busy, close the process using the tree and retry; do not force-unplug the drive. After full shutdown, remove the installer USB, leave the external system drive connected, and restore the internal drive connection/firmware setting if you disabled it.

#2E.8 First boot and proof of independence

Use the laptop's one-time boot menu and select the external drive's UEFI USB entry. It may display the enclosure name rather than “Ubuntu.” Do not select a similarly named internal-disk ubuntu entry merely because it is present. You can keep Windows Boot Manager first in the permanent boot order.

Purpose: check that root, home, EFI files, and swap all belong to the intended external installation. Run in the newly booted Ubuntu system.

findmnt -T /
findmnt -T "$HOME"
findmnt /boot/efi
lsblk -o NAME,SIZE,MODEL,SERIAL,TRAN,FSTYPE,UUID,MOUNTPOINT
cat /etc/fstab
swapon --show

Trace the root and ESP source partitions back to the external physical disk. A /swapfile on the external root is expected if swap was configured. No required /home, /boot/efi, or swap entry should depend on the first laptop's internal disk.

Purpose: inspect Secure Boot state, if the utility is not already installed.

sudo apt install mokutil
mokutil --sb-state

Perform these acceptance checks before calling the disk portable:

  1. Boot it on the installation laptop using the external USB entry and confirm the mounts above.
  2. Shut down Ubuntu fully, disconnect the external drive, and confirm internal Windows still boots. If Windows does not start automatically, select Windows Boot Manager and restore its boot priority; do not delete EFI files as a first response.
  3. Shut Windows down, connect the external drive to a second compatible laptop, select its UEFI USB entry, and repeat the mount checks. This tests that you are not relying on the first laptop's NVRAM entry or internal ESP.
  4. Check Wi-Fi, keyboard/touchpad, audio, GPU rendering, and power management on each laptop. Only then proceed with heavy ROS simulations.

Continue with sections 3–7 for Ubuntu updates, suitable drivers, ROS, workspace creation, and Turtlesim. Those software commands are the same on an external installation. Do not repeat the Windows partition-shrinking steps. You install ROS once on the external system; its packages and workspace then travel with the drive.

#2E.9 Using the same drive on different laptops

Difference between laptopsWhat to do
Intel versus AMD x86-64 CPUThe amd64 Ubuntu image supports both in principle; actual chipset/firmware support still needs testing.
ARM/Snapdragon or Apple SiliconThis amd64 image will not boot natively; use a platform-specific installation.
UEFI versus Legacy BIOSThe main path is UEFI. Use section 2E.10 only if you need Legacy support too.
NVIDIA versus Intel/AMD graphicsInspect the GPU on each laptop. Do not pin the external system to one laptop's GPU using a hardcoded Xorg configuration or run nvidia-xconfig routinely. A single NVIDIA driver branch may not support every old/new NVIDIA GPU.
Secure Boot and NVIDIA/DKMSA module-signing key trusted on one laptop may need enrollment on another. Follow Ubuntu's MOK enrollment prompts on each affected laptop; do not assume firmware trust travels with the disk.
Wi-Fi/Bluetooth/audio hardwareReuse the common firmware/kernel packages, then diagnose the actual device. Do not install random third-party driver scripts based only on the laptop brand.
Very recent hardwareFocal's HWE kernel may still be too old. If a needed device is unsupported, a newer host with a Focal VM/container is an alternative, not a problem solved by another partition layout.
Device names, USB serial ports, network interfacesUse UUIDs for mounts, /dev/serial/by-id for suitable serial devices, and inspect the current network names. Do not hardcode /dev/sdb or one laptop's IP into startup files.
Suspend and ACPI settingsA sleep fix for one laptop can cause failures on another. Leave those tweaks out of a shared portable image unless tested on all target machines.

Each laptop needs its own successful boot/hardware test. The external disk shares the same user accounts, passwords, SSH keys, saved Wi-Fi credentials, and files wherever it is used. For friends who want independent installations, prepare their own drives instead of distributing a copy of your personal system with credentials included.

#2E.10 Optional: also boot an older Legacy BIOS laptop

Skip if all target laptops support 64-bit UEFI. This adds a second boot method to the same GPT external disk; it does not convert Windows or create a second Ubuntu installation. It requires the unformatted bios_grub partition reserved in section 2E.4. Some older firmware cannot USB-boot a GPT disk even with BIOS GRUB; test the actual laptop. GRUB BIOS partition requirements.

Boot the installed external Ubuntu in UEFI mode first, verify its mount sources, and confirm the BIOS boot partition with:

lsblk -o NAME,SIZE,MODEL,UUID,MOUNTPOINT
sudo parted /dev/REPLACE_WITH_EXTERNAL_WHOLE_DISK print

Do not proceed unless the whole disk is positively identified and its partition table includes a bios_grub partition. If you did not reserve one, do not improvise a destructive resize just to copy this command.

Purpose: install BIOS GRUB binaries alongside the UEFI files, then write the BIOS bootloader to the external whole disk, not a numbered partition.

sudo apt install grub-pc-bin
sudo grub-install --target=i386-pc --boot-directory=/boot --recheck \
  /dev/REPLACE_WITH_EXTERNAL_WHOLE_DISK
sudo update-grub

i386-pc is GRUB's BIOS platform name; it does not turn the installed amd64 OS into a 32-bit OS. Install grub-pc-bin here, not a blind replacement of all UEFI GRUB packages with grub-pc. The existing signed UEFI files should remain. Test both UEFI and Legacy USB boot afterward; Legacy mode has no UEFI Secure Boot validation.

For a truly BIOS-only machine that refuses GPT USB media, use a separately planned MBR external disk installation booted in Legacy mode, with GRUB on that external whole disk and the normal space before its first aligned partition. That is a different layout; do not convert a working GPT external drive in place as a troubleshooting shortcut.

#2E.11 External-drive troubleshooting and recovery

SymptomCheck / action
External disk absent from firmware boot menuCheck USB boot is permitted, try a direct port/cable, check enclosure power, and select the correct UEFI/Legacy menu. USB-C storage visibility inside Windows does not prove pre-boot support. Some docks/Thunderbolt enclosures need firmware-specific support.
Disk appears, but says no bootable deviceConfirm an external FAT32 ESP and EFI/BOOT/BOOTX64.EFI exist. Boot the live USB, identify the external partitions again, and repeat sections 2E.6–2E.7.
Works only on the original laptopCheck that /boot/efi is on the external disk, that fallback files exist, and that /etc/fstab has no required internal UUIDs. Then test using a USB entry on another laptop.
Secure Boot violation / revoked imageUpdate the installed shim-signed, signed GRUB, and Ubuntu kernel using trusted Focal repositories; refresh the fallback copies afterward. Firmware revocations or a policy that excludes third-party certificates may reject older loaders. Do not replace a signed loader with an unsigned one and expect Secure Boot acceptance.
GRUB appears but Ubuntu is not foundInspect external root UUID, EFI/ubuntu/grub.cfg, /boot/grub/grub.cfg, and installed kernel/initramfs. Repair using the live chroot route; an EFI loader existing alone is insufficient.
Emergency mode or long wait for a disk UUIDCompare blkid with /etc/fstab. Correct stale internal/old-disk references, including separate home or swap. Do not remove the current root/ESP entries blindly.
Black screen on one laptopTry the installer's safe-graphics option for diagnosis. On the installed system, a temporary GRUB nomodeset boot may help reach a desktop, but limits graphics and is not a permanent ROS simulation solution. Inspect actual GPUs/drivers using section 4.
I/O errors, USB resets, or unexplained freezesCheck the cable, power, port, enclosure, and drive health before changing ROS packages. Preserve important files if storage errors recur.
Windows boots insteadUse the one-time external USB boot entry. Windows being first in boot order is compatible with this setup.

Purpose: inspect USB/storage errors after booting Ubuntu.

lsusb -t
sudo journalctl -k -b | grep -Ei 'usb|uas|reset|I/O error|disconnect'

A recurring USB reset is not automatically a driver problem; begin with the physical connection. Do not apply global USB/UAS blacklists without identifying the affected enclosure.

Recovery when Ubuntu accidentally used the internal ESP: preserve the internal EFI files, boot the live USB in UEFI mode, and use sections 2E.6–2E.7 to install the boot files onto the external ESP and correct its fstab. If the external disk has no ESP, allocate one from verified free space first; do not format its root or another disk's ESP. Test external-only boot before considering any cleanup. Internal Windows' EFI/Microsoft directory must remain intact; deleting it does not repair Ubuntu portability.

#2E.12 Updates, performance, and safe removal

Bootloader maintenance: manual fallback copies may not be refreshed by every package update. After a shim/GRUB update, verify that /boot/efi is still the external ESP, refresh the signed vendor loader, and repeat the fallback copying/checks from section 2E.7. When running from installed Ubuntu rather than a chroot, use an explicit root shell for those no-sudo commands:

findmnt /boot/efi
sudo -i

After confirming the correct mounted ESP, run the grub-install command from section 2E.6, update-grub, and the copy/check blocks from section 2E.7. exit returns to your normal user. Retest the external USB boot path after significant bootloader changes. If you added BIOS support, also rerun its external-disk grub-install command after relevant GRUB updates, verifying the whole-disk identity again.

Portability: keep the normal Ubuntu generic/HWE kernel rather than one tied to a different vendor board. Use one source of kernel updates; do not install a different laptop's vendor kernel just because you moved the disk. Large builds and Gazebo assets benefit from an SSD and USB 3.x. Use catkin_make -j2 -l2 when a smaller laptop runs out of RAM, as described in section 10.4.

Safe disconnect: save files, stop ROS nodes and builds, and shut the installed external system down completely:

sudo poweroff

Wait for full shutdown and disk activity to stop before unplugging. sync alone is not permission to disconnect a running root filesystem. Do not unplug during sleep, resume, an update, or hibernation. Fully shut down before moving the drive to another laptop; do not resume a hibernated installation on different hardware.

When Windows offers to format an unrecognized Linux partition, cancel. Windows normally does not browse ext4 natively; the absence of files in Explorer does not mean the partition is empty. Back up your source code and data separately because the portable drive is still a single point of failure.

All remaining main-path commands run in the installed Ubuntu terminal, opened with Ctrl+Alt+T, as your normal user. Use Bash for the commands below.

#3.1 Confirm the OS and architecture

Purpose: ensure you are using the intended Ubuntu release before adding repositories.

cat /etc/os-release
lsb_release -sc
dpkg --print-architecture
uname -r

Expect Ubuntu 20.04 and focal; a normal Intel/AMD 64-bit PC reports amd64. Stop if the release differs. Do not add Focal repositories to Ubuntu 22.04/24.04 to force Noetic installation.

#3.2 Keep Ubuntu 20.04 while allowing package updates

Purpose: suppress prompts to upgrade to another Ubuntu release.

sudo cp -n /etc/update-manager/release-upgrades /etc/update-manager/release-upgrades.before-noetic
sudo sed -i 's/^Prompt=.*/Prompt=never/' /etc/update-manager/release-upgrades
grep '^Prompt=' /etc/update-manager/release-upgrades

Expect Prompt=never. This does not block ordinary package updates or prevent someone manually upgrading the OS. Do not run do-release-upgrade for this setup.

#3.3 Refresh package lists, update packages, and enable Universe

Purpose: obtain current package lists before installing anything, avoiding the chats' “curl has no installation candidate” ordering problem.

sudo apt update
sudo apt upgrade
sudo apt install software-properties-common ca-certificates curl wget gnupg lsb-release
sudo add-apt-repository universe
sudo apt update

If apt update fails because an old ROS source already exists, use section 10.1 before continuing. Review APT prompts instead of blindly accepting removals.

Purpose: inspect Ubuntu Pro coverage on this installation, if the client is installed.

pro status

If desired, configure Pro through Ubuntu's account flow described in the Ubuntu 20.04 support page. EOL does not mean you should automatically replace every Ubuntu mirror with old-releases.

#3.4 Install the development and diagnostic basics

Purpose: install C/C++ compilers, Make, CMake, debugger, Git, Python 3 tooling, and resource-monitoring utilities.

sudo apt install build-essential cmake gdb git python3 python3-pip python3-dev python3-venv htop

Optional: install the terminal layout tool mentioned in the chats.

sudo apt install terminator

Do not replace Ubuntu's system Python or use sudo pip to upgrade ROS dependencies. Use an isolated virtual environment for unrelated Python projects.

#4.1 Identify hardware and available proprietary drivers

Purpose: inspect PCI/USB devices and loaded drivers.

lspci -k
lsusb
sudo apt install ubuntu-drivers-common
ubuntu-drivers devices

ubuntu-drivers handles supported additional driver packages; it does not install a missing driver for every possible Wi-Fi, audio, or chipset device. Most Linux drivers come from the kernel and firmware packages. Test the actual devices as well as checking the listings.

#4.2 NVIDIA only: install the appropriate driver

Skip this on Intel/AMD-only machines or if an appropriate NVIDIA driver already works. Choose the recommended/tested supported driver in Software & Updates → Additional Drivers, or use Ubuntu 20.04's automatic selection:

sudo ubuntu-drivers autoinstall

Device note: the chats show an RTX 4050 working with 535, after automatic selection of a 570-server-open package failed. That does not make 535 the correct driver for every GPU, or prove all server/open drivers are broken. For manual installation, first use ubuntu-drivers devices and APT policy to select a compatible package. Ubuntu NVIDIA guidance.

Conditional example only: if nvidia-driver-535 is offered and appropriate for the GPU:

apt-cache policy nvidia-driver-535
sudo apt install nvidia-driver-535

After successful installation, save work and reboot. Complete any requested MOK enrollment if Secure Boot is enabled.

sudo reboot

Purpose: verify the NVIDIA driver after reboot.

nvidia-smi

This verifies driver communication, not every graphics application. The CUDA version shown is the driver's supported CUDA level; it does not mean the CUDA toolkit is installed. A separate CUDA toolkit is not required for ordinary ROS/RViz use.

#4.3 Optional: Ubuntu 20.04 HWE kernel and firmware

Purpose: obtain the Focal hardware-enablement kernel and standard firmware when needed for hardware support.

apt-cache policy linux-generic-hwe-20.04
sudo apt install --install-recommends linux-generic-hwe-20.04
sudo apt install linux-firmware
sudo reboot

Use the normal package update path if HWE is already installed. Do not replace a board/vendor-specific kernel without checking its support instructions. Do not use linux-generic-hwe-24.04 from chat7 on Ubuntu 20.04. Some recent devices remain unsupported by Focal's kernel; a newer host OS with a Focal VM/container may be more suitable. Ubuntu HWE package guidance.

#5.1 Configure the ROS repository and signing key

Purpose: install the official ROS 1 repository configuration package, which manages the key and source together. This replaces the old apt-key/keyserver steps in the chats. ROS key migration guidance, official repository package.

For a fresh setup, download the verified Focal release asset below. Version 1.3.0 was available when this guide was reviewed. If unavailable later, obtain the ros-apt-source Focal all.deb asset from the official releases; do not substitute ros2-apt-source.

mkdir -p ~/Downloads/ros-setup
cd ~/Downloads/ros-setup
curl -fL --retry 3 -o ros-apt-source.deb \
  https://github.com/ros-infrastructure/ros-apt-source/releases/download/1.3.0/ros-apt-source_1.3.0.focal_all.deb

Purpose: inspect the downloaded package; it should identify itself as ros-apt-source.

dpkg-deb -f ./ros-apt-source.deb Package Version Architecture

Purpose: install the repository configuration, then refresh the ROS package index.

sudo apt install ./ros-apt-source.deb
sudo apt update
apt-cache policy ros-noetic-desktop-full

APT should report a candidate for ros-noetic-desktop-full. If you previously followed the chats, first resolve duplicate/old source definitions using section 10.1. Never bypass repository signature checking.

#5.2 Install the full desktop ROS distribution

Purpose: install ROS core, RViz, Gazebo integration, and the desktop/simulation tools used in the chats.

sudo apt install ros-noetic-desktop-full

Wait for completion. For a deliberately headless installation, ros-noetic-ros-base is an alternative, but it does not provide the graphical tools assumed below.

#5.3 Load ROS into Bash

Purpose: activate Noetic now and add it to future Bash terminals without repeatedly appending the same line.

source /opt/ros/noetic/setup.bash
grep -qxF 'source /opt/ros/noetic/setup.bash' ~/.bashrc || \
  echo 'source /opt/ros/noetic/setup.bash' >> ~/.bashrc

Purpose: verify that ROS commands and Python 3 configuration are visible.

rosversion -d
echo "$ROS_DISTRO"
echo "$ROS_PYTHON_VERSION"

Expect noetic, noetic, and 3. For Zsh, use the corresponding setup.zsh and .zshrc; the rest of this guide assumes Bash.

#5.4 Install build and dependency tools

Purpose: install the tools used to resolve package dependencies and work with Catkin source projects.

sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator \
  python3-wstool python3-catkin-tools build-essential

#5.5 Initialize rosdep and include Noetic's EOL metadata

Purpose: create the machine-wide rosdep source list once.

if [ ! -f /etc/ros/rosdep/sources.list.d/20-default.list ]; then
    sudo rosdep init
fi

Purpose: update your user's dependency database, including end-of-life distributions.

rosdep update --include-eol-distros

Run the update without sudo. An existing default source list does not need deletion simply because rosdep init says it exists. The EOL flag is required for Noetic metadata now; it does not cure network failures or every missing dependency rule. ROS rosdep EOL behavior.

#6.1 Create the workspace and perform the first build

Purpose: create the folder for your own ROS packages and generate its build environment.

source /opt/ros/noetic/setup.bash
mkdir -p ~/catkin_ws/src
cd ~/catkin_ws
catkin_make

Run catkin_make from ~/catkin_ws, not src, and never with sudo. catkin_init_workspace is unnecessary here because the first build initializes the source space.

#6.2 Activate the workspace

Purpose: make your own packages visible now and in future terminals. Run only after a successful build.

source ~/catkin_ws/devel/setup.bash
grep -qxF 'source ~/catkin_ws/devel/setup.bash' ~/.bashrc || \
  echo 'source ~/catkin_ws/devel/setup.bash' >> ~/.bashrc

Keep the core /opt/ros/noetic source line before the workspace source line in .bashrc.

Purpose: verify the workspace overlay.

echo "$ROS_PACKAGE_PATH"

The output should include your own catkin_ws/src and /opt/ros/noetic/share. This printed path is not a command. You can have multiple workspaces, but source the intended one; overlays can be chained deliberately. Do not mix catkin_make and catkin build in the same build/devel directories.

#6.3 Optional: create the first lab package

Purpose: create the same basic package used in the chats.

cd ~/catkin_ws/src
catkin_create_pkg test_package_1 std_msgs rospy roscpp
cd ~/catkin_ws
catkin_make
source devel/setup.bash
rospack depends1 test_package_1

If it already exists, skip creation and inspect it; do not delete your work. roscpp, rospy, and std_msgs in the output are package names, not programs to execute. Dependency lookup errors should be investigated using section 10.3 even if a list prints underneath them.

#7.1 Start the ROS master — terminal 1

Purpose: start the master, parameter server, and ROS logging.

roscore

Leave it running while using terminals 2 and 3. Ctrl+C stops it.

#7.2 Start the graphical test — terminal 2

Purpose: open the Turtlesim simulator.

rosrun turtlesim turtlesim_node

#7.3 Control the turtle — terminal 3

Purpose: test node-to-node communication using keyboard commands.

rosrun turtlesim turtle_teleop_key

Focus terminal 3 and press the arrow keys. The turtle should move. This tests a basic ROS workflow, not all hardware or simulation features.

#7.4 Inspect running nodes — terminal 4

Purpose: confirm that the nodes and their topics are registered.

rosnode list
rostopic list
rosnode info /turtlesim

Purpose: test RViz rendering, with the master still running.

rviz

Close RViz when done. A missing fixed-frame warning in an empty session is not an installation failure.

Purpose: test Gazebo's ROS integration in a separate terminal.

roslaunch gazebo_ros empty_world.launch

Close the simulator with Ctrl+C in its launching terminal. Initial model/network requests may take time. Stop the test nodes and then roscore when finished.

#7.5 Check resources and hardware function

Purpose: report memory, CPU, disk space, failed services, and network state.

free -h
lscpu
df -h /
systemctl --failed
nmcli device status

Purpose: interactively view CPU and memory usage; press q to exit.

htop

Also test Wi-Fi, Bluetooth, audio, external displays if needed, and suspend/resume after saving work. A loaded driver or free-memory listing is not a complete hardware health test.

#8.1 Install Visual Studio Code

Purpose: install the editor through Snap.

sudo snap install --classic code

If already installed, keep it or update it:

sudo snap refresh code

Purpose: add C/C++, Python, and CMake editing support.

code --install-extension ms-vscode.cpptools
code --install-extension ms-python.python
code --install-extension twxs.cmake

The chats used ms-iot.vscode-ros, whose repository is archived. It is optional and may have compatibility/availability limits; ROS works without it. If your course specifically uses that extension:

code --install-extension ms-iot.vscode-ros

#8.2 Allow serial-port access for development boards

Purpose: grant your user access to typical USB serial devices.

sudo usermod -aG dialout "$USER"

Log out completely and log back in, or reboot. Then check membership and attached serial devices:

id -nG
ls -l /dev/serial/by-id/

If no device appears, connect it and inspect lsusb and sudo dmesg -w (stop with Ctrl+C). Device paths differ: /dev/ttyUSB0 and /dev/ttyACM0 are examples. Prefer a stable /dev/serial/by-id/... link where available. Some boards need specific udev rules; dialout is not universal USB access. Do not solve this by using chmod 777 on devices.

#8.3 Configure Git and an SSH key

Purpose: set the author identity for your commits. Replace both values.

git config --global user.name "Your Name"
git config --global user.email "[email protected]"

Purpose: check whether an SSH public key already exists before generating one.

ls -la ~/.ssh

Purpose: generate a key only if needed; do not overwrite an existing key. Set a passphrase when prompted if desired.

ssh-keygen -t ed25519 -C "[email protected]"
cat ~/.ssh/id_ed25519.pub

Add the public .pub output to your Git host's SSH key settings. Never share id_ed25519, the private key. An SSH key with a passphrase may still prompt unless managed by an agent.

#8.4 Optional Google Chrome — amd64 only

Purpose: download and install Google's Linux desktop package.

mkdir -p ~/Downloads/chrome-setup
cd ~/Downloads/chrome-setup
wget -O google-chrome-stable_current_amd64.deb \
  https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo apt install ./google-chrome-stable_current_amd64.deb

Use this on amd64, not ARM. Firefox is sufficient for reading the guide; Chrome is not a ROS prerequisite. Browser support can change: Google's requirements.

#9.1 Set the actual timezone and network time

Purpose: inspect time settings and available timezone names.

timedatectl
timedatectl list-timezones

Purpose: set Hebron time, if that is your location; otherwise substitute the correct listed timezone.

sudo timedatectl set-timezone Asia/Hebron
sudo timedatectl set-ntp true

#9.2 Optional workaround for the Windows/Ubuntu clock offset

Purpose: use local time in the hardware clock to match a Windows installation that uses local RTC time.

timedatectl set-local-rtc 1 --adjust-system-clock
timedatectl

Local RTC has daylight-saving/timezone limitations; keeping both operating systems on UTC is another approach. Apply only if needed and check the displayed time in both systems. Undo this Ubuntu change with:

timedatectl set-local-rtc 0 --adjust-system-clock

#9.3 Boot Windows by default

Purpose: make a shared UEFI laptop start Windows normally. In firmware settings, move Windows Boot Manager above ubuntu. Use the manufacturer's one-time boot menu to choose Ubuntu when needed. This firmware option does not apply identically to Legacy BIOS systems.

If you prefer GRUB's menu, configure its default entry using the actual menu title or ID on this computer; do not assume Windows is entry number 2.

Purpose: inspect generated menu entries and edit the source configuration.

grep -E "^[[:space:]]*(menuentry|submenu) " /boot/grub/grub.cfg
sudo cp -n /etc/default/grub /etc/default/grub.before-customization
sudo nano /etc/default/grub

Set GRUB_DEFAULT to the exact Windows entry title in quotes, and optionally set GRUB_TIMEOUT=10. Do not edit /boot/grub/grub.cfg directly. In nano: Ctrl+O, Enter to save, then Ctrl+X to exit.

Purpose: regenerate GRUB's menu after editing.

sudo update-grub

Grub Customizer and rEFInd were mentioned as alternatives, not demonstrated necessities. Keep a working bootloader for the basic installation; a graphical boot-manager replacement needs its own UEFI/Secure Boot review.

#10.1 APT: missing key, duplicate ROS sources, or curl unavailable

Purpose: inspect ROS source definitions before changing them.

grep -RnsE 'packages\.ros\.org|ros-apt-source|ros-archive-keyring' \
  /etc/apt/sources.list /etc/apt/sources.list.d/

For the old ros-latest.list created by the chats, inspect it first:

cat /etc/apt/sources.list.d/ros-latest.list

Purpose: disable only that old ROS-only file while preserving a backup. Run only if it exists and contains the obsolete entry; choose another backup name if the destination already exists.

sudo mv -n /etc/apt/sources.list.d/ros-latest.list \
  /etc/apt/sources.list.d/ros-latest.list.disabled
sudo apt update
sudo apt install ca-certificates curl

Then follow section 5.1. If another file contains the same old source, back it up and disable only the conflicting entry. Do not disable the new package-managed source. A successful setup has one consistent ROS 1 source definition and no Signed-By conflict. Do not blindly delete keys or use trusted=yes/--allow-unauthenticated.

For Unable to locate package, verify focal, Internet access, repository configuration, and a successful sudo apt update. For a failing Ubuntu mirror, select a working Ubuntu mirror in Software & Updates; keep the release set to Focal.

#10.2 APT: lock, interrupted installation, or unmet dependencies

Purpose: identify an active package-manager process.

ps -ef | grep -E '[a]pt|[d]pkg|[u]nattended-upgrade'

Wait for the installer/updater to finish. Do not delete lock files or reboot in the middle of a healthy installation.

Purpose: finish package configuration and repair dependencies after an interrupted installation, once no other package manager is running.

sudo dpkg --configure -a
sudo apt --fix-broken install
sudo apt update

Review proposed changes. “You have held broken packages” does not prove packages were explicitly held. Check with:

apt-mark showhold

If a selected NVIDIA package still has unsatisfied dependencies, inspect its candidate/version and select a compatible offered driver. --fix-broken does not clear a live package lock or manufacture missing repository packages.

#10.3 rosdep/rospack errors

Purpose: verify the environment, refresh EOL metadata, and refresh package discovery.

source /opt/ros/noetic/setup.bash
source ~/catkin_ws/devel/setup.bash
echo "$ROS_DISTRO $ROS_PYTHON_VERSION"
rosdep update --include-eol-distros
rospack profile
rosdep check --from-paths ~/catkin_ws/src --ignore-src --rosdistro noetic

If you accidentally used sudo rosdep update and now receive cache permission errors:

sudo rosdep fix-permissions
rosdep update --include-eol-distros

Repair the invalid commit URL from chat6 only if you previously applied it. The hash d560ac3635f28eedf2b0d8efbc4ac5fe9ce1a8d1 returned 404 in the actual chat. Do not reuse it.

cat /etc/ros/rosdep/sources.list.d/20-default.list
sudo cp -n /etc/ros/rosdep/sources.list.d/20-default.list \
  /etc/ros/rosdep/sources.list.d/20-default.list.before-repair
sudo sed -i \
  's|ros/rosdistro/d560ac3635f28eedf2b0d8efbc4ac5fe9ce1a8d1|ros/rosdistro/master|g' \
  /etc/ros/rosdep/sources.list.d/20-default.list
rosdep update --include-eol-distros

A message saying the cache was updated is not success if the same run reports failed sources. Resolve all download/404 errors first.

Purpose: distinguish an unknown dependency rule from an absent installed package.

rosdep resolve python3-catkin-pkg --rosdistro noetic
rosdep resolve python3-empy --rosdistro noetic
apt-cache policy python3-catkin-pkg python3-empy python3-rospkg

Legacy python-* names in rospack warnings may involve conditional dependency metadata or unavailable rules; they do not automatically mean Python 2 must be installed. The final chat proposed local Python 3 mappings, but there is no subsequent output proving they fixed the problem. They are therefore an optional workaround, not a required fresh-install step; see Appendix C.

#10.4 Shell and workspace mistakes

Purpose: inspect and edit the Bash startup file if commands are missing or duplicate source lines accumulated.

ls -la ~/.bashrc
echo "$HOME/.bashrc"
tail -n 25 ~/.bashrc
cp -n ~/.bashrc ~/.bashrc.before-ros-cleanup
nano ~/.bashrc

Keep one core ROS source line, then one valid workspace source line. Remove only confirmed duplicate or invalid lines. If the workspace does not exist, remove/comment its source line until you build it.

Purpose: apply the corrected file.

source ~/.bashrc

Do not paste terminal prompts, printed paths, error messages, or package-name output as commands. udo is a typo for sudo, not a package you need. >> ~/.bashrc appends; > ~/.bashrc overwrites the whole file.

If catkin_make runs out of RAM, retry with fewer jobs from the workspace root:

cd ~/catkin_ws
catkin_make -j2 -l2

#11.1 Bluetooth mouse

Purpose: install Bluetooth utilities, unblock the adapter, and start its service.

sudo apt install bluez rfkill
rfkill list
sudo rfkill unblock bluetooth
sudo systemctl enable --now bluetooth
bluetoothctl

Put the mouse into pairing mode. Inside bluetoothctl, enter:

power on
agent on
default-agent
scan on

Replace the address below with the mouse's discovered Bluetooth address, then enter these at the same Bluetooth prompt:

pair AA:BB:CC:DD:EE:FF
trust AA:BB:CC:DD:EE:FF
connect AA:BB:CC:DD:EE:FF
scan off
exit

Trust permits reconnection but cannot guarantee it if the adapter, firmware, or mouse fails. If no controller is available, inspect lsusb, lspci -k, rfkill list, and kernel logs. A 2.4 GHz receiver mouse usually needs its USB receiver; Wi-Fi installation commands are not a generic mouse driver solution.

#11.2 Disable a faulty touchpad — only if needed

Connect and test an alternative pointing device first. Run these as your desktop user, without sudo.

Purpose: disable touchpad events for the current GNOME user.

gsettings set org.gnome.desktop.peripherals.touchpad send-events disabled

Purpose: undo the change.

gsettings set org.gnome.desktop.peripherals.touchpad send-events enabled

Optional X11-only diagnostic: list devices and temporarily disable the actual touchpad, replacing the quoted name.

echo "$XDG_SESSION_TYPE"
xinput list
xinput disable "REPLACE_WITH_EXACT_TOUCHPAD_NAME"

Undo with xinput enable "REPLACE_WITH_EXACT_TOUCHPAD_NAME". Device IDs may change after reboot. xinput is not a general Wayland solution.

The chats also suggested blacklisting psmouse. That can disable other PS/2 pointing devices, does not target every I2C touchpad, and is not literally a power-off command. Prefer a touchpad-specific firmware setting for problems before login; do not apply a blanket kernel-module blacklist as routine setup.

#11.3 Pinch-to-zoom

Purpose: identify the graphical session before changing gesture settings.

echo "$XDG_SESSION_TYPE"

Gestures depend on the touchpad, desktop version, application, and X11/Wayland session. Ubuntu 20.04 commonly uses Xorg; if offered at login, Ubuntu on Wayland is the explicit alternative. Do not assume the plain “Ubuntu” entry always means Wayland. NVIDIA support may constrain the choice.

In Firefox, inspect about:config for apz.gtk.touchpad_pinch.enabled if supported by that version. Chrome's Wayland/Ozone options vary by version. These are browser settings, not terminal commands, and no single command guarantees Windows-equivalent gestures. Ctrl + +/- is a simple application zoom alternative.

#11.4 Audio on Ubuntu 20.04

Purpose: identify audio devices and the sound server.

aplay -l
pactl info
lspci -k | grep -A3 -i audio

Purpose: install the mixer tools and update available audio firmware/configuration.

sudo apt install alsa-utils pavucontrol
apt-cache policy firmware-sof-signed alsa-ucm-conf linux-firmware
sudo apt install firmware-sof-signed alsa-ucm-conf linux-firmware

If a package has no candidate, stop and check the Focal repositories; do not add another Ubuntu release. Firmware does not fix every amplifier/codec issue.

Purpose: choose the correct output/profile and unmute the correct hardware channels.

pavucontrol

Close it when done, then:

alsamixer

In alsamixer, use F6 to choose the intended card and M to toggle mute. Start at moderate volume. Test speakers and headphones separately.

Ubuntu 20.04 normally uses PulseAudio. The EasyEffects/PipeWire command in chat7 is not a standard Focal step. Optional PulseAudio effects, if available for your setup:

apt-cache policy pulseeffects
sudo apt install pulseeffects

Effects are not driver repairs and cannot guarantee the same sound as Windows' vendor processing.

#11.5 Laptop freezes after suspend or closing the lid

Purpose: identify supported sleep modes and inspect the previous boot's logs.

cat /sys/power/mem_sleep
journalctl --list-boots
journalctl -b -1 -u systemd-suspend.service
journalctl -b -1 -k | tail -n 120

Previous-boot logs may be unavailable if not retained. Update the appropriate drivers/kernel first and test one change at a time. Disabling sleep is not a repair for a failed resume.

Conditional test: only if deep appears in /sys/power/mem_sleep, temporarily select it, save work, and test suspend.

echo deep | sudo tee /sys/power/mem_sleep
systemctl suspend

Wake with the power button if necessary. The mode selection resets at reboot. If this helps, preserve existing GRUB arguments and append mem_sleep_default=deep inside the quotes of GRUB_CMDLINE_LINUX_DEFAULT:

sudo cp -n /etc/default/grub /etc/default/grub.before-sleep-change
sudo nano /etc/default/grub

Example file content, not a shell command:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash mem_sleep_default=deep"

Apply and reboot:

sudo update-grub
sudo reboot

To undo, remove only mem_sleep_default=deep, run sudo update-grub, and reboot. If deep is absent, this parameter cannot create firmware support for it.

NVIDIA-specific diagnosis: inspect the installed driver's services and parameters before changing them.

systemctl status nvidia-suspend.service nvidia-resume.service nvidia-hibernate.service
grep -E 'PreserveVideoMemoryAllocations|TemporaryFilePath' /proc/driver/nvidia/params
df -h /var/tmp

The chats' video-memory-preservation option must be paired with the correct suspend/resume integration and sufficient backing storage. It is not a universal fix. Use the power-management README for the installed driver version, under NVIDIA's driver documentation, before enabling these options. Appendix D records the conditional commands.

External-drive installations: also follow section 2E.12 after shim/GRUB updates, and retest the portable USB boot path. Always shut Ubuntu down fully before disconnecting its system drive.

Purpose: keep packages updated within the configured Ubuntu release.

sudo apt update
sudo apt upgrade
rosdep update --include-eol-distros

Purpose: preview unused packages before cleanup.

sudo apt autoremove --dry-run

Only if the list is appropriate:

sudo apt autoremove

Keep a known-working fallback kernel until the new one has been tested. Back up ~/catkin_ws/src and project configuration; generated build/devel folders can be rebuilt. Share this Markdown file by USB or a repository/Gist; friends should read commands before running them rather than pipe a shared page directly into a shell.

These are optional after setup. Runtime commands need roscore and the relevant nodes running. Stop continuous commands with Ctrl+C.

#A.1 Discover packages

# List installed/discoverable ROS packages and their locations.
rospack list

# List only names.
rospack list-names

# Find an installed package.
rospack find turtlesim

# Search installable Noetic packages.
apt-cache search ros-noetic-

# Install an example extra package.
sudo apt install ros-noetic-teleop-twist-keyboard

# Inspect direct and recursive dependencies of the lab package.
rospack depends1 test_package_1
rospack depends test_package_1

# Navigate to a package and inspect its manifest.
roscd test_package_1
cat package.xml

# List package files, or copy a manifest into the current directory.
rosls turtlesim
roscp turtlesim package.xml ./turtlesim-package.xml

APT package names commonly replace underscores with hyphens, e.g. rqt_graph → ros-noetic-rqt-graph. ros2 pkg ... from chat4 is for ROS 2, not Noetic.

#A.2 Build an existing source project

Purpose: download the project's documented ROS 1/Noetic branch. Replace the URL and branch; do not assume every repository has a branch literally called noetic.

cd ~/catkin_ws/src
git clone --branch REPLACE_WITH_NOETIC_COMPATIBLE_BRANCH REPLACE_WITH_REPOSITORY_URL

Purpose: install declared dependencies, then build and activate the workspace.

cd ~/catkin_ws
rosdep install --from-paths src --ignore-src --rosdistro noetic
catkin_make
source devel/setup.bash

Proceed to the build only after resolving dependency errors. The -r used in the chats continues past failures; it does not mean dependencies were successfully installed.

Purpose: make an existing Python ROS node executable. Use its real path.

chmod +x ~/catkin_ws/src/REPLACE_WITH_PACKAGE/scripts/REPLACE_WITH_NODE.py

A Python node needs a Python 3 shebang and declared dependencies. A C++ node must be registered in its package's CMake configuration and compiled. The lengthy controller examples in chat6 are application exercises, not installation steps; some need corrections before use.

#A.3 Inspect nodes, topics, and messages in Turtlesim

# Inspect node connectivity.
rosnode list
rosnode info /turtlesim
rosnode ping /turtlesim

# Inspect topics, types, message structure, and actual data.
rostopic list
rostopic info /turtle1/cmd_vel
rostopic type /turtle1/cmd_vel
rosmsg show geometry_msgs/Twist
rostopic echo /turtle1/pose

Run these continuous/graphical commands separately:

# Measure publication frequency.
rostopic hz /turtle1/pose
# View the node/topic graph.
rosrun rqt_graph rqt_graph
# Plot pose fields.
rosrun rqt_plot rqt_plot /turtle1/pose/x /turtle1/pose/y /turtle1/pose/theta

Purpose: publish one simulated velocity command. Use only the Turtlesim topic shown here, not a physical robot's velocity topic.

rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- \
  '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

Purpose: continuously move the simulated turtle; 10 Hz provides margin over its command timeout. Stop with Ctrl+C.

rostopic pub -r 10 /turtle1/cmd_vel geometry_msgs/Twist -- \
  '[2.0, 0.0, 0.0]' '[0.0, 0.0, 1.8]'

Purpose: send an explicit stop command.

rostopic pub -1 /turtle1/cmd_vel geometry_msgs/Twist -- \
  '[0.0, 0.0, 0.0]' '[0.0, 0.0, 0.0]'

Purpose: run a separate simulator without a node-name or topic-name collision.

rosrun turtlesim turtlesim_node __ns:=second_sim __name:=turtlesim

#A.4 Services and parameters

# List and inspect services.
rosservice list
rosservice type /clear
rossrv show turtlesim/Spawn

# Clear drawn trails and spawn another turtle.
rosservice call /clear
rosservice call /spawn "{x: 2.0, y: 2.0, theta: 0.2, name: 'my_turtle'}"

# Inspect and change background parameters, then refresh the display.
rosparam list
rosparam get /turtlesim/background_g
rosparam set /turtlesim/background_r 150
rosservice call /clear

# Save parameters and load them into a separate namespace.
cd ~/catkin_ws
rosparam dump param.yaml
rosparam load param.yaml copy_turtle
rosparam get /copy_turtle/turtlesim/background_r

Use the same filename for dump/load; the chats mention a param.yaml/params.yaml typo. Loading under copy_turtle stores parameters there; it does not create a running turtle node.

#A.5 Bags, TF, and serial integration

# Record only the test topics; stop recording with Ctrl+C.
rosbag record -O turtle-test.bag /turtle1/pose /turtle1/cmd_vel
# Inspect and replay the recorded data in an isolated simulation session.
rosbag info turtle-test.bag
rosbag play turtle-test.bag

Playback republishes commands too; do not replay control bags onto a live robot unintentionally. Unlike recording every topic with -a, selecting topics limits disk consumption.

# Install the optional TF inspection tool and Graphviz renderer.
sudo apt install ros-noetic-tf2-tools graphviz

# Generate a frame diagram when a robot is publishing TF.
rosrun tf2_tools view_frames.py
# Install a serial bridge only for firmware that actually implements rosserial.
sudo apt install ros-noetic-rosserial-python

# Substitute the actual port and the baud rate configured in the firmware.
rosrun rosserial_python serial_node.py _port:=/dev/ttyUSB0 _baud:=115200

Purpose: stop a selected ROS node cleanly, or clean up stale node registrations after a crash.

rosnode kill /turtlesim
rosnode cleanup

For stuck Gazebo processes, first use Ctrl+C in the launching terminal. If needed, inspect pgrep -a gzserver and pgrep -a gzclient, then terminate only the identified processes. The blanket killall -9 from the chats is a last resort, not normal shutdown.

These are separate installation paths, not additional steps to run on the native Ubuntu system. A VM or container can keep Focal user space on newer hardware; graphics, USB, networking, and resource requirements need separate configuration. Installing a Focal container does not make the host's unsupported hardware drivers work.

#B.1 WSL2 on Windows

Purpose: inspect available distributions, install Ubuntu 20.04 if listed, and verify WSL version. Run in Windows PowerShell; installation may require Administrator rights and a restart.

wsl --list --online
wsl --set-default-version 2
wsl --install -d Ubuntu-20.04
wsl --list --verbose

If the installed distribution is version 1, convert it:

wsl --set-version Ubuntu-20.04 2

Then run the Ubuntu/ROS software steps inside that distribution. Skip partitioning, GRUB, native Ubuntu GPU-driver installation, lid management, and native kernel installation. Keep the Catkin workspace under Linux ~/, not /mnt/c. WSL graphics use the Windows/WSL stack. Microsoft WSL installation.

Purpose: install USB forwarding support for a device needed inside WSL. Microsoft USB instructions.

winget install --interactive --exact dorssel.usbipd-win
usbipd list

Bind the actual bus ID as Administrator, then attach with a WSL session running:

usbipd bind --busid REPLACE_WITH_BUS_ID
usbipd attach --wsl --busid REPLACE_WITH_BUS_ID

The device is unavailable to Windows while attached. Detach when finished:

usbipd detach --busid REPLACE_WITH_BUS_ID

#B.2 Docker — only on a host with Docker already configured

Purpose: start a disposable Noetic shell for basic CLI work.

docker run --rm -it ros:noetic-ros-base bash

This is not a desktop-full installation. Changes disappear when this container exits unless saved in an image or mounted storage; RViz/Gazebo, USB devices, and ROS networking need additional setup. Do not add permissive X11 access or --privileged just to make a basic shell work.

Use only on Focal + Noetic + Python 3, after restoring valid source URLs and checking that the exact legacy keys still fail. This adapts the unverified final suggestion in chat6; it is not evidence that every warning in that chat had the same cause. Check your package manifests before treating a true Python 2 dependency as Python 3.

Purpose: verify that the replacement packages are available.

apt-cache policy python3-catkin-pkg python3-empy python3-rospkg \
  python3-catkin-pkg-modules python3-rosdep-modules

Proceed only if the relevant candidates exist. If either destination file below already exists, inspect and back it up before modifying it.

Purpose: define local mappings restricted to Ubuntu Focal.

sudo tee /etc/ros/rosdep/focal-python.yaml >/dev/null <<'EOF'
python-catkin-pkg:
  ubuntu:
    focal: [python3-catkin-pkg]
python-empy:
  ubuntu:
    focal: [python3-empy]
python-rospkg:
  ubuntu:
    focal: [python3-rospkg]
python-catkin-pkg-modules:
  ubuntu:
    focal: [python3-catkin-pkg-modules]
python-rosdep-modules:
  ubuntu:
    focal: [python3-rosdep-modules]
EOF

Purpose: register the mapping before the default list, refresh the cache, and check resolution.

echo 'yaml file:///etc/ros/rosdep/focal-python.yaml' | \
  sudo tee /etc/ros/rosdep/sources.list.d/10-focal-python.list
rosdep update --include-eol-distros
rosdep resolve python-catkin-pkg --rosdistro noetic
rospack depends1 test_package_1

These mappings only teach rosdep what to install; they do not install the packages themselves. Re-run the workspace dependency installation from Appendix A.2 if needed. If the result is still wrong, diagnose it rather than adding increasingly broad aliases.

Purpose: disable this added override while retaining its contents, if it is no longer needed.

sudo mv -n /etc/ros/rosdep/sources.list.d/10-focal-python.list \
  /etc/ros/rosdep/sources.list.d/10-focal-python.list.disabled
rosdep update --include-eol-distros

These are conditional experiments, not proven fixes on every laptop. Record current values and make one change at a time.

#D.1 NVIDIA video-memory preservation

Only for a driver whose documentation requires the /proc/driver/nvidia/suspend integration: verify the services exist, that /var/tmp has backing storage larger than the total GPU memory plus overhead, and that no conflicting options already exist.

grep -RnsE 'PreserveVideoMemoryAllocations|TemporaryFilePath' /etc/modprobe.d/
systemctl is-enabled nvidia-suspend.service nvidia-hibernate.service nvidia-resume.service

Purpose: edit the NVIDIA power-management options; preserve/back up any existing file.

sudo nano /etc/modprobe.d/nvidia-power-management.conf

File content to add only when appropriate:

options nvidia NVreg_PreserveVideoMemoryAllocations=1 NVreg_TemporaryFilePath=/var/tmp

Purpose: enable the matching service integration and rebuild the initramfs.

sudo systemctl enable nvidia-suspend.service nvidia-hibernate.service nvidia-resume.service
sudo update-initramfs -u
sudo reboot

If unsuccessful, restore the file's prior contents and service states, rebuild the initramfs, and reboot. Enabling the hibernate service does not configure system hibernation itself. Reference: NVIDIA power-management documentation; use the corresponding documentation for your installed driver, not settings from a different driver generation.

#D.2 ACPI wake sources

Purpose: inspect wake sources if logs suggest immediate unwanted wakeups.

cat /proc/acpi/wakeup

Conditional example: only if XHC is the identified problematic entry, this toggles it. It can disable USB wake, so retain another way to wake the laptop.

echo XHC | sudo tee /proc/acpi/wakeup
cat /proc/acpi/wakeup

The same write toggles it back; read the state first. Do not toggle every enabled entry. This is not a general cure for freezes.

#D.3 Disable lid-triggered suspend temporarily

This changes behavior rather than repairing suspend; skip it if you want normal lid sleep. Desktop power settings may override logind through inhibitors.

Purpose: edit logind's lid behavior if a temporary workaround is wanted.

sudo cp -n /etc/systemd/logind.conf /etc/systemd/logind.conf.before-lid-change
sudo nano /etc/systemd/logind.conf

Set under the existing [Login] section:

HandleLidSwitch=ignore

Save work and reboot to apply. Restarting systemd-logind in an active desktop session, as suggested in the chats, can disrupt sessions. Revert the setting to restore prior behavior. An ignored lid can leave a laptop running and heating inside a bag.

You do not need a separate /home for ROS. This advanced procedure is for an ordinary unencrypted ext4 root with /home currently a normal directory on that root. LVM, encryption, Btrfs subvolumes, existing separate /home, or other mounts inside /home need a different plan. Back up data independently first.

Purpose: perform the copy while the installed system is offline, avoiding the active-session copy/rename problem in chat8.

  1. Boot Try Ubuntu from a live USB. In GParted, create a new empty ext4 partition from suitable space. Do not shrink a mounted filesystem. Identify the installed root and new home partitions using lsblk -f.
  2. Replace the two device placeholders below. Mount only the positively identified partitions. The new partition must be empty and large enough.
lsblk -f
sudo mkdir -p /mnt/installed /mnt/newhome
sudo mount /dev/REPLACE_WITH_ROOT_PARTITION /mnt/installed
sudo mount /dev/REPLACE_WITH_NEW_HOME_PARTITION /mnt/newhome
findmnt /mnt/installed
findmnt /mnt/newhome

Purpose: copy all home data with ownership, permissions, links, ACLs, and extended attributes.

sudo rsync -aHAXx --numeric-ids --info=progress2 /mnt/installed/home/ /mnt/newhome/

Purpose: verify content and metadata with a checksum dry run; inspect any differences before proceeding.

sudo rsync -aHAXxnc --numeric-ids --itemize-changes /mnt/installed/home/ /mnt/newhome/
sudo blkid /dev/REPLACE_WITH_NEW_HOME_PARTITION

Purpose: back up and edit the installed system's mount configuration, not the live USB's configuration.

sudo cp -n /mnt/installed/etc/fstab /mnt/installed/etc/fstab.before-home-move
sudo nano /mnt/installed/etc/fstab

Add a line using the new ext4 partition's actual UUID:

UUID=REPLACE_WITH_ACTUAL_UUID /home ext4 defaults 0 2

Purpose: retain the original home as a fallback and prepare the new mount point. First verify /mnt/installed/home.old does not already exist; stop if it does.

sudo test ! -e /mnt/installed/home.old && \
  sudo mv /mnt/installed/home /mnt/installed/home.old
sudo mkdir -p /mnt/installed/home
sudo chmod 755 /mnt/installed/home
sudo umount /mnt/newhome
sudo mount /dev/REPLACE_WITH_NEW_HOME_PARTITION /mnt/installed/home
findmnt /mnt/installed/home
ls -la /mnt/installed/home

Verify the expected user directories. Then unmount and reboot into the installed system:

sudo umount /mnt/installed/home
sudo umount /mnt/installed
sudo reboot

Purpose: confirm the new home mount after login.

findmnt /home
df -h /home

Check files, ownership, application settings, and ROS workspace builds. Keep /home.old until the migration is verified and an independent backup exists; the automatic rm -rf /home.old cleanup from chat8 is intentionally not part of this walkthrough.

Rollback if login fails: boot the live USB, mount the installed root, restore its saved fstab, unmount any new home mount, and restore home.old to home after confirming the current root-side home directory is empty. Preserve both copies until recovery is complete.