Merge "Fixing /camera channel issue on GamePieces"
diff --git a/frc971/rockpi/README.md b/frc971/rockpi/README.md
index c71ee08..4f44739 100644
--- a/frc971/rockpi/README.md
+++ b/frc971/rockpi/README.md
@@ -17,9 +17,74 @@
 
 # Installing
 
+We're currently installing the filesystem onto the eMMC of the Rock
+Pis.  This involves a multi-step process:
+
+* Create an SD card with the image.  The Pi will boot off of this in order to flash the eMMC
+
+Assuming the SD card shows up on your system as /dev/sda, then you can use the command:
+
 `sudo dd if=arm64_bullseye_debian.img of=/dev/sda status=progress`
 
-The default user is `pi`, and password is `raspberry`.
+WARNING: any time you're using 'dd' to write data, make SURE you've got the right output
+device, e.g., here of=/dev/sda.  It's possible your hard drive is /dev/sda, and you
+don't want to over-write that!!
+
+* Create a USB drive with the image on it.  We'll use this to copy the image to the eMMC
+
+We're using the xfs filesystem for USB thumb drives.  To create this, do the following:
+* Insert the thumbdrive
+* Figure out which device this is and unmount it.  E.g., if it's /dev/sdb1, do
+  * `sudo umount /dev/sdb1`
+* Run fdisk to create an empty partition:
+  * `sudo fdisk /dev/sdb`
+  * Type "o" to create an empty DOS partition table
+  * Type "n" to create a new partition
+  * Type "p" to select primary partition
+  * Accept the next 3 default values (1, 2048, 500170751) (or whatever end block is given)
+  * Type "w" to write this information to the partition table
+* Run mkfs to make this an xfs file system:
+  * `sudo mkfs -t xfs -f /dev/sdb1`
+    * (Note, you might have to install the xfs file system support for mkfs)
+* Change permissions on the drive to make it write-able
+  * `sudo chmod a+rwx [path-to-drive]`
+    * where `[path-to-drive]` is the path to the drive, e.g., /media/jim/XXXX
+    (I believe /dev/sdb1 should work, also)
+
+# Writing the disk image to the eMMC
+
+Insert the SD card and the thumbdrive and boot the Pi.
+
+It should come up as pi-971-1 (IP: 10.9.71.101).  The default user is
+`pi`, and password is `raspberry`.  Note: if you don't have your ssh
+key installed, you should get that added to the base image.
+
+Once booted, login and write the image to the eMMC:
+
+`sudo dd if=/media/sda1/arm64_bullseye_debian.img of=/dev/mmcblk1 status=progress`
+
+Then, power down the Pi, remove the SD card and the USB thumb drive, and power on the Pi
+
+Once it's up, login again.
+
+Change the hostname to the desired hostname, e.g., if you want it to be pi-9971-2, use
+
+`sudo /root/bin/change_hostname.sh pi-9971-2`
+
+It's a good idea here to reboot the Pi one more time to make sure it
+came up with the expected IP address and hostname.
+
+# Additional steps in setting up the Rock Pis
+
+We also have been plugging in a USB thumb drive to each Pi to do logging.
+
+We are formatting these as xfs filesystems.  To do this follow the
+above instructions on a new USB drive to format as xfs.
+
+That's it!!
+
+
+# Other notes:
 
 # State of RK3399 image processing.
 
diff --git a/frc971/rockpi/build_rootfs.sh b/frc971/rockpi/build_rootfs.sh
index 78ae6ac..d19a260 100755
--- a/frc971/rockpi/build_rootfs.sh
+++ b/frc971/rockpi/build_rootfs.sh
@@ -12,14 +12,14 @@
 # Check if dependencies are missing.
 missing_deps=()
 REQUIRED_DEPS=(
-    flex
     bison
-    gcc-arm-none-eabi
-    gcc-aarch64-linux-gnu
-    u-boot-tools
-    device-tree-compiler
-    swig
     debootstrap
+    device-tree-compiler
+    flex
+    gcc-aarch64-linux-gnu
+    gcc-arm-none-eabi
+    swig
+    u-boot-tools
 )
 for dep in "${REQUIRED_DEPS[@]}"; do
     if ! dpkg-query -W -f='${Status}' "${dep}" | grep -q "install ok installed"; then
@@ -258,6 +258,13 @@
 
 target "apt-get clean"
 
+# Add a file to show when this image was last modified and by whom
+TIMESTAMP_FILE="${PARTITION}/home/pi/.ImageModifiedDate.txt"
+echo "Date modified:"`date` > "${TIMESTAMP_FILE}"
+echo "Image file: ${IMAGE}"  >> "${TIMESTAMP_FILE}"
+echo "Git tag: "`git rev-parse HEAD` >> "${TIMESTAMP_FILE}"
+echo "User: "`whoami` >> "${TIMESTAMP_FILE}"
+
 sudo chroot ${PARTITION} qemu-aarch64-static /bin/bash
 
 # TODO(austin): This appears to not be working...  pi_target doesn't apper to be happy
