Merge "Change entry for 2024 scouting"
diff --git a/frc971/can_logger/can_logger.cc b/frc971/can_logger/can_logger.cc
index d7c2df7..cfc3dd8 100644
--- a/frc971/can_logger/can_logger.cc
+++ b/frc971/can_logger/can_logger.cc
@@ -5,10 +5,11 @@
 CanLogger::CanLogger(aos::ShmEventLoop *event_loop,
                      std::string_view channel_name,
                      std::string_view interface_name)
-    : fd_(socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)),
-      frames_sender_(event_loop->MakeSender<CanFrame>(channel_name)) {
+    : shm_event_loop_(event_loop),
+      fd_(socket(PF_CAN, SOCK_RAW | SOCK_NONBLOCK, CAN_RAW)),
+      frames_sender_(shm_event_loop_->MakeSender<CanFrame>(channel_name)) {
   // TOOD(max): Figure out a proper priority
-  event_loop->SetRuntimeRealtimePriority(10);
+  shm_event_loop_->SetRuntimeRealtimePriority(10);
   struct ifreq ifr;
   strcpy(ifr.ifr_name, interface_name.data());
   PCHECK(ioctl(fd_.get(), SIOCGIFINDEX, &ifr) == 0)
@@ -34,7 +35,7 @@
   CHECK_EQ(opt_size, sizeof(recieve_buffer_size));
   VLOG(0) << "CAN recieve bufffer is " << recieve_buffer_size << " bytes large";
 
-  event_loop->epoll()->OnReadable(fd_.get(), [this]() { Poll(); });
+  shm_event_loop_->epoll()->OnReadable(fd_.get(), [this]() { Poll(); });
 }
 
 void CanLogger::Poll() {
diff --git a/frc971/can_logger/can_logger.h b/frc971/can_logger/can_logger.h
index a144265..6bad877 100644
--- a/frc971/can_logger/can_logger.h
+++ b/frc971/can_logger/can_logger.h
@@ -33,6 +33,8 @@
   CanLogger(const CanLogger &) = delete;
   CanLogger &operator=(const CanLogger &) = delete;
 
+  ~CanLogger() { shm_event_loop_->epoll()->DeleteFd(fd_.get()); }
+
  private:
   void Poll();
 
@@ -40,6 +42,7 @@
   // Returns true if successful and false if the recieve buffer is empty.
   bool ReadFrame();
 
+  aos::ShmEventLoop *shm_event_loop_;
   aos::ScopedFD fd_;
   aos::Sender<CanFrame> frames_sender_;
 };
diff --git a/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h b/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
index 82017a4..069914e 100644
--- a/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
+++ b/frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h
@@ -3,10 +3,26 @@
 
 #include "aos/flatbuffer_merge.h"
 #include "frc971/control_loops/profiled_subsystem.h"
+#include "frc971/control_loops/profiled_subsystem_static.h"
 #include "frc971/control_loops/state_feedback_loop_converters.h"
 
 namespace frc971::control_loops {
 
+inline void PopulateStaticZeroingSingleDOFProfiledSubsystemGoal(
+    StaticZeroingSingleDOFProfiledSubsystemGoalStatic *goal_table,
+    double unsafe_goal = 0.0, float max_velocity = 0.0,
+    float max_acceleration = 0.0, double goal_velocity = 0.0,
+    bool ignore_profile = false) {
+  goal_table->set_unsafe_goal(unsafe_goal);
+  goal_table->set_goal_velocity(goal_velocity);
+  goal_table->set_ignore_profile(ignore_profile);
+
+  frc971::ProfileParametersStatic *profile_parameters =
+      goal_table->add_profile_params();
+  profile_parameters->set_max_velocity(max_velocity);
+  profile_parameters->set_max_acceleration(max_acceleration);
+}
+
 template <typename ZeroingEstimator>
 struct StaticZeroingSingleDOFProfiledSubsystemParams {
   // Maximum voltage while the subsystem is zeroing