blob: ab9ffa5cc7d22b119a28915a26021228d1876249 [file] [log] [blame]
#include <stdio.h>
#include <memory>
#include "aos/common/util/phased_loop.h"
#include "aos/common/time.h"
#include "aos/common/util/trapezoid_profile.h"
#include "aos/common/logging/logging.h"
#include "bot3/actions/drivetrain_action.h"
#include "bot3/control_loops/drivetrain/drivetrain.q.h"
#include "bot3/control_loops/drivetrain/drivetrain_constants.h"
#include "bot3/control_loops/rollers/rollers.q.h"
#include "frc971/actions/action_client.h"
#include "frc971/actions/drivetrain_action.q.h"
#include "frc971/autonomous/auto.q.h"
#include "frc971/queues/other_sensors.q.h"
using ::aos::time::Time;
namespace bot3 {
namespace autonomous {
namespace time = ::aos::time;
static double left_initial_position, right_initial_position;
bool ShouldExitAuto() {
::frc971::autonomous::autonomous.FetchLatest();
bool ans = !::frc971::autonomous::autonomous->run_auto;
if (ans) {
LOG(INFO, "Time to exit auto mode\n");
}
return ans;
}
void StopDrivetrain() {
LOG(INFO, "Stopping the drivetrain\n");
control_loops::drivetrain.goal.MakeWithBuilder()
.control_loop_driving(true)
.left_goal(left_initial_position)
.left_velocity_goal(0)
.right_goal(right_initial_position)
.right_velocity_goal(0)
.quickturn(false)
.Send();
}
void ResetDrivetrain() {
LOG(INFO, "resetting the drivetrain\n");
control_loops::drivetrain.goal.MakeWithBuilder()
.control_loop_driving(false)
.highgear(false)
.steering(0.0)
.throttle(0.0)
.left_goal(left_initial_position)
.left_velocity_goal(0)
.right_goal(right_initial_position)
.right_velocity_goal(0)
.Send();
}
void WaitUntilDoneOrCanceled(::frc971::Action *action) {
while (true) {
// Poll the running bit and auto done bits.
::aos::time::PhasedLoop10MS(5000);
if (!action->Running() || ShouldExitAuto()) {
return;
}
}
}
::std::unique_ptr<::frc971::TypedAction
< ::frc971::actions::DrivetrainActionQueueGroup>>
SetDriveGoal(double distance, bool slow_acceleration,
double maximum_velocity = 1.7, double theta = 0) {
LOG(INFO, "Driving to %f\n", distance);
auto drivetrain_action = actions::MakeDrivetrainAction();
drivetrain_action->GetGoal()->left_initial_position = left_initial_position;
drivetrain_action->GetGoal()->right_initial_position = right_initial_position;
drivetrain_action->GetGoal()->y_offset = distance;
drivetrain_action->GetGoal()->theta_offset = theta;
drivetrain_action->GetGoal()->maximum_velocity = maximum_velocity;
drivetrain_action->GetGoal()->maximum_acceleration =
slow_acceleration ? 2.5 : 3.0;
drivetrain_action->Start();
left_initial_position +=
distance - theta * control_loops::kBot3TurnWidth / 2.0;
right_initial_position +=
distance + theta * control_loops::kBot3TurnWidth / 2.0;
return ::std::move(drivetrain_action);
}
void InitializeEncoders() {
control_loops::drivetrain.status.FetchLatest();
while (!control_loops::drivetrain.status.get()) {
LOG(WARNING,
"No previous drivetrain position packet, trying to fetch again\n");
control_loops::drivetrain.status.FetchNextBlocking();
}
left_initial_position =
control_loops::drivetrain.status->filtered_left_position;
right_initial_position =
control_loops::drivetrain.status->filtered_right_position;
}
void StopRollers() {
control_loops::rollers.goal.MakeWithBuilder()
.intake(0)
.low_spit(0)
.human_player(false)
.Send();
}
void SpitBallFront() {
control_loops::rollers.goal.MakeWithBuilder()
.intake(0)
.low_spit(1)
.human_player(false)
.Send();
time::SleepFor(time::Time::InSeconds(1));
StopRollers();
}
void IntakeBallBack() {
control_loops::rollers.goal.MakeWithBuilder()
.intake(-1)
.low_spit(0)
.human_player(false)
.Send();
time::SleepFor(time::Time::InSeconds(1.5));
StopRollers();
}
void ScoreBall(const double distance, const double velocity) {
// Drive to the goal, score, and drive back.
{
// Drive forward.
auto drivetrain_action = SetDriveGoal(distance,
false, velocity);
LOG(INFO, "Waiting until drivetrain is finished.\n");
WaitUntilDoneOrCanceled(drivetrain_action.get());
time::SleepFor(time::Time::InSeconds(0.5));
if (ShouldExitAuto()) return;
}
{
LOG(INFO, "Spitting ball.\n");
SpitBallFront();
time::SleepFor(time::Time::InSeconds(0.5));
if (ShouldExitAuto()) return;
}
{
// Drive back.
LOG(INFO, "Driving back.\n");
auto drivetrain_action = SetDriveGoal(-distance,
false, velocity);
LOG(INFO, "Waiting until drivetrain is finished.\n");
WaitUntilDoneOrCanceled(drivetrain_action.get());
if (ShouldExitAuto()) return;
}
}
void HandleAuto() {
constexpr double kDriveDistance = 4.86;
constexpr double kAutoVelocity = 2.5;
if (ShouldExitAuto()) return;
ResetDrivetrain();
InitializeEncoders();
if (ShouldExitAuto()) return;
ScoreBall(kDriveDistance, kAutoVelocity);
}
} // namespace autonomous
} // namespace bot3