blob: d70cb6d7872a1a4c15f947dd439869d154f4fd7e [file] [log] [blame]
Alex Perry731b4602019-02-02 22:13:01 -08001#ifndef FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_
2#define FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_
3
Alex Perrycc3ee4c2019-02-09 21:20:41 -08004#include <atomic>
5#include <thread>
6
Alex Perrya71badb2019-02-06 19:40:41 -08007#include "Eigen/Dense"
8
Alex Perrycc3ee4c2019-02-09 21:20:41 -08009#include "aos/condition.h"
10#include "aos/mutex/mutex.h"
Alex Perry731b4602019-02-02 22:13:01 -080011#include "frc971/control_loops/drivetrain/distance_spline.h"
12#include "frc971/control_loops/drivetrain/drivetrain.q.h"
13#include "frc971/control_loops/drivetrain/drivetrain_config.h"
14#include "frc971/control_loops/drivetrain/spline.h"
15#include "frc971/control_loops/drivetrain/trajectory.h"
16
17namespace frc971 {
18namespace control_loops {
19namespace drivetrain {
20
21class SplineDrivetrain {
22 public:
23 SplineDrivetrain(const DrivetrainConfig<double> &dt_config);
24
Alex Perrycc3ee4c2019-02-09 21:20:41 -080025 ~SplineDrivetrain() {
26 {
27 ::aos::MutexLocker locker(&mutex_);
28 run_ = false;
29 new_goal_.Signal();
30 }
31 worker_thread_.join();
32 }
33
Alex Perry731b4602019-02-02 22:13:01 -080034 void SetGoal(const ::frc971::control_loops::DrivetrainQueue::Goal &goal);
35
Alex Perrye32eabc2019-02-08 19:51:19 -080036 void Update(bool enabled, const ::Eigen::Matrix<double, 5, 1> &state);
Alex Perrya71badb2019-02-06 19:40:41 -080037
Alex Perry731b4602019-02-02 22:13:01 -080038 void SetOutput(
39 ::frc971::control_loops::DrivetrainQueue::Output *output);
Alex Perry731b4602019-02-02 22:13:01 -080040 void PopulateStatus(
41 ::frc971::control_loops::DrivetrainQueue::Status *status) const;
James Kuszmaul1057ce82019-02-09 17:58:24 -080042
43 // Accessor for the current goal state, pretty much only present for debugging
44 // purposes.
Alex Perrycc3ee4c2019-02-09 21:20:41 -080045 ::Eigen::Matrix<double, 5, 1> CurrentGoalState() const {
46 return current_trajectory_
47 ? current_trajectory_->GoalState(current_xva_(0),
48 current_xva_(1))
49 : ::Eigen::Matrix<double, 5, 1>::Zero();
James Kuszmaul1057ce82019-02-09 17:58:24 -080050 }
51
52 bool IsAtEnd() const {
Alex Perrycc3ee4c2019-02-09 21:20:41 -080053 return current_trajectory_
54 ? current_trajectory_->is_at_end(current_xva_.block<2, 1>(0, 0)) :
55 true;
James Kuszmaul1057ce82019-02-09 17:58:24 -080056 }
Alex Perrycc3ee4c2019-02-09 21:20:41 -080057
58 enum class PlanState : int8_t {
59 kNoPlan = 0,
60 kBuildingTrajectory = 1,
61 kPlanningTrajectory = 2,
62 kPlannedTrajectory = 3,
63 };
64
Alex Perry731b4602019-02-02 22:13:01 -080065 private:
Alex Perrycc3ee4c2019-02-09 21:20:41 -080066 void ComputeTrajectory();
Alex Perrye32eabc2019-02-08 19:51:19 -080067 void ScaleCapU(Eigen::Matrix<double, 2, 1> *U);
68
Alex Perry731b4602019-02-02 22:13:01 -080069 const DrivetrainConfig<double> dt_config_;
70
Alex Perrycc3ee4c2019-02-09 21:20:41 -080071 int32_t current_spline_handle_ = 0; // Current spline told to excecute.
72 int32_t current_spline_idx_ = 0; // Current executing spline.
Alex Perry4b502a92019-04-06 22:00:38 -070073 bool has_started_execution_ = false;
Alex Perrye32eabc2019-02-08 19:51:19 -080074
Alex Perrycc3ee4c2019-02-09 21:20:41 -080075 ::std::unique_ptr<DistanceSpline> current_distance_spline_;
76 ::std::unique_ptr<Trajectory> current_trajectory_;
77
78 // State required to compute the next iteration's output.
79 ::Eigen::Matrix<double, 3, 1> current_xva_, next_xva_;
80 ::Eigen::Matrix<double, 2, 1> next_U_;
81
82 // Information used for status message.
83 ::Eigen::Matrix<double, 2, 1> uncapped_U_;
84 bool enable_ = false;
85 bool output_was_capped_ = false;
86
87 std::atomic<PlanState> plan_state_ = {PlanState::kNoPlan};
88
89 ::std::thread worker_thread_;
90 // mutex_ is held by the worker thread while it is doing work or by the main
91 // thread when it is sending work to the worker thread.
92 ::aos::Mutex mutex_;
93 // new_goal_ is used to signal to the worker thread that ther is work to do.
94 ::aos::Condition new_goal_;
95 // The following variables are guarded by mutex_.
96 bool run_ = true;
97 ::frc971::control_loops::DrivetrainQueue::Goal goal_;
98 ::std::unique_ptr<DistanceSpline> past_distance_spline_;
99 ::std::unique_ptr<DistanceSpline> future_distance_spline_;
100 ::std::unique_ptr<Trajectory> past_trajectory_;
101 ::std::unique_ptr<Trajectory> future_trajectory_;
102 int32_t future_spline_idx_ = 0; // Current spline being computed.
Austin Schuh6bcc2302019-03-23 22:28:06 -0700103 ::std::atomic<int32_t> planning_spline_idx_{-1};
Alex Perrye32eabc2019-02-08 19:51:19 -0800104
105 // TODO(alex): pull this out of dt_config.
106 const ::Eigen::DiagonalMatrix<double, 5> Q =
107 (::Eigen::DiagonalMatrix<double, 5>().diagonal()
Austin Schuh11043182019-03-23 22:29:12 -0700108 << 1.0 / ::std::pow(0.07, 2),
109 1.0 / ::std::pow(0.07, 2), 1.0 / ::std::pow(0.2, 2),
110 1.0 / ::std::pow(1.5, 2), 1.0 / ::std::pow(1.5, 2))
Alex Perrye32eabc2019-02-08 19:51:19 -0800111 .finished()
112 .asDiagonal();
113 const ::Eigen::DiagonalMatrix<double, 2> R =
114 (::Eigen::DiagonalMatrix<double, 2>().diagonal()
115 << 1.0 / ::std::pow(12.0, 2),
116 1.0 / ::std::pow(12.0, 2))
117 .finished()
118 .asDiagonal();
Alex Perry731b4602019-02-02 22:13:01 -0800119};
120
121} // namespace drivetrain
122} // namespace control_loops
123} // namespace frc971
124
125#endif // FRC971_CONTROL_LOOPS_DRIVETRAIN_SPLINEDRIVETRAIN_H_