Add 3rd Robot Auto

- 3 Cube (High, mid, low) cable side  tested at MTTD
- 1 Cube middle with mobility over charge untested
- 1 High Cube tested at MTTD

Signed-off-by: Filip Kujawa <filip.j.kujawa@gmail.com>
Change-Id: Ia4db6bea9559fe77f5fca6e866179ef866f37715
diff --git a/y2023_bot3/autonomous/auto_splines.cc b/y2023_bot3/autonomous/auto_splines.cc
index e2779c4..25277e9 100644
--- a/y2023_bot3/autonomous/auto_splines.cc
+++ b/y2023_bot3/autonomous/auto_splines.cc
@@ -102,6 +102,56 @@
       alliance);
 }
 
+flatbuffers::Offset<frc971::MultiSpline> AutonomousSplines::Spline1(
+    aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+        *builder,
+    aos::Alliance alliance) {
+  return FixSpline(
+      builder,
+      aos::CopyFlatBuffer<frc971::MultiSpline>(spline_1_, builder->fbb()),
+      alliance);
+}
+
+flatbuffers::Offset<frc971::MultiSpline> AutonomousSplines::Spline2(
+    aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+        *builder,
+    aos::Alliance alliance) {
+  return FixSpline(
+      builder,
+      aos::CopyFlatBuffer<frc971::MultiSpline>(spline_2_, builder->fbb()),
+      alliance);
+}
+
+flatbuffers::Offset<frc971::MultiSpline> AutonomousSplines::Spline3(
+    aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+        *builder,
+    aos::Alliance alliance) {
+  return FixSpline(
+      builder,
+      aos::CopyFlatBuffer<frc971::MultiSpline>(spline_3_, builder->fbb()),
+      alliance);
+}
+
+flatbuffers::Offset<frc971::MultiSpline> AutonomousSplines::Spline4(
+    aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+        *builder,
+    aos::Alliance alliance) {
+  return FixSpline(
+      builder,
+      aos::CopyFlatBuffer<frc971::MultiSpline>(spline_4_, builder->fbb()),
+      alliance);
+}
+
+flatbuffers::Offset<frc971::MultiSpline> AutonomousSplines::SplineMiddle1(
+    aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+        *builder,
+    aos::Alliance alliance) {
+  return FixSpline(builder,
+                   aos::CopyFlatBuffer<frc971::MultiSpline>(spline_middle_1_,
+                                                            builder->fbb()),
+                   alliance);
+}
+
 flatbuffers::Offset<frc971::MultiSpline> AutonomousSplines::StraightLine(
     aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
         *builder,
diff --git a/y2023_bot3/autonomous/auto_splines.h b/y2023_bot3/autonomous/auto_splines.h
index 0c9d92f..daa39b7 100644
--- a/y2023_bot3/autonomous/auto_splines.h
+++ b/y2023_bot3/autonomous/auto_splines.h
@@ -1,5 +1,5 @@
-#ifndef Y2023_AUTONOMOUS_AUTO_SPLINES_H_
-#define Y2023_AUTONOMOUS_AUTO_SPLINES_H_
+#ifndef Y2023_BOT3_AUTONOMOUS_AUTO_SPLINES_H_
+#define Y2023_BOT3_AUTONOMOUS_AUTO_SPLINES_H_
 
 #include "aos/events/event_loop.h"
 #include "aos/flatbuffer_merge.h"
@@ -20,7 +20,17 @@
  public:
   AutonomousSplines()
       : test_spline_(aos::JsonFileToFlatbuffer<frc971::MultiSpline>(
-            "splines/test_spline.json")) {}
+            "splines/test_spline.json")),
+        spline_1_(aos::JsonFileToFlatbuffer<frc971::MultiSpline>(
+            "splines/charged_up.0.json")),
+        spline_2_(aos::JsonFileToFlatbuffer<frc971::MultiSpline>(
+            "splines/charged_up.1.json")),
+        spline_3_(aos::JsonFileToFlatbuffer<frc971::MultiSpline>(
+            "splines/charged_up.2.json")),
+        spline_4_(aos::JsonFileToFlatbuffer<frc971::MultiSpline>(
+            "splines/charged_up.3.json")),
+        spline_middle_1_(aos::JsonFileToFlatbuffer<frc971::MultiSpline>(
+            "splines/charged_up_middle.0.json")) {}
   static flatbuffers::Offset<frc971::MultiSpline> BasicSSpline(
       aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
           *builder,
@@ -34,9 +44,34 @@
       aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
           *builder,
       aos::Alliance alliance);
