Moving raspberry pi rootfs creation to frc971 and updating
Upgrade to opencv 4.5, and using legacy camera driver for now
Added some additional comments and a timestamp / tracker on changes to the image
Change-Id: Iaf22f8e527b8147a5d73161a7292f78ce3114801
Signed-off-by: Jim Ostrowski <yimmy13@gmail.com>
diff --git a/frc971/raspi/rootfs/99-usb-mount.rules b/frc971/raspi/rootfs/99-usb-mount.rules
new file mode 100644
index 0000000..1884828
--- /dev/null
+++ b/frc971/raspi/rootfs/99-usb-mount.rules
@@ -0,0 +1,2 @@
+ACTION=="add",KERNEL=="sd[a-z][0-9]*",SUBSYSTEMS=="usb",RUN+="/bin/systemctl start usb-mount@%k.service"
+ACTION=="remove",KERNEL=="sd[a-z][0-9]*",SUBSYSTEMS=="usb",RUN+="/bin/systemctl stop usb-mount@%k.service"
diff --git a/frc971/raspi/rootfs/README.md b/frc971/raspi/rootfs/README.md
new file mode 100644
index 0000000..a9c7251
--- /dev/null
+++ b/frc971/raspi/rootfs/README.md
@@ -0,0 +1,50 @@
+This modifies a stock debian root filesystem to be able to operate as a vision
+pi. It is not trying to be reproducible, but should be good enough for FRC
+purposes.
+
+The default hostname and IP is pi-971-1, 10.9.71.101.
+ Username pi, password raspberry.
+
+Download 2021-10-30-raspios-bullseye-armhf-lite.img (or any newer
+bullseye version, as a .zip file) from
+`https://www.raspberrypi.org/downloads/raspberry-pi-os/`, extract
+(unzip) the .img file, and edit `modify_rootfs.sh` to point to it.
+
+Run modify_rootfs.sh to build the filesystem (you might need to hit
+return in a spot or two and will need sudo privileges to mount the
+partition):
+ * `modify_root.sh`
+
+VERY IMPORTANT NOTE: Before doing the next step, use `lsblk` to find
+the device and make absolutely sure this isn't your hard drive or
+something else. It will target /dev/sda by default, which in some
+computers is your default hard drive.
+
+After confirming the target device, edit the `make_sd.sh` script to point to the correct IMAGE filename, and run the `make_sd.sh` command,
+which takes the name of the pi as an argument:
+ * `make_sd.sh pi-971-1`
+
+OR, if you want to manually run this, you can deploy the image by
+copying the contents of the image to the SD card. You can do this
+manually, via
+ `dd if=2020-02-13-raspbian-bullseye-lite-frc-mods.img of=/dev/sdX bs=1M`
+
+From there, transfer the SD card to the pi, log in, `sudo` to `root`,
+and run `/root/bin/change_hostname.sh` to change the hostname to the
+actual target.
+
+
+A couple additional notes on setting this up:
+ * You'll likely need to install (`sudo apt install`) the emulation packages `proot` and `qemu-user-static` (or possibly `qemu-arm-static`)
+ * If the modify_root.sh script fails, you may need to manually unmount the image (`sudo umount ${PARTITION}` and `rmdir ${PARTITION}`) before running it again
+ * Don't be clever and try to link to the image file in a different folder. These scripts need access directly to the file and will fail otherwise
+
+
+Things to do once the SD card is complete, and you've booted a PI with it:
+
+ * Download the code:
+ Once this is completed, you can boot the pi with the newly flashed SD
+ card, and download the code to the pi using:
+ `bazel run -c opt --cpu=armv7 //y2022:pi_download_stripped -- PI_IP_ADDR
+
+ where PI_IP_ADDR is the IP address of the target pi, e.g., 10.9.71.101
diff --git a/frc971/raspi/rootfs/change_hostname.sh b/frc971/raspi/rootfs/change_hostname.sh
new file mode 100755
index 0000000..c9b0b35
--- /dev/null
+++ b/frc971/raspi/rootfs/change_hostname.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+set -euo pipefail
+
+HOSTNAME="$1"
+
+if [[ ! "${HOSTNAME}" =~ ^pi-[0-9]*-[0-9]$ ]]; then
+ echo "Invalid hostname ${HOSTNAME}, needs to be pi-[team#]-[pi#]"
+ exit 1
+fi
+
+TEAM_NUMBER="$(echo ${HOSTNAME} | sed 's/pi-\(.*\)-.*/\1/')"
+PI_NUMBER="$(echo ${HOSTNAME} | sed 's/pi-.*-\(.*\)/\1/')"
+IP_BASE="$(echo ${TEAM_NUMBER} | sed 's/\(.*\)\(..\)/10.\1.\2/')"
+IP="${IP_BASE}.$(( 100 + ${PI_NUMBER}))"
+
+echo "Changing to team number ${TEAM_NUMBER}, IP ${IP}"
+
+sed -i "s/^static ip_address=.*$/static ip_address=${IP}\/24/" /etc/dhcpcd.conf
+
+sed -i "s/\(127\.0\.1\.1\t\).*$/\1${HOSTNAME}/" /etc/hosts
+
+echo "${HOSTNAME}" > /etc/hostname
+
+if grep '^10\.[0-9]*\.[0-9]*\.[0-9]*\s*pi-[0-9]*-[0-9] pi[0-9]$' /etc/hosts >/dev/null ;
+then
+ sed -i "s/^10\.[0-9]*\.[0-9]*\(\.[0-9]*\s*pi-\)[0-9]*\(-[0-9] pi[0-9]\)$/${IP_BASE}\1${TEAM_NUMBER}\2/" /etc/hosts
+else
+ for i in {1..6}; do
+ echo -e "${IP_BASE}.$(( i + 100 ))\tpi-${TEAM_NUMBER}-${i} pi${i}" >> /etc/hosts
+ done
+fi
+
+if grep '^10\.[0-9]*\.[0-9]*\.2\s*roborio$' /etc/hosts >/dev/null;
+then
+ sed -i "s/^10\.[0-9]*\.[0-9]*\(\.2\s*roborio\)$/${IP_BASE}\1/" /etc/hosts
+else
+ echo -e "${IP_BASE}.2\troborio" >> /etc/hosts
+fi
+
+if grep '^10\.[0-9]*\.[0-9]*\.13\s*logger$' /etc/hosts >/dev/null;
+then
+ sed -i "s/^10\.[0-9]*\.[0-9]*\(\.13\s*logger\)$/${IP_BASE}\1/" /etc/hosts
+else
+ echo -e "${IP_BASE}.13\tlogger" >> /etc/hosts
+fi
diff --git a/frc971/raspi/rootfs/dhcpcd.conf b/frc971/raspi/rootfs/dhcpcd.conf
new file mode 100644
index 0000000..43a54b7
--- /dev/null
+++ b/frc971/raspi/rootfs/dhcpcd.conf
@@ -0,0 +1,59 @@
+# A sample configuration for dhcpcd.
+# See dhcpcd.conf(5) for details.
+
+# Allow users of this group to interact with dhcpcd via the control socket.
+#controlgroup wheel
+
+# Inform the DHCP server of our hostname for DDNS.
+hostname
+
+# Use the hardware address of the interface for the Client ID.
+clientid
+# or
+# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
+# Some non-RFC compliant DHCP servers do not reply with this set.
+# In this case, comment out duid and enable clientid above.
+#duid
+
+# Persist interface configuration when dhcpcd exits.
+persistent
+
+# Rapid commit support.
+# Safe to enable by default because it requires the equivalent option set
+# on the server to actually work.
+option rapid_commit
+
+# A list of options to request from the DHCP server.
+option domain_name_servers, domain_name, domain_search, host_name
+option classless_static_routes
+# Respect the network MTU. This is applied to DHCP routes.
+option interface_mtu
+
+# Most distributions have NTP support.
+#option ntp_servers
+
+# A ServerID is required by RFC2131.
+require dhcp_server_identifier
+
+# Generate SLAAC address using the Hardware Address of the interface
+#slaac hwaddr
+# OR generate Stable Private IPv6 Addresses based from the DUID
+slaac private
+
+# Example static IP configuration:
+interface eth0
+static ip_address=10.89.71.102/24
+#static ip6_address=fd51:42f8:caae:d92e::ff/64
+#static routers=192.168.0.1
+#static domain_name_servers=192.168.0.1 8.8.8.8 fd51:42f8:caae:d92e::1
+
+# It is possible to fall back to a static IP if DHCP fails:
+# define static profile
+#profile static_eth0
+#static ip_address=192.168.1.23/24
+#static routers=192.168.1.1
+#static domain_name_servers=192.168.1.1
+
+# fallback to static profile on eth0
+#interface eth0
+#fallback static_eth0
diff --git a/frc971/raspi/rootfs/frc971.service b/frc971/raspi/rootfs/frc971.service
new file mode 100644
index 0000000..cdfb347
--- /dev/null
+++ b/frc971/raspi/rootfs/frc971.service
@@ -0,0 +1,22 @@
+[Unit]
+Description=Start up 971 robot code
+Requires=network-online.target
+After=network-online.target
+
+[Service]
+User=pi
+Group=pi
+Type=simple
+WorkingDirectory=/home/pi/robot_code
+ExecStart=/home/pi/robot_code/starter.sh
+KillMode=mixed
+TimeoutStopSec=10
+LimitRTPRIO=60
+LimitNICE=-20
+LimitMEMLOCK=infinity
+
+Restart=always
+RestartSec=5s
+
+[Install]
+WantedBy=multi-user.target
diff --git a/frc971/raspi/rootfs/logind.conf b/frc971/raspi/rootfs/logind.conf
new file mode 100644
index 0000000..17ced30
--- /dev/null
+++ b/frc971/raspi/rootfs/logind.conf
@@ -0,0 +1,36 @@
+# This file is part of systemd.
+#
+# systemd is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation; either version 2.1 of the License, or
+# (at your option) any later version.
+#
+# See logind.conf(5) for details.
+
+[Login]
+#NAutoVTs=6
+#ReserveVT=6
+#KillUserProcesses=no
+#KillOnlyUsers=
+#KillExcludeUsers=root
+#InhibitDelayMaxSec=5
+#HandlePowerKey=poweroff
+#HandleSuspendKey=suspend
+#HandleHibernateKey=hibernate
+#HandleLidSwitch=suspend
+#HandleLidSwitchExternalPower=suspend
+#HandleLidSwitchDocked=ignore
+#PowerKeyIgnoreInhibited=no
+#SuspendKeyIgnoreInhibited=no
+#HibernateKeyIgnoreInhibited=no
+#LidSwitchIgnoreInhibited=yes
+#HoldoffTimeoutSec=30s
+#IdleAction=ignore
+#IdleActionSec=30min
+#RuntimeDirectorySize=10%
+
+# We don't want systemd removing IPC. This makes it so nothing new can talk to
+# existing channels.
+RemoveIPC=no
+#InhibitorsMax=8192
+#SessionsMax=8192
diff --git a/frc971/raspi/rootfs/make_sd.sh b/frc971/raspi/rootfs/make_sd.sh
new file mode 100755
index 0000000..81f7727
--- /dev/null
+++ b/frc971/raspi/rootfs/make_sd.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+set -e
+
+# Disk image to use for creating SD card
+# NOTE: You MUST run modify_rootfs.sh on this image BEFORE running make_sd.sh
+ORIG_IMAGE="2021-10-30-raspios-bullseye-armhf-lite.img"
+IMAGE=`echo ${ORIG_IMAGE} | sed s/.img/-frc-mods.img/`
+DEVICE="/dev/sda"
+
+if mount | grep "${DEVICE}" >/dev/null ;
+then
+ echo "Overwriting a mounted partition, is ${DEVICE} the sd card?"
+ exit 1
+fi
+
+sudo dd if=${IMAGE} of=${DEVICE} bs=1M status=progress
+
+PARTITION="${IMAGE}.partition"
+
+mkdir -p "${PARTITION}"
+sudo mount "${DEVICE}2" "${PARTITION}"
+
+function target() {
+ HOME=/root/ USER=root sudo proot -0 -q qemu-arm-static -w / -r "${PARTITION}" "$@"
+}
+
+if [ "${1}" == "" ]; then
+ echo "No hostname specified, so skipping setting it."
+ echo "You do this manually on the pi by running /root/bin/change_hostname.sh PI_NAME"
+else
+ target /root/bin/change_hostname.sh "${1}"
+fi
+
+echo "Starting a shell for any manual configuration"
+target /bin/bash --rcfile /root/.bashrc
+
+# Put a timestamp on when this card got created and by whom
+TIMESTAMP_FILE="${PARTITION}/home/pi/.DiskFlashedDate.txt"
+date > "${TIMESTAMP_FILE}"
+git rev-parse HEAD >> "${TIMESTAMP_FILE}"
+whoami >> "${TIMESTAMP_FILE}"
+
+# Found I had to do a lazy force unmount ("-l" flag) to make it work reliably
+sudo umount -l "${PARTITION}"
+rmdir "${PARTITION}"
diff --git a/frc971/raspi/rootfs/modify_rootfs.sh b/frc971/raspi/rootfs/modify_rootfs.sh
new file mode 100755
index 0000000..a340c64
--- /dev/null
+++ b/frc971/raspi/rootfs/modify_rootfs.sh
@@ -0,0 +1,109 @@
+#!/bin/bash
+
+set -xe
+
+# Full path to Raspberry Pi Bullseye disk image
+IMAGE="2021-10-30-raspios-bullseye-armhf-lite.img"
+BOOT_PARTITION="${IMAGE}.boot_partition"
+PARTITION="${IMAGE}.partition"
+
+function target() {
+ HOME=/root/ USER=root sudo proot -0 -q qemu-arm-static -w / -r "${PARTITION}" "$@"
+}
+
+function user_pi_target() {
+ USER=root sudo proot -0 -q qemu-arm-static -w / -r "${PARTITION}" sudo -h 127.0.0.1 -u pi "$@"
+}
+
+
+mkdir -p "${PARTITION}"
+mkdir -p "${BOOT_PARTITION}"
+
+if mount | grep "${BOOT_PARTITION}" >/dev/null ;
+then
+ echo "Already mounted"
+else
+ OFFSET="$(/sbin/fdisk -lu "${IMAGE}" | grep "${IMAGE}1" | awk '{print 512*$2}')"
+ sudo mount -o loop,offset=${OFFSET} "${IMAGE}" "${BOOT_PARTITION}"
+fi
+
+# Enable the camera on boot.
+if ! grep "start_x=1" "${BOOT_PARTITION}/config.txt"; then
+ echo "start_x=1" | sudo tee -a "${BOOT_PARTITION}/config.txt"
+fi
+if ! grep "gpu_mem=128" "${BOOT_PARTITION}/config.txt"; then
+ echo "gpu_mem=128" | sudo tee -a "${BOOT_PARTITION}/config.txt"
+fi
+# For now, disable the new libcamera driver in favor of legacy ones
+sudo sed -i s/^camera_auto_detect=1/#camera_auto_detect=1/ "${BOOT_PARTITION}/config.txt"
+
+# Seeing a race condition with umount, so doing lazy umount
+sudo umount -l "${BOOT_PARTITION}"
+rmdir "${BOOT_PARTITION}"
+
+if mount | grep "${PARTITION}" >/dev/null ;
+then
+ echo "Already mounted"
+else
+ OFFSET="$(/sbin/fdisk -lu "${IMAGE}" | grep "${IMAGE}2" | awk '{print 512*$2}')"
+
+ if [[ "$(stat -c %s "${IMAGE}")" < 2000000000 ]]; then
+ echo "Growing image"
+ dd if=/dev/zero bs=1G count=1 >> "${IMAGE}"
+ START="$(/sbin/fdisk -lu "${IMAGE}" | grep "${IMAGE}2" | awk '{print $2}')"
+
+ sed -e 's/\s*\([\+0-9a-zA-Z]*\).*/\1/' << EOF | /sbin/fdisk "${IMAGE}"
+ d # remove old partition
+ 2
+ n # new partition
+ p # primary partition
+ 2 # partion number 2
+ 532480 # start where the old one starts
+ # To the end
+ p # print the in-memory partition table
+ w # Flush
+ q # and we're done
+EOF
+
+ sudo losetup -o "${OFFSET}" -f "${IMAGE}"
+ LOOPBACK="$(sudo losetup --list | grep "${IMAGE}" | awk '{print $1}')"
+ sudo e2fsck -f "${LOOPBACK}"
+ sudo resize2fs "${LOOPBACK}"
+ sudo losetup -d "${LOOPBACK}"
+ fi
+
+ echo "Mounting"
+ sudo mount -o loop,offset=${OFFSET} "${IMAGE}" "${PARTITION}"
+fi
+
+sudo cp target_configure.sh "${PARTITION}/tmp/"
+sudo cp dhcpcd.conf "${PARTITION}/tmp/dhcpcd.conf"
+sudo cp sctp.conf "${PARTITION}/etc/sysctl.d/sctp.conf"
+sudo cp logind.conf "${PARTITION}/etc/systemd/logind.conf"
+sudo cp change_hostname.sh "${PARTITION}/tmp/change_hostname.sh"
+sudo cp frc971.service "${PARTITION}/etc/systemd/system/frc971.service"
+sudo cp rt.conf "${PARTITION}/etc/security/limits.d/rt.conf"
+sudo cp usb-mount@.service "${PARTITION}/etc/systemd/system/usb-mount@.service"
+sudo cp 99-usb-mount.rules "${PARTITION}/etc/udev/rules.d/99-usb-mount.rules"
+
+target /bin/mkdir -p /home/pi/.ssh/
+cat ~/.ssh/id_rsa.pub | target tee /home/pi/.ssh/authorized_keys
+
+# Downloads and installs our target libraries
+target /bin/bash /tmp/target_configure.sh
+
+# Add a file to show when this image was last modified and by whom
+TIMESTAMP_FILE="${PARTITION}/home/pi/.ImageModifiedDate.txt"
+date > "${TIMESTAMP_FILE}"
+git rev-parse HEAD >> "${TIMESTAMP_FILE}"
+whoami >> "${TIMESTAMP_FILE}"
+
+# Run a prompt as root inside the target to poke around and check things.
+target /bin/bash --rcfile /root/.bashrc
+
+sudo umount -l "${PARTITION}"
+rmdir "${PARTITION}"
+
+# Move the image to a different name, to indicated we've modified it
+MOD_IMAGE_NAME=`echo ${IMAGE} | sed s/.img/-frc-mods.img/`
+mv ${IMAGE} ${MOD_IMAGE_NAME}
diff --git a/frc971/raspi/rootfs/rt.conf b/frc971/raspi/rootfs/rt.conf
new file mode 100644
index 0000000..ad2c08b
--- /dev/null
+++ b/frc971/raspi/rootfs/rt.conf
@@ -0,0 +1,3 @@
+pi - nice -20
+pi - rtprio 95
+pi - memlock unlimited
diff --git a/frc971/raspi/rootfs/sctp.conf b/frc971/raspi/rootfs/sctp.conf
new file mode 100644
index 0000000..1fcf2ca
--- /dev/null
+++ b/frc971/raspi/rootfs/sctp.conf
@@ -0,0 +1,4 @@
+# https://wwwx.cs.unc.edu/~sparkst/howto/network_tuning.php
+# Make the buffers big enough for an image
+net.core.wmem_max=8388608
+net.core.rmem_max=8388608
diff --git a/frc971/raspi/rootfs/target_configure.sh b/frc971/raspi/rootfs/target_configure.sh
new file mode 100755
index 0000000..3fd4d40
--- /dev/null
+++ b/frc971/raspi/rootfs/target_configure.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+set -ex
+
+mkdir -p /root/bin
+
+# Give it a static IP
+cp /tmp/dhcpcd.conf /etc/
+
+# And provide a script to change it.
+cp /tmp/change_hostname.sh /root/bin/
+chmod a+x /root/bin/change_hostname.sh
+
+chown -R pi.pi /home/pi/.ssh
+
+apt-get update
+
+apt-get install -y vim-nox \
+ git \
+ python3-pip \
+ cpufrequtils \
+ libopencv-calib3d4.5 \
+ libopencv-contrib4.5 \
+ libopencv-core4.5 \
+ libopencv-features2d4.5 \
+ libopencv-flann4.5 \
+ libopencv-highgui4.5 \
+ libopencv-imgcodecs4.5 \
+ libopencv-imgproc4.5 \
+ libopencv-ml4.5 \
+ libopencv-objdetect4.5 \
+ libopencv-photo4.5 \
+ libopencv-shape4.5 \
+ libopencv-stitching4.5 \
+ libopencv-superres4.5 \
+ libopencv-video4.5 \
+ libopencv-videoio4.5 \
+ libopencv-videostab4.5 \
+ libopencv-viz4.5 \
+ python3-opencv \
+ libnice10 \
+ pmount \
+ libnice-dev \
+ feh
+
+echo 'GOVERNOR="performance"' > /etc/default/cpufrequtils
+
+# Add a .bashrc and friends for root.
+if [[ ! -e "/root/.dotfiles" ]]; then
+ cd /root/
+ git clone --separate-git-dir=/root/.dotfiles https://github.com/AustinSchuh/.dotfiles.git tmpdotfiles
+ rsync --recursive --verbose --exclude '.git' tmpdotfiles/ /root/
+ rm -r tmpdotfiles
+ git --git-dir=/root/.dotfiles/ --work-tree=/root/ config --local status.showUntrackedFiles no
+ # Run the vundle installer which installs plugins on the first run of vim.
+ vim -c ":qa!"
+fi
+
+# Add a .bashrc and friends for pi.
+if [[ ! -e "/home/pi/.dotfiles" ]]; then
+ cd /home/pi/
+ su -c "git clone --separate-git-dir=/home/pi/.dotfiles https://github.com/AustinSchuh/.dotfiles.git tmpdotfiles" pi
+ su -c "rsync --recursive --verbose --exclude '.git' tmpdotfiles/ /home/pi/" pi
+ su -c "rm -r tmpdotfiles" pi
+ su -c "git --git-dir=/home/pi/.dotfiles/ --work-tree=/home/pi/ config --local status.showUntrackedFiles no" pi
+ # Run the vundle installer which installs plugins on the first run of vim.
+ su -c "vim -c ':qa!'" pi
+fi
+
+# Make SSH work and not complain about pi being the username and pw still.
+rm -f /etc/profile.d/sshpwd.sh
+rm -f /etc/profile.d/wifi-check.sh
+
+systemctl enable ssh.service
+systemctl enable frc971.service
+
+# Default us to pi-971-1
+/root/bin/change_hostname.sh pi-971-1
diff --git a/frc971/raspi/rootfs/usb-mount@.service b/frc971/raspi/rootfs/usb-mount@.service
new file mode 100644
index 0000000..934d456
--- /dev/null
+++ b/frc971/raspi/rootfs/usb-mount@.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Mount USB Drive on %i
+[Service]
+Type=oneshot
+RemainAfterExit=true
+ExecStart=/usr/bin/pmount --umask 000 /dev/%i /media/%i
+ExecStop=/usr/bin/pumount /dev/%i