blob: 0d6b6aed32e7bc41ff01a960f010be5d73c7c27b [file] [log] [blame]
Alex Perry731b4602019-02-02 22:13:01 -08001#include "frc971/control_loops/drivetrain/splinedrivetrain.h"
2
3#include "Eigen/Dense"
4
5#include "frc971/control_loops/drivetrain/drivetrain.q.h"
6#include "frc971/control_loops/drivetrain/drivetrain_config.h"
7
8const int kMaxSplineConstraints = 6;
9
10namespace frc971 {
11namespace control_loops {
12namespace drivetrain {
13
14SplineDrivetrain::SplineDrivetrain(const DrivetrainConfig<double> &dt_config)
15 : dt_config_(dt_config) {}
16
17// TODO(alex): put in another thread to avoid malloc in RT.
18void SplineDrivetrain::SetGoal(
19 const ::frc971::control_loops::DrivetrainQueue::Goal &goal) {
20 current_spline_handle_ = goal.spline_handle;
21 const ::frc971::MultiSpline &multispline = goal.spline;
22 if (multispline.spline_idx) {
23 current_spline_idx_ = multispline.spline_idx;
24 auto x = multispline.spline_x;
25 auto y = multispline.spline_y;
26 ::std::vector<Spline> splines = ::std::vector<Spline>();
27 for (int i = 0; i < multispline.spline_count; ++i) {
28 ::Eigen::Matrix<double, 2, 6> points =
29 ::Eigen::Matrix<double, 2, 6>::Zero();
30 for (int j = 0; j < 6; ++j) {
31 points(0, j) = x[i * 5 + j];
32 points(1, j) = y[i * 5 + j];
33 }
34 splines.emplace_back(Spline(points));
35 }
36
37 distance_spline_ = ::std::unique_ptr<DistanceSpline>(
38 new DistanceSpline(::std::move(splines)));
39
40 current_trajectory_ = ::std::unique_ptr<Trajectory>(
41 new Trajectory(distance_spline_.get(), dt_config_));
42
43 for (int i = 0; i < kMaxSplineConstraints; ++i) {
44 const ::frc971::Constraint &constraint = multispline.constraints[i];
45 switch (constraint.constraint_type) {
46 case 0:
47 break;
48 case 1:
49 current_trajectory_->set_longitudal_acceleration(constraint.value);
50 break;
51 case 2:
52 current_trajectory_->set_lateral_acceleration(constraint.value);
53 break;
54 case 3:
55 current_trajectory_->set_voltage_limit(constraint.value);
56 break;
57 case 4:
58 current_trajectory_->LimitVelocity(constraint.start_distance,
59 constraint.end_distance,
60 constraint.value);
61 break;
62 }
63 }
64
65 current_trajectory_->Plan();
Alex Perrya71badb2019-02-06 19:40:41 -080066 current_xva_ = current_trajectory_->FFAcceleration(0);
67 current_xva_(1) = 0.0;
68 }
69}
70
71void SplineDrivetrain::Update(bool enable) {
72 if (enable && current_trajectory_ &&
73 !current_trajectory_->is_at_end(current_state_)) {
74 next_xva_ = current_trajectory_->GetNextXVA(dt_config_.dt, &current_state_);
Alex Perry731b4602019-02-02 22:13:01 -080075 }
76}
77
78// TODO(alex): Handle drift.
79void SplineDrivetrain::SetOutput(
80 ::frc971::control_loops::DrivetrainQueue::Output *output) {
81 if (!output) {
82 return;
83 }
Alex Perrya71badb2019-02-06 19:40:41 -080084 if (!current_trajectory_) {
85 return;
86 }
Alex Perry731b4602019-02-02 22:13:01 -080087 if (current_spline_handle_ == current_spline_idx_) {
Alex Perrya71badb2019-02-06 19:40:41 -080088 if (!current_trajectory_->is_at_end(current_state_)) {
89 double current_distance = current_xva_(0);
Alex Perry731b4602019-02-02 22:13:01 -080090 ::Eigen::Matrix<double, 2, 1> FFVoltage =
91 current_trajectory_->FFVoltage(current_distance);
92 output->left_voltage = FFVoltage(0);
93 output->right_voltage = FFVoltage(1);
Alex Perrya71badb2019-02-06 19:40:41 -080094 current_xva_ = next_xva_;
Alex Perry731b4602019-02-02 22:13:01 -080095 }
96 }
97}
98
99} // namespace drivetrain
100} // namespace control_loops
101} // namespace frc971