diff --git a/frc971/rockpi/contents/root/bin/change_hostname.sh b/frc971/rockpi/contents/root/bin/change_hostname.sh
index 43e6528..785903e 100755
--- a/frc971/rockpi/contents/root/bin/change_hostname.sh
+++ b/frc971/rockpi/contents/root/bin/change_hostname.sh
@@ -33,10 +33,16 @@
 # Put corret team number in pi's IP addresses, or add them if needed
 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
+  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\3/" /etc/hosts
 else
   for i in {1..6}; do
-    echo -e "${IP_BASE}.$(( i + 100 ))\tpi-${TEAM_NUMBER}-${i} pi${i}" >> /etc/hosts
+      imu=""
+      # Add imu name to pi6.  Put space in this string, since extra
+      # spaces otherwise will make the above grep fail
+      if [[ ${i} == 6 ]]; then
+          imu=" imu"
+      fi
+    echo -e "${IP_BASE}.$(( i + 100 ))\tpi-${TEAM_NUMBER}-${i} pi${i}${imu}" >> /etc/hosts
   done
 fi
 
diff --git a/y2023/constants.h b/y2023/constants.h
index 059a3f0..de665d9 100644
--- a/y2023/constants.h
+++ b/y2023/constants.h
@@ -154,6 +154,32 @@
     return std::chrono::seconds(2);
   }
 
+  // if true, tune down all the arm constants for testing.
+  static constexpr bool kArmGrannyMode() { return false; }
+
+  // the operating voltage.
+  static constexpr double kArmOperatingVoltage() {
+    return kArmGrannyMode() ? 6.0 : 12.0;
+  }
+  static constexpr double kArmDt() { return 0.00505; }
+  static constexpr std::chrono::nanoseconds kArmDtDuration() {
+    return std::chrono::duration_cast<std::chrono::nanoseconds>(
+        std::chrono::duration<double>(kArmDt()));
+  }
+  static constexpr double kArmAlpha0Max() {
+    return kArmGrannyMode() ? 15.0 : 15.0;
+  }
+  static constexpr double kArmAlpha1Max() {
+    return kArmGrannyMode() ? 10.0 : 10.0;
+  }
+  static constexpr double kArmAlpha2Max() {
+    return kArmGrannyMode() ? 90.0 : 90.0;
+  }
+
+  static constexpr double kArmVMax() { return kArmGrannyMode() ? 4.0 : 9.5; }
+  static constexpr double kArmPathlessVMax() { return 4.5; }
+  static constexpr double kArmGotoPathVMax() { return 4.5; }
+
   struct PotConstants {
     ::frc971::control_loops::StaticZeroingSingleDOFProfiledSubsystemParams<
         ::frc971::zeroing::RelativeEncoderZeroingEstimator>
diff --git a/y2023/control_loops/superstructure/arm/arm.cc b/y2023/control_loops/superstructure/arm/arm.cc
index fd5d83f..27a1450 100644
--- a/y2023/control_loops/superstructure/arm/arm.cc
+++ b/y2023/control_loops/superstructure/arm/arm.cc
@@ -26,8 +26,9 @@
       distal_offset_(0.0),
       roll_joint_offset_(0.0),
       alpha_unitizer_((::Eigen::DiagonalMatrix<double, 3>().diagonal()
-                           << (1.0 / kAlpha0Max()),
-                       (1.0 / kAlpha1Max()), (1.0 / kAlpha2Max()))
+                           << (1.0 / constants::Values::kArmAlpha0Max()),
+                       (1.0 / constants::Values::kArmAlpha1Max()),
+                       (1.0 / constants::Values::kArmAlpha2Max()))
                           .finished()),
       dynamics_(kArmConstants),
       close_enough_for_full_power_(false),
@@ -36,7 +37,8 @@
       hybrid_roll_joint_loop_(roll::MakeIntegralHybridRollLoop()),
       arm_ekf_(&dynamics_),
       search_graph_(MakeSearchGraph(&dynamics_, &trajectories_, alpha_unitizer_,
-                                    kVMax(), &hybrid_roll_joint_loop_)),
+                                    constants::Values::kArmVMax(),
+                                    &hybrid_roll_joint_loop_)),
       // Go to the start of the first trajectory.
       follower_(&dynamics_, &hybrid_roll_joint_loop_, NeutralPoint()),
       points_(PointList()),
@@ -117,7 +119,7 @@
     *roll_joint_output = 0.0;
   }
 
