blob: da644089222605fb39e8f1a333e356caa3908a2a [file] [log] [blame]
#include "y2020/actors/autonomous_actor.h"
#include <inttypes.h>
#include <chrono>
#include <cmath>
#include "aos/logging/logging.h"
#include "aos/util/math.h"
#include "frc971/control_loops/drivetrain/localizer_generated.h"
#include "y2020/actors/auto_splines.h"
#include "y2020/control_loops/drivetrain/drivetrain_base.h"
DEFINE_bool(spline_auto, false, "If true, define a spline autonomous mode");
DEFINE_bool(ignore_vision, false, "If true, ignore vision");
DEFINE_bool(galactic_search, false,
"If true, do the galactic search autonomous");
DEFINE_bool(bounce, false, "If true, run the AutoNav Bounce autonomous");
DEFINE_bool(barrel, false, "If true, run the AutoNav Barrel autonomous");
DEFINE_bool(slalom, true, "If true, run the AutoNav Slalom autonomous");
namespace y2020 {
namespace actors {
using ::aos::monotonic_clock;
using ::frc971::ProfileParametersT;
using frc971::control_loops::drivetrain::LocalizerControl;
namespace chrono = ::std::chrono;
AutonomousActor::AutonomousActor(::aos::EventLoop *event_loop)
: frc971::autonomous::BaseAutonomousActor(
event_loop, control_loops::drivetrain::GetDrivetrainConfig()),
localizer_control_sender_(
event_loop->MakeSender<
::frc971::control_loops::drivetrain::LocalizerControl>(
"/drivetrain")),
superstructure_goal_sender_(
event_loop->MakeSender<control_loops::superstructure::Goal>(
"/superstructure")),
joystick_state_fetcher_(
event_loop->MakeFetcher<aos::JoystickState>("/aos")),
path_fetcher_(event_loop->MakeFetcher<y2020::vision::GalacticSearchPath>(
"/pi2/camera")),
auto_splines_() {
set_max_drivetrain_voltage(2.0);
replan_timer_ = event_loop->AddTimer([this]() { Replan(); });
event_loop->OnRun([this, event_loop]() {
replan_timer_->Setup(event_loop->monotonic_now());
});
}
void AutonomousActor::Replan() {
if (FLAGS_galactic_search) {
galactic_search_splines_ = {
.red_a = PlanSpline(std::bind(&AutonomousSplines::SplineRedA,
&auto_splines_, std::placeholders::_1),
SplineDirection::kForward),
.red_b = PlanSpline(std::bind(&AutonomousSplines::SplineRedB,
&auto_splines_, std::placeholders::_1),
SplineDirection::kForward),
.blue_a = PlanSpline(std::bind(&AutonomousSplines::SplineBlueA,
&auto_splines_, std::placeholders::_1),
SplineDirection::kForward),
.blue_b = PlanSpline(std::bind(&AutonomousSplines::SplineBlueB,
&auto_splines_, std::placeholders::_1),
SplineDirection::kForward)};
} else if (FLAGS_bounce) {
bounce_splines_ = {
PlanSpline(std::bind(&AutonomousSplines::AutoNavBounce1, &auto_splines_,
std::placeholders::_1),
SplineDirection::kForward),
PlanSpline(std::bind(&AutonomousSplines::AutoNavBounce2, &auto_splines_,
std::placeholders::_1),
SplineDirection::kBackward),
PlanSpline(std::bind(&AutonomousSplines::AutoNavBounce3, &auto_splines_,
std::placeholders::_1),
SplineDirection::kForward),
PlanSpline(std::bind(&AutonomousSplines::AutoNavBounce4, &auto_splines_,
std::placeholders::_1),
SplineDirection::kBackward)};
} else if (FLAGS_barrel) {
barrel_spline_ =
PlanSpline(std::bind(&AutonomousSplines::AutoNavBarrel, &auto_splines_,
std::placeholders::_1),
SplineDirection::kForward);
} else if (FLAGS_slalom) {
slalom_spline_ =
PlanSpline(std::bind(&AutonomousSplines::AutoNavSlalom, &auto_splines_,
std::placeholders::_1),
SplineDirection::kForward);
} else if (FLAGS_spline_auto) {
test_spline_ =
PlanSpline(std::bind(&AutonomousSplines::TestSpline, &auto_splines_,
std::placeholders::_1),
SplineDirection::kForward);
}
}
void AutonomousActor::Reset() {
InitializeEncoders();
ResetDrivetrain();
RetractIntake();
joystick_state_fetcher_.Fetch();
CHECK(joystick_state_fetcher_.get() != nullptr)
<< "Expect at least one JoystickState message before running auto...";
alliance_ = joystick_state_fetcher_->alliance();
}
bool AutonomousActor::RunAction(
const ::frc971::autonomous::AutonomousActionParams *params) {
Reset();
// Queue up a replan to occur as soon as this action completes.
// TODO(james): Modify this so we don't replan during teleop.
replan_timer_->Setup(monotonic_now());
AOS_LOG(INFO, "Params are %d\n", params->mode());
if (alliance_ == aos::Alliance::kInvalid) {
AOS_LOG(INFO, "Aborting autonomous due to invalid alliance selection.");
return false;
}
if (FLAGS_galactic_search) {
GalacticSearch();
} else if (FLAGS_bounce) {
AutoNavBounce();
} else if (FLAGS_barrel) {
AutoNavBarrel();
} else if (FLAGS_slalom) {
AutoNavSlalom();
} else if (FLAGS_spline_auto) {
SplineAuto();
} else {
return DriveFwd();
}
return true;
}
void AutonomousActor::SendStartingPosition(const Eigen::Vector3d &start) {
// Set up the starting position for the blue alliance.
// TODO(james): Resetting the localizer breaks the left/right statespace
// controller. That is a bug, but we can fix that later by not resetting.
auto builder = localizer_control_sender_.MakeBuilder();
LocalizerControl::Builder localizer_control_builder =
builder.MakeBuilder<LocalizerControl>();
localizer_control_builder.add_x(start(0));
localizer_control_builder.add_y(start(1));
localizer_control_builder.add_theta(start(2));
localizer_control_builder.add_theta_uncertainty(0.00001);
if (!builder.Send(localizer_control_builder.Finish())) {
AOS_LOG(ERROR, "Failed to reset localizer.\n");
}
}
void AutonomousActor::GalacticSearch() {
CHECK(galactic_search_splines_);
path_fetcher_.Fetch();
SplineHandle *spline = nullptr;
if (path_fetcher_.get()) {
if (path_fetcher_->alliance() == y2020::vision::Alliance::kUnknown) {
AOS_LOG(ERROR, "The galactic search path is unknown, doing nothing.");
return;
}
if (path_fetcher_->alliance() == y2020::vision::Alliance::kRed) {
if (path_fetcher_->letter() == y2020::vision::Letter::kA) {
LOG(INFO) << "Red A";
spline = &galactic_search_splines_->red_a;
} else {
LOG(INFO) << "Red B";
CHECK(path_fetcher_->letter() == y2020::vision::Letter::kB);
spline = &galactic_search_splines_->red_b;
}
} else {
if (path_fetcher_->letter() == y2020::vision::Letter::kA) {
LOG(INFO) << "Blue A";
spline = &galactic_search_splines_->blue_a;
} else {
LOG(INFO) << "Blue B";
CHECK(path_fetcher_->letter() == y2020::vision::Letter::kB);
spline = &galactic_search_splines_->blue_b;
}
}
}
if (FLAGS_ignore_vision) {
LOG(INFO) << "Forcing Red B";
spline = &galactic_search_splines_->red_b;
}
CHECK(spline != nullptr)
<< "Expect at least one GalacticSearchPath message before running "
"auto...";
SendStartingPosition(spline->starting_position());
set_intake_goal(1.25);
set_roller_voltage(12.0);
SendSuperstructureGoal();
if (!spline->WaitForPlan()) return;
spline->Start();
if (!spline->WaitForSplineDistanceRemaining(0.02)) return;
RetractIntake();
}
void AutonomousActor::AutoNavBounce() {
CHECK(bounce_splines_);
auto &splines = *bounce_splines_;
SendStartingPosition(splines[0].starting_position());
if (!splines[0].WaitForPlan()) return;
splines[0].Start();
if (!splines[0].WaitForSplineDistanceRemaining(0.02)) return;
if (!splines[1].WaitForPlan()) return;
splines[1].Start();
if (!splines[1].WaitForSplineDistanceRemaining(0.02)) return;
if (!splines[2].WaitForPlan()) return;
splines[2].Start();
if (!splines[2].WaitForSplineDistanceRemaining(0.02)) return;
if (!splines[3].WaitForPlan()) return;
splines[3].Start();
if (!splines[3].WaitForSplineDistanceRemaining(0.02)) return;
}
void AutonomousActor::AutoNavBarrel() {
CHECK(barrel_spline_);
SendStartingPosition(barrel_spline_->starting_position());
if (!barrel_spline_->WaitForPlan()) return;
barrel_spline_->Start();
if (!barrel_spline_->WaitForSplineDistanceRemaining(0.02)) return;
}
void AutonomousActor::AutoNavSlalom() {
CHECK(slalom_spline_);
SendStartingPosition(slalom_spline_->starting_position());
if (!slalom_spline_->WaitForPlan()) return;
slalom_spline_->Start();
if (!slalom_spline_->WaitForSplineDistanceRemaining(0.02)) return;
}
void AutonomousActor::SplineAuto() {
CHECK(test_spline_);
SendStartingPosition(test_spline_->starting_position());
if (!test_spline_->WaitForPlan()) return;
test_spline_->Start();
if (!test_spline_->WaitForSplineDistanceRemaining(0.02)) return;
}
ProfileParametersT MakeProfileParametersT(const float max_velocity,
const float max_acceleration) {
ProfileParametersT params;
params.max_velocity = max_velocity;
params.max_acceleration = max_acceleration;
return params;
}
bool AutonomousActor::DriveFwd() {
SendStartingPosition({0, 0, 0});
const ProfileParametersT kDrive = MakeProfileParametersT(0.3f, 1.0f);
const ProfileParametersT kTurn = MakeProfileParametersT(5.0f, 15.0f);
StartDrive(1.0, 0.0, kDrive, kTurn);
return WaitForDriveDone();
}
void AutonomousActor::SendSuperstructureGoal() {
auto builder = superstructure_goal_sender_.MakeBuilder();
flatbuffers::Offset<StaticZeroingSingleDOFProfiledSubsystemGoal>
intake_offset;
{
StaticZeroingSingleDOFProfiledSubsystemGoal::Builder intake_builder =
builder.MakeBuilder<StaticZeroingSingleDOFProfiledSubsystemGoal>();
frc971::ProfileParameters::Builder profile_params_builder =
builder.MakeBuilder<frc971::ProfileParameters>();
profile_params_builder.add_max_velocity(20.0);
profile_params_builder.add_max_acceleration(60.0);
flatbuffers::Offset<frc971::ProfileParameters> profile_params_offset =
profile_params_builder.Finish();
intake_builder.add_unsafe_goal(intake_goal_);
intake_builder.add_profile_params(profile_params_offset);
intake_offset = intake_builder.Finish();
}
superstructure::Goal::Builder superstructure_builder =
builder.MakeBuilder<superstructure::Goal>();
superstructure_builder.add_intake(intake_offset);
superstructure_builder.add_roller_voltage(roller_voltage_);
superstructure_builder.add_roller_speed_compensation(kRollerSpeedCompensation);
if (!builder.Send(superstructure_builder.Finish())) {
AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
}
}
void AutonomousActor::RetractIntake() {
set_intake_goal(-0.89);
set_roller_voltage(0.0);
SendSuperstructureGoal();
}
} // namespace actors
} // namespace y2020