+  flatbuffers::Offset<frc971::MultiSpline> Spline1(
+      aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+          *builder,
+      aos::Alliance alliance);
+  flatbuffers::Offset<frc971::MultiSpline> Spline2(
+      aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+          *builder,
+      aos::Alliance alliance);
+  flatbuffers::Offset<frc971::MultiSpline> Spline3(
+      aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+          *builder,
+      aos::Alliance alliance);
+  flatbuffers::Offset<frc971::MultiSpline> Spline4(
+      aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+          *builder,
+      aos::Alliance alliance);
+  flatbuffers::Offset<frc971::MultiSpline> SplineMiddle1(
+      aos::Sender<frc971::control_loops::drivetrain::SplineGoal>::Builder
+          *builder,
+      aos::Alliance alliance);
 
  private:
   aos::FlatbufferDetachedBuffer<frc971::MultiSpline> test_spline_;
+  aos::FlatbufferDetachedBuffer<frc971::MultiSpline> spline_1_;
+  aos::FlatbufferDetachedBuffer<frc971::MultiSpline> spline_2_;
+  aos::FlatbufferDetachedBuffer<frc971::MultiSpline> spline_3_;
+  aos::FlatbufferDetachedBuffer<frc971::MultiSpline> spline_4_;
+  aos::FlatbufferDetachedBuffer<frc971::MultiSpline> spline_middle_1_;
 };
 
 }  // namespace autonomous
diff --git a/y2023_bot3/autonomous/autonomous_actor.cc b/y2023_bot3/autonomous/autonomous_actor.cc
index 0aacbd1..fc794b1 100644
--- a/y2023_bot3/autonomous/autonomous_actor.cc
+++ b/y2023_bot3/autonomous/autonomous_actor.cc
@@ -12,6 +12,13 @@
 #include "y2023_bot3/control_loops/drivetrain/drivetrain_base.h"
 
 DEFINE_bool(spline_auto, false, "Run simple test S-spline auto mode.");
+DEFINE_bool(charged_up, true,
+            "If true run charged up autonomous mode. 2 Piece non-cable side");
+DEFINE_bool(charged_up_middle, false,
+            "If true run charged up middle autonomous mode. Starts middle, "
+            "places cube mid, mobility");
+DEFINE_bool(one_piece, false,
+            "End charged_up autonomous after first cube is placed.");
 
 namespace y2023_bot3 {
 namespace autonomous {
@@ -110,11 +117,32 @@
                    SplineDirection::kForward);
 
     starting_position_ = test_spline_->starting_position();
+  } else if (FLAGS_charged_up) {
+    charged_up_splines_ = {
+        PlanSpline(std::bind(&AutonomousSplines::Spline1, &auto_splines_,
+                             std::placeholders::_1, alliance_),
+                   SplineDirection::kBackward),
+        PlanSpline(std::bind(&AutonomousSplines::Spline2, &auto_splines_,
+                             std::placeholders::_1, alliance_),
+                   SplineDirection::kForward),
+        PlanSpline(std::bind(&AutonomousSplines::Spline3, &auto_splines_,
+                             std::placeholders::_1, alliance_),
+                   SplineDirection::kBackward),
+        PlanSpline(std::bind(&AutonomousSplines::Spline4, &auto_splines_,
+                             std::placeholders::_1, alliance_),
+                   SplineDirection::kForward)};
+    starting_position_ = charged_up_splines_.value()[0].starting_position();
+    CHECK(starting_position_);
+  } else if (FLAGS_charged_up_middle) {
+    charged_up_middle_splines_ = {
+        PlanSpline(std::bind(&AutonomousSplines::SplineMiddle1, &auto_splines_,
+                             std::placeholders::_1, alliance_),
+                   SplineDirection::kForward)};
   }
   is_planned_ = true;
 
   MaybeSendStartingPosition();