-  arm_ekf_.Correct(Y_arm, kDt());
+  arm_ekf_.Correct(Y_arm, constants::Values::kArmDt());
   roll_joint_loop_.Correct(Y_roll_joint);
 
   if (::std::abs(arm_ekf_.X_hat(0) - follower_.theta(0)) <= 0.05 &&
@@ -276,16 +278,21 @@
 
   const double max_operating_voltage =
       close_enough_for_full_power_
-          ? kOperatingVoltage()
-          : (state_ == ArmState::GOTO_PATH ? kGotoPathVMax() : kPathlessVMax());
+          ? constants::Values::kArmOperatingVoltage()
+          : (state_ == ArmState::GOTO_PATH
+                 ? constants::Values::kArmGotoPathVMax()
+                 : constants::Values::kArmPathlessVMax());
   ::Eigen::Matrix<double, 9, 1> X_hat;
   X_hat.block<6, 1>(0, 0) = arm_ekf_.X_hat();
   X_hat.block<3, 1>(6, 0) = roll_joint_loop_.X_hat();
 
-  follower_.Update(X_hat, disable, kDt(), vmax_, max_operating_voltage);
+  follower_.Update(X_hat, disable, constants::Values::kArmDt(), vmax_,
+                   max_operating_voltage);
+  AOS_LOG(INFO, "Max voltage: %f\n", max_operating_voltage);
 
-  arm_ekf_.Predict(follower_.U().head<2>(), kDt());
-  roll_joint_loop_.UpdateObserver(follower_.U().tail<1>(), kDtDuration());
+  arm_ekf_.Predict(follower_.U().head<2>(), constants::Values::kArmDt());
+  roll_joint_loop_.UpdateObserver(follower_.U().tail<1>(),
+                                  constants::Values::kArmDtDuration());
 
   flatbuffers::Offset<frc971::PotAndAbsoluteEncoderEstimatorState>
       proximal_estimator_state_offset =
@@ -329,11 +336,14 @@
 
   if (!disable) {
     *proximal_output = ::std::max(
-        -kOperatingVoltage(), ::std::min(kOperatingVoltage(), follower_.U(0)));
+        -constants::Values::kArmOperatingVoltage(),
+        ::std::min(constants::Values::kArmOperatingVoltage(), follower_.U(0)));
     *distal_output = ::std::max(
-        -kOperatingVoltage(), ::std::min(kOperatingVoltage(), follower_.U(1)));
+        -constants::Values::kArmOperatingVoltage(),
+        ::std::min(constants::Values::kArmOperatingVoltage(), follower_.U(1)));
     *roll_joint_output = ::std::max(
-        -kOperatingVoltage(), ::std::min(kOperatingVoltage(), follower_.U(2)));
+        -constants::Values::kArmOperatingVoltage(),
+        ::std::min(constants::Values::kArmOperatingVoltage(), follower_.U(2)));
   }
 
   status_builder.add_path_distance_to_go(follower_.path_distance_to_go());
diff --git a/y2023/control_loops/superstructure/arm/arm.h b/y2023/control_loops/superstructure/arm/arm.h
index 6b7da54..216b89d 100644
--- a/y2023/control_loops/superstructure/arm/arm.h
+++ b/y2023/control_loops/superstructure/arm/arm.h
@@ -23,26 +23,6 @@
  public:
   Arm(std::shared_ptr<const constants::Values> values);
 
-  // if true, tune down all the constants for testing.
-  static constexpr bool kGrannyMode() { return false; }
-
-  // the operating voltage.
-  static constexpr double kOperatingVoltage() {
-    return kGrannyMode() ? 6.0 : 12.0;
-  }
-  static constexpr double kVMax() { return kGrannyMode() ? 4.0 : 9.5; }
-  static constexpr double kPathlessVMax() { return 4.5; }
-  static constexpr double kGotoPathVMax() { return 4.5; }
-
-  static constexpr double kDt() { return 0.00505; }
-  static constexpr std::chrono::nanoseconds kDtDuration() {
-    return std::chrono::duration_cast<std::chrono::nanoseconds>(
-        std::chrono::duration<double>(kDt()));
-  }
-  static constexpr double kAlpha0Max() { return kGrannyMode() ? 15.0 : 15.0; }
-  static constexpr double kAlpha1Max() { return kGrannyMode() ? 10.0 : 10.0; }
-  static constexpr double kAlpha2Max() { return kGrannyMode() ? 90.0 : 90.0; }
-
   flatbuffers::Offset<superstructure::ArmStatus> Iterate(
       const ::aos::monotonic_clock::time_point /*monotonic_now*/,
       const uint32_t *unsafe_goal, const superstructure::ArmPosition *position,
@@ -89,7 +69,7 @@
 
   const ::Eigen::DiagonalMatrix<double, 3> alpha_unitizer_;
 
-  double vmax_ = kVMax();
+  double vmax_ = constants::Values::kArmVMax();
 
   frc971::control_loops::arm::Dynamics dynamics_;
 
diff --git a/y2023/control_loops/superstructure/superstructure_lib_test.cc b/y2023/control_loops/superstructure/superstructure_lib_test.cc
index 3252030..2a67adf 100644
--- a/y2023/control_loops/superstructure/superstructure_lib_test.cc
+++ b/y2023/control_loops/superstructure/superstructure_lib_test.cc
@@ -127,8 +127,7 @@
   double roll_joint_velocity() const { return roll_joint_loop_.X_hat(1, 0); }
 
   void Simulate(::Eigen::Matrix<double, 3, 1> U) {
-    constexpr double voltage_check =
-        superstructure::arm::Arm::kOperatingVoltage();
+    constexpr double voltage_check = constants::Values::kArmOperatingVoltage();
 
     AOS_CHECK_LE(::std::abs(U(0)), voltage_check);
     AOS_CHECK_LE(::std::abs(U(1)), voltage_check);