blob: 2a04ef4fc634857aa7e14eb01aa01824c01741fd [file] [log] [blame]
Austin Schuh87c10632017-02-05 19:02:17 -08001#include "y2017/control_loops/superstructure/superstructure.h"
2
3#include "aos/common/controls/control_loops.q.h"
4#include "aos/common/logging/logging.h"
5#include "y2017/constants.h"
Austin Schuhd5ccb862017-03-11 22:06:36 -08006#include "y2017/control_loops/superstructure/column/column.h"
Austin Schuh87c10632017-02-05 19:02:17 -08007#include "y2017/control_loops/superstructure/hood/hood.h"
Adam Snaider79900c22017-02-08 20:23:15 -08008#include "y2017/control_loops/superstructure/intake/intake.h"
Austin Schuhd5ccb862017-03-11 22:06:36 -08009#include "y2017/control_loops/superstructure/shooter/shooter.h"
Austin Schuh87c10632017-02-05 19:02:17 -080010
11namespace y2017 {
12namespace control_loops {
13namespace superstructure {
14
Campbell Crowley651c4b42017-02-17 22:30:50 -080015namespace {
16// The maximum voltage the intake roller will be allowed to use.
17constexpr double kMaxIntakeRollerVoltage = 12.0;
18constexpr double kMaxIndexerRollerVoltage = 12.0;
19} // namespace
20
Austin Schuh87c10632017-02-05 19:02:17 -080021Superstructure::Superstructure(
22 control_loops::SuperstructureQueue *superstructure_queue)
23 : aos::controls::ControlLoop<control_loops::SuperstructureQueue>(
24 superstructure_queue) {}
25
26void Superstructure::RunIteration(
27 const control_loops::SuperstructureQueue::Goal *unsafe_goal,
28 const control_loops::SuperstructureQueue::Position *position,
29 control_loops::SuperstructureQueue::Output *output,
30 control_loops::SuperstructureQueue::Status *status) {
31 if (WasReset()) {
32 LOG(ERROR, "WPILib reset, restarting\n");
33 hood_.Reset();
Adam Snaider79900c22017-02-08 20:23:15 -080034 intake_.Reset();
Tyler Chatow2737d2a2017-02-08 21:20:51 -080035 shooter_.Reset();
Austin Schuhd5ccb862017-03-11 22:06:36 -080036 column_.Reset();
Austin Schuh87c10632017-02-05 19:02:17 -080037 }
38
39 hood_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->hood) : nullptr,
40 &(position->hood),
41 output != nullptr ? &(output->voltage_hood) : nullptr,
42 &(status->hood));
Tyler Chatow2737d2a2017-02-08 21:20:51 -080043 shooter_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->shooter) : nullptr,
Austin Schuh932a5ce2017-03-05 01:04:18 -080044 &(position->theta_shooter), position->sent_time,
Campbell Crowley651c4b42017-02-17 22:30:50 -080045 output != nullptr ? &(output->voltage_shooter) : nullptr,
46 &(status->shooter));
Austin Schuhd5ccb862017-03-11 22:06:36 -080047
48 // Implement collision avoidance by passing down a freeze or range restricting
49 // signal to the column and intake objects.
50
51 // Wait until the column is ready before doing collision avoidance.
52 if (unsafe_goal && column_.state() == column::Column::State::RUNNING) {
53 if (!ignore_collisions_) {
54 // The turret is in a position (or wants to be in a position) where we
55 // need the intake out. Push it out.
56 if (::std::abs(unsafe_goal->turret.angle) >
57 column::Column::kTurretNearZero ||
58 ::std::abs(column_.turret_position()) >
59 column::Column::kTurretNearZero) {
60 intake_.set_min_position(column::Column::kIntakeZeroingMinDistance);
61 } else {
62 intake_.clear_min_position();
63 }
64 // The intake is in a position where it could hit. Don't move the turret.
65 if (intake_.position() < column::Column::kIntakeZeroingMinDistance -
66 column::Column::kIntakeTolerance &&
67 ::std::abs(column_.turret_position()) >
68 column::Column::kTurretNearZero) {
69 column_.set_freeze(true);
70 } else {
71 column_.set_freeze(false);
72 }
73 } else {
74 // If we are ignoring collisions, unfreeze and un-limit the min.
75 column_.set_freeze(false);
76 intake_.clear_min_position();
77 }
78 } else {
79 column_.set_freeze(false);
80 }
81
82 // Make some noise if someone left this set...
83 if (ignore_collisions_) {
84 LOG(ERROR, "Collisions ignored\n");
85 }
86
87 intake_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->intake) : nullptr,
88 &(position->intake),
89 output != nullptr ? &(output->voltage_intake) : nullptr,
90 &(status->intake));
91
92 column_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->indexer) : nullptr,
93 unsafe_goal != nullptr ? &(unsafe_goal->turret) : nullptr,
94 &(position->column),
95 output != nullptr ? &(output->voltage_indexer) : nullptr,
96 output != nullptr ? &(output->voltage_turret) : nullptr,
97 &(status->indexer), &(status->turret), &intake_);
Campbell Crowley651c4b42017-02-17 22:30:50 -080098
Austin Schuhc587c882017-03-29 21:33:10 -070099 status->estopped =
100 status->intake.estopped | status->hood.estopped | status->turret.estopped;
101
102 status->zeroed =
103 status->intake.zeroed && status->hood.zeroed && status->turret.zeroed;
104
Campbell Crowley651c4b42017-02-17 22:30:50 -0800105 if (output && unsafe_goal) {
106 output->voltage_intake_rollers =
107 ::std::max(-kMaxIntakeRollerVoltage,
108 ::std::min(unsafe_goal->intake.voltage_rollers,
109 kMaxIntakeRollerVoltage));
110 output->voltage_indexer_rollers =
111 ::std::max(-kMaxIndexerRollerVoltage,
112 ::std::min(unsafe_goal->indexer.voltage_rollers,
113 kMaxIndexerRollerVoltage));
Adam Snaidere0554ef2017-03-11 23:02:45 -0800114
115 // Set the lights on or off
116 output->lights_on = unsafe_goal->lights_on;
Austin Schuhc587c882017-03-29 21:33:10 -0700117
118 if (status->estopped) {
119 output->red_light_on = true;
120 output->green_light_on = false;
121 output->blue_light_on = false;
122 } else if (status->turret.vision_tracking) {
123 output->red_light_on = false;
124 output->green_light_on = true;
125 output->blue_light_on = false;
126 } else if (!status->zeroed) {
127 output->red_light_on = false;
128 output->green_light_on = false;
129 output->blue_light_on = true;
130 }
Campbell Crowley651c4b42017-02-17 22:30:50 -0800131 }
Austin Schuh87c10632017-02-05 19:02:17 -0800132}
133
134} // namespace superstructure
135} // namespace control_loops
136} // namespace y2017