-}
+}  // namespace autonomous
 
 void AutonomousActor::MaybeSendStartingPosition() {
   if (is_planned_ && user_indicated_safe_to_reset_ &&
@@ -134,6 +162,8 @@
   alliance_ = joystick_state_fetcher_->alliance();
 
   preloaded_ = false;
+  roller_goal_ = control_loops::superstructure::RollerGoal::IDLE;
+  pivot_goal_ = control_loops::superstructure::PivotGoal::NEUTRAL;
   SendSuperstructureGoal();
 }
 
@@ -160,6 +190,13 @@
     return false;
   }
 
+  if (FLAGS_charged_up) {
+    ChargedUp();
+  } else {
+    AOS_LOG(INFO, "No autonomous mode selected.");
+    return false;
+  }
+
   return true;
 }
 
@@ -182,17 +219,263 @@
   }
 }
 
+// Charged Up 2 Game Object Autonomous (non-cable side)
+void AutonomousActor::ChargedUp() {
+  aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
+
+  CHECK(charged_up_splines_);
+
+  auto &splines = *charged_up_splines_;
+
+  AOS_LOG(INFO, "Going to preload");
+
+  // Tell the superstructure that a cube was preloaded
+  if (!WaitForPreloaded()) {
+    return;
+  }
+
+  // Place & Spit firt cube high
+  AOS_LOG(INFO, "Moving arm to front high scoring position");
+
+  HighScore();
+  std::this_thread::sleep_for(chrono::milliseconds(600));
+
+  SpitHigh();
+  std::this_thread::sleep_for(chrono::milliseconds(600));
+
+  StopSpitting();
+
+  std::this_thread::sleep_for(chrono::milliseconds(200));
+  AOS_LOG(
+      INFO, "Placed first cube (HIGH) %lf s\n",
+      aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
+
+  if (FLAGS_one_piece) {
+    return;
+  }
+
+  // Drive to second cube
+  if (!splines[0].WaitForPlan()) {
+    return;
+  }
+  splines[0].Start();
+
+  // Move arm into position to intake cube and intake.
+  AOS_LOG(INFO, "Moving arm to back pickup position");
+
+  Pickup();
+
+  std::this_thread::sleep_for(chrono::milliseconds(500));
+  Intake();
+
+  AOS_LOG(
+      INFO, "Turning on rollers %lf s\n",
+      aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
+
+  if (!splines[0].WaitForSplineDistanceRemaining(0.02)) {
+    return;
+  }
+
+  AOS_LOG(
+      INFO, "Got there %lf s\n",
+      aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
+
+  // Drive back to grid
+  if (!splines[1].WaitForPlan()) {
+    return;
+  }
+  splines[1].Start();
+  std::this_thread::sleep_for(chrono::milliseconds(600));
+
+  // Place Low
+  AOS_LOG(INFO, "Moving arm to front mid scoring position");
+
+  MidScore();
+
+  std::this_thread::sleep_for(chrono::milliseconds(600));
+  if (!splines[1].WaitForSplineDistanceRemaining(0.1)) return;
+
+  Spit();
+  std::this_thread::sleep_for(chrono::milliseconds(400));
+  StopSpitting();
+
+  AOS_LOG(
+      INFO, "Placed second cube (MID) %lf s\n",
+      aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
+
+  // Drive to third cube
+  if (!splines[2].WaitForPlan()) {
+    return;
+  }
+  splines[2].Start();
+
+  std::this_thread::sleep_for(chrono::milliseconds(500));
+  // Move arm into position to intake cube and intake.
+  AOS_LOG(INFO, "Moving arm to back pickup position");
+
+  Pickup();
+
+  std::this_thread::sleep_for(chrono::milliseconds(250));
+  Intake();
+
+  AOS_LOG(
+      INFO, "Turning on rollers %lf s\n",
+      aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
+
+  if (!splines[2].WaitForSplineDistanceRemaining(0.02)) {
+    return;
+  }
+
+  AOS_LOG(
+      INFO, "Got there %lf s\n",
+      aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
+
+  // Drive back to grid
+  if (!splines[3].WaitForPlan()) {
+    return;
+  }
+  splines[3].Start();
+  std::this_thread::sleep_for(chrono::milliseconds(600));
+
+  // Place Low
+  AOS_LOG(INFO, "Moving arm to front low scoring position");
+
+  LowScore();
+
+  std::this_thread::sleep_for(chrono::milliseconds(600));
+  if (!splines[3].WaitForSplineDistanceRemaining(0.1)) return;
+
+  Spit();
+  std::this_thread::sleep_for(chrono::milliseconds(600));
+  StopSpitting();
+
+  AOS_LOG(
+      INFO, "Placed low cube (LOW) %lf s\n",
+      aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
+}
+
+// Charged Up Place and Mobility Autonomous (middle)
+void AutonomousActor::ChargedUpMiddle() {
+  aos::monotonic_clock::time_point start_time = aos::monotonic_clock::now();
+
+  CHECK(charged_up_middle_splines_);
+
+  auto &splines = *charged_up_middle_splines_;
+
+  AOS_LOG(INFO, "Going to preload");
+
+  // Tell the superstructure that a cube was preloaded
+  if (!WaitForPreloaded()) {
+    return;
+  }
+
+  // Place & Spit firt cube mid
+  AOS_LOG(INFO, "Moving arm to front mid scoring position");
+
+  MidScore();
+  std::this_thread::sleep_for(chrono::milliseconds(300));
+
+  Spit();
+  std::this_thread::sleep_for(chrono::milliseconds(300));
+
+  StopSpitting();
+
+  std::this_thread::sleep_for(chrono::milliseconds(100));
+  AOS_LOG(
+      INFO, "Placed first cube (Mid) %lf s\n",
+      aos::time::DurationInSeconds(aos::monotonic_clock::now() - start_time));
+
+  // Drive to second cube
+
+  if (!splines[0].WaitForPlan()) {
+    return;
+  }
+  splines[0].Start();
+}
+
 void AutonomousActor::SendSuperstructureGoal() {
   auto builder = superstructure_goal_sender_.MakeBuilder();
 
   control_loops::superstructure::Goal::Builder superstructure_builder =
       builder.MakeBuilder<control_loops::superstructure::Goal>();
 
+  superstructure_builder.add_pivot_goal(pivot_goal_);
+  superstructure_builder.add_roller_goal(roller_goal_);
+  superstructure_builder.add_preloaded_with_cube(preloaded_);
+
   if (builder.Send(superstructure_builder.Finish()) !=
       aos::RawSender::Error::kOk) {
     AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
   }
 }
 
+[[nodiscard]] bool AutonomousActor::WaitForPreloaded() {
+  set_preloaded(true);
+  SendSuperstructureGoal();
+
+  ::aos::time::PhasedLoop phased_loop(frc971::controls::kLoopFrequency,
+                                      event_loop()->monotonic_now(),
+                                      ActorBase::kLoopOffset);
+
+  bool loaded = false;
+  while (!loaded) {
+    if (ShouldCancel()) {
+      return false;
+    }
+
+    phased_loop.SleepUntilNext();
+    superstructure_status_fetcher_.Fetch();
+    CHECK(superstructure_status_fetcher_.get() != nullptr);
+
+    loaded = (superstructure_status_fetcher_->end_effector_state() ==
+              control_loops::superstructure::EndEffectorState::LOADED);
+  }
+
+  set_preloaded(false);
+  SendSuperstructureGoal();
+
+  return true;
+}
+
+void AutonomousActor::HighScore() {
+  set_pivot_goal(control_loops::superstructure::PivotGoal::SCORE_HIGH_FRONT);
+  SendSuperstructureGoal();
+}
+void AutonomousActor::MidScore() {
+  set_pivot_goal(control_loops::superstructure::PivotGoal::SCORE_MID_FRONT);
+  SendSuperstructureGoal();
+}
+void AutonomousActor::LowScore() {
+  set_pivot_goal(control_loops::superstructure::PivotGoal::SCORE_LOW_FRONT);
+  SendSuperstructureGoal();
+}
+void AutonomousActor::Spit() {
+  set_roller_goal(control_loops::superstructure::RollerGoal::SPIT);
+  SendSuperstructureGoal();
+}
+void AutonomousActor::SpitHigh() {
+  set_roller_goal(control_loops::superstructure::RollerGoal::SPIT_HIGH);
+  SendSuperstructureGoal();
+}
+
+void AutonomousActor::StopSpitting() {
+  set_roller_goal(control_loops::superstructure::RollerGoal::IDLE);
+  SendSuperstructureGoal();
+}
+void AutonomousActor::Intake() {
+  set_roller_goal(control_loops::superstructure::RollerGoal::INTAKE_CUBE);
+  SendSuperstructureGoal();
+}
+
+void AutonomousActor::Pickup() {
+  set_pivot_goal(control_loops::superstructure::PivotGoal::PICKUP_BACK);
+  SendSuperstructureGoal();
+}
+
+void AutonomousActor::Neutral() {
+  set_pivot_goal(control_loops::superstructure::PivotGoal::NEUTRAL);
+  SendSuperstructureGoal();
+}
+
 }  // namespace autonomous
 }  // namespace y2023_bot3
diff --git a/y2023_bot3/autonomous/autonomous_actor.h b/y2023_bot3/autonomous/autonomous_actor.h
index b7978c7..ad33eed 100644
--- a/y2023_bot3/autonomous/autonomous_actor.h
+++ b/y2023_bot3/autonomous/autonomous_actor.h
@@ -1,5 +1,5 @@
-#ifndef Y2023_AUTONOMOUS_AUTONOMOUS_ACTOR_H_
-#define Y2023_AUTONOMOUS_AUTONOMOUS_ACTOR_H_
+#ifndef Y2023_BOT3_AUTONOMOUS_AUTONOMOUS_ACTOR_H_
+#define Y2023_BOT3_AUTONOMOUS_AUTONOMOUS_ACTOR_H_
 
 #include "aos/actions/actions.h"
 #include "aos/actions/actor.h"
@@ -11,6 +11,8 @@
 #include "y2023_bot3/control_loops/superstructure/superstructure_goal_generated.h"
 #include "y2023_bot3/control_loops/superstructure/superstructure_status_generated.h"
 
+// TODO<FILIP>: Add NEUTRAL pivot pose.
+
 namespace y2023_bot3 {
 namespace autonomous {
 
@@ -24,13 +26,38 @@
  private:
   void set_preloaded(bool preloaded) { preloaded_ = preloaded; }
 
+  void set_pivot_goal(
+      control_loops::superstructure::PivotGoal requested_pivot_goal) {
+    pivot_goal_ = requested_pivot_goal;
+  }
+
+  void set_roller_goal(
+      control_loops::superstructure::RollerGoal requested_roller_goal) {
+    roller_goal_ = requested_roller_goal;
+  }
+
   void SendSuperstructureGoal();
 
+  [[nodiscard]] bool WaitForPreloaded();
+
+  void HighScore();
+  void MidScore();
+  void LowScore();
+  void Spit();
+  void SpitHigh();
+  void StopSpitting();
+  void Pickup();
+  void Intake();
+  void Neutral();
+
   void Reset();
 
   void SendStartingPosition(const Eigen::Vector3d &start);
   void MaybeSendStartingPosition();
   void Replan();
+  void ChargedUp();
+  void ChargedUpMiddle();
+  void OnePieceMiddle();
 
   aos::Sender<frc971::control_loops::drivetrain::LocalizerControl>
       localizer_control_sender_;
@@ -51,11 +78,16 @@
 
   bool preloaded_ = false;
 
+  control_loops::superstructure::PivotGoal pivot_goal_;
+  control_loops::superstructure::RollerGoal roller_goal_;
+
   aos::Sender<control_loops::superstructure::Goal> superstructure_goal_sender_;
   aos::Fetcher<y2023_bot3::control_loops::superstructure::Status>
       superstructure_status_fetcher_;
 
   std::optional<SplineHandle> test_spline_;
+  std::optional<std::array<SplineHandle, 4>> charged_up_splines_;
+  std::optional<std::array<SplineHandle, 1>> charged_up_middle_splines_;
 };
 
 }  // namespace autonomous
diff --git a/y2023_bot3/autonomous/splines/charged_up.0.json b/y2023_bot3/autonomous/splines/charged_up.0.json
new file mode 100644
index 0000000..92457db
--- /dev/null
+++ b/y2023_bot3/autonomous/splines/charged_up.0.json
@@ -0,0 +1 @@
+{"spline_count": 1, "spline_x": [-6.445692607996035, -5.415058675142317, -4.209411432936082, -3.2465463700565964, -2.4298175930781793, -1.3618353380388033], "spline_y": [0.4209511918970197, 0.4209511918970197, 0.362613422112847, 0.6813475323823923, 0.5646719928140473, 0.5783738080079003], "constraints": [{"constraint_type": "LONGITUDINAL_ACCELERATION", "value": 2.5}, {"constraint_type": "LATERAL_ACCELERATION", "value": 1.5}, {"constraint_type": "VOLTAGE", "value": 10.0}]}
diff --git a/y2023_bot3/autonomous/splines/charged_up.1.json b/y2023_bot3/autonomous/splines/charged_up.1.json
new file mode 100644
index 0000000..dcb5199
--- /dev/null
+++ b/y2023_bot3/autonomous/splines/charged_up.1.json
@@ -0,0 +1 @@
+{"spline_count": 1, "spline_x": [-1.3618353380388033, -2.3872501162751885, -3.2039788932536055, -4.203904851957984, -5.409552094164219, -6.440186027017937], "spline_y": [0.5783738080079003, 0.5652181177123508, 0.6818936572806957, 0.34998739215158625, 0.40832516193575896, 0.40832516193575896], "constraints": [{"constraint_type": "LONGITUDINAL_ACCELERATION", "value": 2.5}, {"constraint_type": "LATERAL_ACCELERATION", "value": 1.5}, {"constraint_type": "VOLTAGE", "value": 10.0}]}
diff --git a/y2023_bot3/autonomous/splines/charged_up.2.json b/y2023_bot3/autonomous/splines/charged_up.2.json
new file mode 100644
index 0000000..59d6be9
--- /dev/null
+++ b/y2023_bot3/autonomous/splines/charged_up.2.json
@@ -0,0 +1 @@
+{"spline_count": 1, "spline_x": [-6.454553325309534, -4.460161354045205, -1.5509007918193776, -2.0414882541240535, -1.561168539005604, -1.2111154074787347], "spline_y": [0.5453682144642946, 0.5546337154126451, 0.8131021132876166, 0.19103636149376457, -0.3361640874334603, -0.6272868229790012], "constraints": [{"constraint_type": "LONGITUDINAL_ACCELERATION", "value": 1.2}, {"constraint_type": "LATERAL_ACCELERATION", "value": 1}, {"constraint_type": "VOLTAGE", "value": 10.0}]}
\ No newline at end of file
diff --git a/y2023_bot3/autonomous/splines/charged_up.3.json b/y2023_bot3/autonomous/splines/charged_up.3.json
new file mode 100644
index 0000000..8429898
--- /dev/null
+++ b/y2023_bot3/autonomous/splines/charged_up.3.json
@@ -0,0 +1 @@
+{"spline_count": 1, "spline_x": [-1.2111154074787347, -2.14291716567915, -3.156528585717081, -5.403636264390716, -4.837378001437765, -6.451325108951964], "spline_y": [-0.6272868229790012, 0.14764890077877224, 0.8014128668038034, 0.3355527717509894, 0.46308586049140743, 0.44756341283790313], "constraints": [{"constraint_type": "LONGITUDINAL_ACCELERATION", "value": 1.2}, {"constraint_type": "LATERAL_ACCELERATION", "value": 1}, {"constraint_type": "VOLTAGE", "value": 10}]}
\ No newline at end of file
diff --git a/y2023_bot3/autonomous/splines/charged_up_middle.0.json b/y2023_bot3/autonomous/splines/charged_up_middle.0.json
new file mode 100644
index 0000000..745672f
--- /dev/null
+++ b/y2023_bot3/autonomous/splines/charged_up_middle.0.json
@@ -0,0 +1 @@
+{"spline_count": 1, "spline_x": [-6.473051792628953, -5.825415380863309, -5.094212980482744, -4.2376615971797955, -3.04684625941716, -2.190294876114212], "spline_y": [-1.2754706248451688, -1.2754706248451688, -1.2754706248451688, -1.2754706248451688, -1.2754706248451688, -1.2754706248451688], "constraints": [{"constraint_type": "LONGITUDINAL_ACCELERATION", "value": 3}, {"constraint_type": "LATERAL_ACCELERATION", "value": 2}, {"constraint_type": "VOLTAGE", "value": 10}]}