blob: 1f1a76bc0893c8fac715d1f52b70854b88c1c203 [file] [log] [blame]
Austin Schuh473a5652017-02-05 01:30:42 -08001#include "frc971/control_loops/profiled_subsystem.h"
2
3namespace frc971 {
4namespace control_loops {
5
6namespace {
7double UseUnlessZero(double target_value, double default_value) {
8 if (target_value != 0.0) {
9 return target_value;
10 } else {
11 return default_value;
12 }
13}
14} // namespace
15
16SingleDOFProfiledSubsystem::SingleDOFProfiledSubsystem(
17 ::std::unique_ptr<SimpleCappedStateFeedbackLoop<3, 1, 1>> loop,
18 const ::frc971::constants::ZeroingConstants &zeroing_constants,
19 const ::frc971::constants::Range &range, double default_velocity,
20 double default_acceleration)
21 : ProfiledSubsystem(::std::move(loop), {{zeroing_constants}}),
22 profile_(::aos::controls::kLoopFrequency),
23 range_(range),
24 default_velocity_(default_velocity),
25 default_acceleration_(default_acceleration) {
26 Y_.setZero();
27 offset_.setZero();
28 AdjustProfile(0.0, 0.0);
29}
30
31void SingleDOFProfiledSubsystem::UpdateOffset(double offset) {
32 const double doffset = offset - offset_(0, 0);
33 LOG(INFO, "Adjusting offset from %f to %f\n", offset_(0, 0), offset);
34
35 loop_->mutable_X_hat()(0, 0) += doffset;
36 Y_(0, 0) += doffset;
37 loop_->mutable_R(0, 0) += doffset;
38
39 profile_.MoveGoal(doffset);
40 offset_(0, 0) = offset;
41
42 CapGoal("R", &loop_->mutable_R());
43}
44
45void SingleDOFProfiledSubsystem::Correct(PotAndIndexPosition position) {
46 estimators_[0].UpdateEstimate(position);
47
48 if (estimators_[0].error()) {
49 LOG(ERROR, "zeroing error with intake_estimator\n");
50 return;
51 }
52
53 if (!initialized_) {
54 if (estimators_[0].offset_ready()) {
55 UpdateOffset(estimators_[0].offset());
56 initialized_ = true;
57 }
58 }
59
60 if (!zeroed(0) && estimators_[0].zeroed()) {
61 UpdateOffset(estimators_[0].offset());
62 set_zeroed(0, true);
63 }
64
65 Y_ << position.encoder;
66 Y_ += offset_;
67 loop_->Correct(Y_);
68}
69
70void SingleDOFProfiledSubsystem::CapGoal(const char *name,
71 Eigen::Matrix<double, 3, 1> *goal) {
72 // Limit the goal to min/max allowable angles.
73 if ((*goal)(0, 0) > range_.upper) {
74 LOG(WARNING, "Intake goal %s above limit, %f > %f\n", name, (*goal)(0, 0),
75 range_.upper);
76 (*goal)(0, 0) = range_.upper;
77 }
78 if ((*goal)(0, 0) < range_.lower) {
79 LOG(WARNING, "Intake goal %s below limit, %f < %f\n", name, (*goal)(0, 0),
80 range_.lower);
81 (*goal)(0, 0) = range_.lower;
82 }
83}
84
85void SingleDOFProfiledSubsystem::ForceGoal(double goal) {
86 set_unprofiled_goal(goal);
87 loop_->mutable_R() = unprofiled_goal_;
88 loop_->mutable_next_R() = loop_->R();
89
90 profile_.MoveCurrentState(loop_->R().block<2, 1>(0, 0));
91}
92
93void SingleDOFProfiledSubsystem::set_unprofiled_goal(double unprofiled_goal) {
94 unprofiled_goal_(0, 0) = unprofiled_goal;
95 unprofiled_goal_(1, 0) = 0.0;
96 unprofiled_goal_(2, 0) = 0.0;
97 CapGoal("unprofiled R", &unprofiled_goal_);
98}
99
100void SingleDOFProfiledSubsystem::Update(bool disable) {
101 if (!disable) {
102 ::Eigen::Matrix<double, 2, 1> goal_state =
103 profile_.Update(unprofiled_goal_(0, 0), unprofiled_goal_(1, 0));
104
105 loop_->mutable_next_R(0, 0) = goal_state(0, 0);
106 loop_->mutable_next_R(1, 0) = goal_state(1, 0);
107 loop_->mutable_next_R(2, 0) = 0.0;
108 CapGoal("next R", &loop_->mutable_next_R());
109 }
110
111 loop_->Update(disable);
112
113 if (!disable && loop_->U(0, 0) != loop_->U_uncapped(0, 0)) {
114 profile_.MoveCurrentState(loop_->R().block<2, 1>(0, 0));
115 }
116}
117
118bool SingleDOFProfiledSubsystem::CheckHardLimits() {
119 // Returns whether hard limits have been exceeded.
120
121 if (angle() > range_.upper_hard || angle() < range_.lower_hard) {
122 LOG(ERROR,
123 "SingleDOFProfiledSubsystem at %f out of bounds [%f, %f], ESTOPing\n",
124 angle(), range_.lower_hard, range_.upper_hard);
125 return true;
126 }
127
128 return false;
129}
130
131void SingleDOFProfiledSubsystem::AdjustProfile(
132 double max_angular_velocity, double max_angular_acceleration) {
133 profile_.set_maximum_velocity(
134 UseUnlessZero(max_angular_velocity, default_velocity_));
135 profile_.set_maximum_acceleration(
136 UseUnlessZero(max_angular_acceleration, default_acceleration_));
137}
138
139} // namespace control_loops
140} // namespace frc971