blob: 0e8f3a5da70a3830bc0c6328d930dc7c9eed0cc5 [file] [log] [blame]
Comran Morshed2a97bc82016-01-16 17:27:01 +00001#include "y2016/control_loops/shooter/shooter.h"
2
3#include "aos/common/controls/control_loops.q.h"
4#include "aos/common/logging/logging.h"
5#include "aos/common/logging/queue_logging.h"
6
7#include "y2016/control_loops/shooter/shooter_plant.h"
8
Comran Morshedcde50322016-01-18 15:10:36 +00009
Comran Morshed2a97bc82016-01-16 17:27:01 +000010namespace y2016 {
11namespace control_loops {
Austin Schuh09c2b0b2016-02-13 15:53:16 -080012namespace shooter {
13
14// TODO(austin): Pseudo current limit?
Comran Morshed2a97bc82016-01-16 17:27:01 +000015
Comran Morshedcde50322016-01-18 15:10:36 +000016ShooterSide::ShooterSide()
Austin Schuh09c2b0b2016-02-13 15:53:16 -080017 : loop_(new StateFeedbackLoop<3, 1, 1>(MakeIntegralShooterLoop())) {
18 history_.fill(0);
19 Y_.setZero();
Comran Morshed2a97bc82016-01-16 17:27:01 +000020}
21
Austin Schuh09c2b0b2016-02-13 15:53:16 -080022void ShooterSide::set_goal(double angular_velocity_goal) {
23 loop_->mutable_next_R() << 0.0, angular_velocity_goal, 0.0;
Comran Morshedcde50322016-01-18 15:10:36 +000024}
Comran Morshed2a97bc82016-01-16 17:27:01 +000025
Austin Schuh09c2b0b2016-02-13 15:53:16 -080026void ShooterSide::set_position(double current_position) {
Comran Morshedcde50322016-01-18 15:10:36 +000027 // Update position in the model.
Austin Schuh09c2b0b2016-02-13 15:53:16 -080028 Y_ << current_position;
Comran Morshed2a97bc82016-01-16 17:27:01 +000029
Comran Morshedcde50322016-01-18 15:10:36 +000030 // Add the position to the history.
Austin Schuh09c2b0b2016-02-13 15:53:16 -080031 history_[history_position_] = current_position;
Comran Morshedcde50322016-01-18 15:10:36 +000032 history_position_ = (history_position_ + 1) % kHistoryLength;
33}
Comran Morshed2a97bc82016-01-16 17:27:01 +000034
Austin Schuh09c2b0b2016-02-13 15:53:16 -080035double ShooterSide::voltage() const {
Comran Morshedcde50322016-01-18 15:10:36 +000036 return loop_->U(0, 0);
37}
38
Austin Schuh09c2b0b2016-02-13 15:53:16 -080039void ShooterSide::Update(bool disabled) {
40 loop_->mutable_R() = loop_->next_R();
41 if (loop_->R(1, 0) < 1.0) {
42 // Kill power at low angular velocities.
43 disabled = true;
44 }
45
46 loop_->Correct(Y_);
47 loop_->Update(disabled);
Comran Morshedcde50322016-01-18 15:10:36 +000048}
49
Austin Schuh09c2b0b2016-02-13 15:53:16 -080050void ShooterSide::SetStatus(ShooterSideStatus *status) {
51 // Compute the oldest point in the history.
52 const int oldest_history_position =
53 ((history_position_ == 0) ? kHistoryLength : history_position_) - 1;
Comran Morshedcde50322016-01-18 15:10:36 +000054
Austin Schuh09c2b0b2016-02-13 15:53:16 -080055 // Compute the distance moved over that time period.
56 status->avg_angular_velocity =
57 (history_[oldest_history_position] - history_[history_position_]) /
58 (::aos::controls::kLoopFrequency.ToSeconds() *
59 static_cast<double>(kHistoryLength - 1));
60
61 status->angular_velocity = loop_->X_hat(1, 0);
62
63 // Ready if average angular velocity is close to the goal.
64 status->ready = (std::abs(loop_->next_R(1, 0) -
65 status->avg_angular_velocity) < kTolerance &&
66 loop_->next_R(1, 0) > 1.0);
67}
68
69Shooter::Shooter(ShooterQueue *my_shooter)
70 : aos::controls::ControlLoop<ShooterQueue>(my_shooter) {}
71
72void Shooter::RunIteration(const ShooterQueue::Goal *goal,
73 const ShooterQueue::Position *position,
74 ShooterQueue::Output *output,
75 ShooterQueue::Status *status) {
Comran Morshedcde50322016-01-18 15:10:36 +000076 if (goal) {
77 // Update position/goal for our two shooter sides.
Austin Schuh09c2b0b2016-02-13 15:53:16 -080078 left_.set_goal(goal->angular_velocity);
79 right_.set_goal(goal->angular_velocity);
Comran Morshedcde50322016-01-18 15:10:36 +000080 }
81
Austin Schuh09c2b0b2016-02-13 15:53:16 -080082 left_.set_position(position->theta_left);
83 right_.set_position(position->theta_right);
Comran Morshedcde50322016-01-18 15:10:36 +000084
Austin Schuh09c2b0b2016-02-13 15:53:16 -080085 left_.Update(output == nullptr);
86 right_.Update(output == nullptr);
Comran Morshedcde50322016-01-18 15:10:36 +000087
Austin Schuh09c2b0b2016-02-13 15:53:16 -080088 left_.SetStatus(&status->left);
89 right_.SetStatus(&status->right);
90 status->ready = (status->left.ready && status->right.ready);
Comran Morshed2a97bc82016-01-16 17:27:01 +000091
92 if (output) {
Austin Schuh09c2b0b2016-02-13 15:53:16 -080093 output->voltage_left = left_.voltage();
94 output->voltage_right = right_.voltage();
Comran Morshedb79c4242016-02-06 18:27:26 +000095
96 if (goal) {
97 output->clamp_open = goal->clamp_open;
98 output->push_to_shooter = goal->push_to_shooter;
99 }
Comran Morshed2a97bc82016-01-16 17:27:01 +0000100 }
101}
102
Austin Schuh09c2b0b2016-02-13 15:53:16 -0800103} // namespace shooter
Comran Morshed2a97bc82016-01-16 17:27:01 +0000104} // namespace control_loops
105} // namespace y2016