blob: ff9bb13a5cc7a069c80366b050b6202c63196bcf [file] [log] [blame]
#include "y2019/control_loops/superstructure/superstructure.h"
#include "aos/controls/control_loops.q.h"
#include "aos/events/event-loop.h"
#include "frc971/control_loops/control_loops.q.h"
#include "frc971/control_loops/drivetrain/drivetrain.q.h"
#include "frc971/control_loops/static_zeroing_single_dof_profiled_subsystem.h"
#include "y2019/status_light.q.h"
namespace y2019 {
namespace control_loops {
namespace superstructure {
Superstructure::Superstructure(::aos::EventLoop *event_loop,
const ::std::string &name)
: aos::controls::ControlLoop<SuperstructureQueue>(event_loop, name),
status_light_sender_(
event_loop->MakeSender<::y2019::StatusLight>(".y2019.status_light")),
drivetrain_status_fetcher_(
event_loop
->MakeFetcher<::frc971::control_loops::DrivetrainQueue::Status>(
".frc971.control_loops.drivetrain_queue.status")),
elevator_(constants::GetValues().elevator.subsystem_params),
wrist_(constants::GetValues().wrist.subsystem_params),
intake_(constants::GetValues().intake),
stilts_(constants::GetValues().stilts.subsystem_params) {}
void Superstructure::RunIteration(const SuperstructureQueue::Goal *unsafe_goal,
const SuperstructureQueue::Position *position,
SuperstructureQueue::Output *output,
SuperstructureQueue::Status *status) {
if (WasReset()) {
AOS_LOG(ERROR, "WPILib reset, restarting\n");
elevator_.Reset();
wrist_.Reset();
intake_.Reset();
stilts_.Reset();
}
elevator_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->elevator) : nullptr,
&(position->elevator),
output != nullptr ? &(output->elevator_voltage) : nullptr,
&(status->elevator));
wrist_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->wrist) : nullptr,
&(position->wrist),
output != nullptr ? &(output->wrist_voltage) : nullptr,
&(status->wrist));
intake_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->intake) : nullptr,
&(position->intake_joint),
output != nullptr ? &(output->intake_joint_voltage) : nullptr,
&(status->intake));
stilts_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->stilts) : nullptr,
&(position->stilts),
output != nullptr ? &(output->stilts_voltage) : nullptr,
&(status->stilts));
vacuum_.Iterate(unsafe_goal != nullptr ? &(unsafe_goal->suction) : nullptr,
position->suction_pressure, output, &(status->has_piece),
event_loop());
status->zeroed = status->elevator.zeroed && status->wrist.zeroed &&
status->intake.zeroed && status->stilts.zeroed;
status->estopped = status->elevator.estopped || status->wrist.estopped ||
status->intake.estopped || status->stilts.estopped;
if (output) {
if (unsafe_goal && status->intake.position > kMinIntakeAngleForRollers) {
output->intake_roller_voltage = unsafe_goal->roller_voltage;
} else {
output->intake_roller_voltage = 0.0;
}
}
if (unsafe_goal) {
if (!unsafe_goal->suction.grab_piece) {
wrist_.set_controller_index(0);
elevator_.set_controller_index(0);
} else if (unsafe_goal->suction.gamepiece_mode == 0) {
wrist_.set_controller_index(1);
elevator_.set_controller_index(1);
} else {
wrist_.set_controller_index(2);
elevator_.set_controller_index(2);
}
}
// TODO(theo) move these up when Iterate() is split
// update the goals
collision_avoidance_.UpdateGoal(status, unsafe_goal);
elevator_.set_min_position(collision_avoidance_.min_elevator_goal());
wrist_.set_min_position(collision_avoidance_.min_wrist_goal());
wrist_.set_max_position(collision_avoidance_.max_wrist_goal());
intake_.set_min_position(collision_avoidance_.min_intake_goal());
intake_.set_max_position(collision_avoidance_.max_intake_goal());
drivetrain_status_fetcher_.Fetch();
if (status && unsafe_goal) {
// Light Logic
if (status->estopped) {
// Estop is red
SendColors(1.0, 0.0, 0.0);
} else if (drivetrain_status_fetcher_.get() &&
drivetrain_status_fetcher_->line_follow_logging.frozen) {
// Vision align is flashing white for button pressed, purple for target
// acquired.
++line_blink_count_;
if (line_blink_count_ < 20) {
if (drivetrain_status_fetcher_->line_follow_logging.have_target) {
SendColors(1.0, 0.0, 1.0);
} else {
SendColors(1.0, 1.0, 1.0);
}
} else {
// And then flash with green if we have a game piece.
if (status->has_piece) {
SendColors(0.0, 1.0, 0.0);
} else {
SendColors(0.0, 0.0, 0.0);
}
}
if (line_blink_count_ > 40) {
line_blink_count_ = 0;
}
} else {
line_blink_count_ = 0;
if (status->has_piece) {
// Green if we have a game piece.
SendColors(0.0, 1.0, 0.0);
} else if (unsafe_goal->suction.gamepiece_mode == 0 &&
!status->has_piece) {
// Ball mode is orange
SendColors(1.0, 0.1, 0.0);
} else if (unsafe_goal->suction.gamepiece_mode == 1 &&
!status->has_piece) {
// Disk mode is deep blue
SendColors(0.05, 0.1, 0.5);
} else {
SendColors(0.0, 0.0, 0.0);
}
}
}
}
void Superstructure::SendColors(float red, float green, float blue) {
auto new_status_light = status_light_sender_.MakeMessage();
new_status_light->red = red;
new_status_light->green = green;
new_status_light->blue = blue;
if (!new_status_light.Send()) {
AOS_LOG(ERROR, "Failed to send lights.\n");
}
}
} // namespace superstructure
} // namespace control_loops
} // namespace y2019