blob: a9fbd8c62573d405fe35072a04cf28151656eff4 [file] [log] [blame]
#include "y2019/control_loops/superstructure/vacuum.h"
#include <chrono>
#include "frc971/control_loops/control_loops_generated.h"
#include "frc971/control_loops/profiled_subsystem_generated.h"
#include "y2019/control_loops/superstructure/superstructure_goal_generated.h"
#include "y2019/control_loops/superstructure/superstructure_output_generated.h"
namespace y2019::control_loops::superstructure {
namespace chrono = ::std::chrono;
constexpr double Vacuum::kPumpVoltage;
constexpr double Vacuum::kPumpHasPieceVoltage;
constexpr aos::monotonic_clock::duration Vacuum::kTimeAtHigherVoltage;
constexpr aos::monotonic_clock::duration Vacuum::kReleaseTime;
void Vacuum::Iterate(const SuctionGoal *unsafe_goal, float suction_pressure,
OutputT *output, bool *has_piece,
aos::EventLoop *event_loop) {
auto monotonic_now = event_loop->monotonic_now();
bool low_pump_voltage = false;
// implement a simple low-pass filter on the pressure
filtered_pressure_ = kSuctionAlpha * suction_pressure +
(1 - kSuctionAlpha) * filtered_pressure_;
const bool new_has_piece =
filtered_pressure_ < (filtered_had_piece_near_disabled_
? kVacuumOffThreshold
: kVacuumOnThreshold);
if (new_has_piece && !had_piece_) {
time_at_last_acquisition_ = monotonic_now;
}
*has_piece =
monotonic_now > time_at_last_acquisition_ + kTimeAtHigherVoltage &&
new_has_piece;
if (!output && *has_piece) {
last_disable_has_piece_time_ = monotonic_now;
}
// If we've had the piece for enough time, go to lower pump_voltage
low_pump_voltage = *has_piece && filtered_pressure_ < kVacuumOnThreshold;
if (unsafe_goal && output) {
const bool release = !unsafe_goal->grab_piece();
if (release) {
last_release_time_ = monotonic_now;
}
// Once the vacuum evacuates, the pump speeds up because there is no
// resistance. So, we want to turn it down to save the pump from
// overheating.
output->pump_voltage =
release ? 0 : (low_pump_voltage ? kPumpHasPieceVoltage : kPumpVoltage);
if (unsafe_goal->grab_piece() && unsafe_goal->gamepiece_mode() == 0) {
output->intake_suction_top = false;
output->intake_suction_bottom = true;
} else if (unsafe_goal->grab_piece() &&
unsafe_goal->gamepiece_mode() == 1) {
output->intake_suction_top = true;
output->intake_suction_bottom = true;
} else {
output->intake_suction_top = false;
output->intake_suction_bottom = false;
}
// If we intend to release, or recently released, set has_piece to false so
// that we give the part of the vacuum circuit with the pressure sensor time
// to equilibrate with the rest of the suction cup.
if (release || monotonic_now < last_release_time_ + kReleaseTime) {
*has_piece = false;
}
}
had_piece_ = new_has_piece;
filtered_had_piece_near_disabled_ =
*has_piece &&
monotonic_now < last_disable_has_piece_time_ + chrono::milliseconds(250);
}
} // namespace y2019::control_loops::superstructure