blob: 78f81c7c9f0ab90dee055226d027b8d06c1e8760 [file] [log] [blame] [edit]
#include <unistd.h>
#include <cmath>
#include <cstdio>
#include <cstring>
#include "aos/actions/actions.h"
#include "aos/init.h"
#include "aos/logging/logging.h"
#include "aos/time/time.h"
#include "aos/util/log_interval.h"
#include "frc971/autonomous/base_autonomous_actor.h"
#include "frc971/input/action_joystick_input.h"
#include "frc971/input/driver_station_data.h"
#include "frc971/input/drivetrain_input.h"
#include "y2017/constants.h"
#include "y2017/control_loops/drivetrain/drivetrain_base.h"
#include "y2017/control_loops/superstructure/superstructure_goal_generated.h"
#include "y2017/control_loops/superstructure/superstructure_status_generated.h"
using ::frc971::input::DrivetrainInputReader;
using ::frc971::input::driver_station::ButtonLocation;
using ::frc971::input::driver_station::ControlBit;
using ::frc971::input::driver_station::JoystickAxis;
using ::frc971::input::driver_station::POVLocation;
namespace y2017::input::joysticks {
namespace superstructure = control_loops::superstructure;
const ButtonLocation kGearSlotBack(2, 11);
const ButtonLocation kIntakeDown(3, 9);
const POVLocation kIntakeUp(3, 90);
const ButtonLocation kIntakeIn(3, 12);
const ButtonLocation kIntakeOut(3, 8);
const ButtonLocation kFire(3, 3);
const ButtonLocation kVisionDistanceShot(3, 7);
const ButtonLocation kMiddleShot(3, 6);
const POVLocation kFarShot(3, 270);
const ButtonLocation kVisionAlign(3, 5);
const ButtonLocation kReverseIndexer(3, 4);
const ButtonLocation kExtra1(3, 11);
const ButtonLocation kExtra2(3, 10);
const ButtonLocation kHang(3, 2);
class Reader : public ::frc971::input::ActionJoystickInput {
public:
Reader(::aos::EventLoop *event_loop)
: ::frc971::input::ActionJoystickInput(
event_loop,
::y2017::control_loops::drivetrain::GetDrivetrainConfig(),
DrivetrainInputReader::InputType::kSteeringWheel, {}),
superstructure_status_fetcher_(
event_loop
->MakeFetcher<::y2017::control_loops::superstructure::Status>(
"/superstructure")),
superstructure_goal_sender_(
event_loop
->MakeSender<::y2017::control_loops::superstructure::Goal>(
"/superstructure")) {}
enum class ShotDistance { VISION_SHOT, MIDDLE_SHOT, FAR_SHOT };
void HandleTeleop(const ::frc971::input::driver_station::Data &data) {
// Default the intake to in.
intake_goal_ = 0.07;
bool lights_on = false;
bool vision_track = false;
superstructure_status_fetcher_.Fetch();
if (!superstructure_status_fetcher_.get()) {
AOS_LOG(ERROR, "Got no superstructure status packet.\n");
return;
}
if (data.IsPressed(kIntakeUp)) {
intake_goal_ = 0.0;
turret_goal_ = M_PI / 3.0;
}
if (data.IsPressed(kIntakeDown)) {
intake_goal_ = 0.235;
// Don't go quite so far out since we have a gear mech out now.
if (data.IsPressed(kIntakeUp)) {
intake_goal_ = 0.160;
}
}
if (data.IsPressed(kVisionAlign)) {
// Align shot using vision
// TODO(campbell): Add vision aligning.
lights_on = true;
vision_track = true;
}
if (data.PosEdge(kMiddleShot)) {
turret_goal_ = -M_PI;
}
if (data.PosEdge(kFarShot)) {
turret_goal_ = 0.0;
}
if (data.PosEdge(kVisionDistanceShot)) {
turret_goal_ = 0.0;
}
if (data.IsPressed(kVisionDistanceShot)) {
last_shot_distance_ = ShotDistance::VISION_SHOT;
} else if (data.IsPressed(kMiddleShot)) {
last_shot_distance_ = ShotDistance::MIDDLE_SHOT;
} else if (data.IsPressed(kFarShot)) {
last_shot_distance_ = ShotDistance::FAR_SHOT;
}
if (data.IsPressed(kVisionAlign) || data.IsPressed(kMiddleShot) ||
data.IsPressed(kFarShot) || data.IsPressed(kFire)) {
switch (last_shot_distance_) {
case ShotDistance::VISION_SHOT:
hood_goal_ = 0.10;
shooter_velocity_ = 300.0;
vision_distance_shot_ = true;
break;
case ShotDistance::MIDDLE_SHOT:
hood_goal_ = 0.43 - 0.00;
shooter_velocity_ = 364.0;
vision_distance_shot_ = false;
break;
case ShotDistance::FAR_SHOT:
hood_goal_ = 0.47;
shooter_velocity_ = 410.0;
vision_distance_shot_ = false;
break;
}
} else {
// hood_goal_ = 0.15;
shooter_velocity_ = 0.0;
}
if (data.IsPressed(kExtra1)) {
// turret_goal_ = -M_PI * 3.0 / 4.0;
turret_goal_ += 0.150;
}
if (data.IsPressed(kExtra2)) {
// turret_goal_ = M_PI * 3.0 / 4.0;
turret_goal_ -= 0.150;
}
turret_goal_ = ::std::max(::std::min(turret_goal_, M_PI), -M_PI);
fire_ = data.IsPressed(kFire) && shooter_velocity_ != 0.0;
if (data.IsPressed(kVisionAlign)) {
fire_ =
fire_ && superstructure_status_fetcher_->turret()->vision_tracking();
}
auto builder = superstructure_goal_sender_.MakeBuilder();
if (data.IsPressed(kHang)) {
intake_goal_ = 0.23;
}
bool intake_disable_intake = false;
double intake_gear_servo = 0.0;
if (data.IsPressed(kIntakeUp)) {
intake_gear_servo = 0.30;
} else {
// Clamp the gear
intake_gear_servo = 0.66;
}
double intake_voltage_rollers = 0.0;
if (superstructure_status_fetcher_->intake()->position() >
superstructure_status_fetcher_->intake()->unprofiled_goal_position() +
0.01) {
intake_accumulator_ = 10;
}
if (intake_accumulator_ > 0) {
--intake_accumulator_;
if (!superstructure_status_fetcher_->intake()->estopped()) {
intake_voltage_rollers = 10.0;
}
}
if (data.IsPressed(kHang)) {
intake_voltage_rollers = -10.0;
intake_disable_intake = true;
} else if (data.IsPressed(kIntakeIn) || data.IsPressed(kFire)) {
if (robot_velocity() > 2.0) {
intake_voltage_rollers = 12.0;
} else {
intake_voltage_rollers = 11.0;
}
} else if (data.IsPressed(kIntakeOut)) {
intake_voltage_rollers = -8.0;
}
if (intake_goal_ < 0.1) {
intake_voltage_rollers = ::std::min(8.0, intake_voltage_rollers);
}
double indexer_voltage_rollers = 0.0;
double indexer_angular_velocity = 0.0;
if (data.IsPressed(kReverseIndexer)) {
indexer_voltage_rollers = -12.0;
indexer_angular_velocity = 1.0;
} else if (fire_) {
indexer_voltage_rollers = 12.0;
switch (last_shot_distance_) {
case ShotDistance::VISION_SHOT:
indexer_angular_velocity = -1.25 * M_PI;
break;
case ShotDistance::MIDDLE_SHOT:
case ShotDistance::FAR_SHOT:
indexer_angular_velocity = -2.25 * M_PI;
break;
}
} else {
indexer_voltage_rollers = 0.0;
indexer_angular_velocity = 0.0;
}
superstructure::IndexerGoal::Builder indexer_goal_builder =
builder.MakeBuilder<superstructure::IndexerGoal>();
indexer_goal_builder.add_angular_velocity(indexer_angular_velocity);
indexer_goal_builder.add_voltage_rollers(indexer_voltage_rollers);
flatbuffers::Offset<superstructure::IndexerGoal> indexer_goal_offset =
indexer_goal_builder.Finish();
flatbuffers::Offset<frc971::ProfileParameters>
turret_profile_parameters_offset;
if (vision_track) {
turret_profile_parameters_offset =
frc971::CreateProfileParameters(*builder.fbb(), 10.0, 35.0);
} else {
turret_profile_parameters_offset =
frc971::CreateProfileParameters(*builder.fbb(), 6.0, 15.0);
}
superstructure::TurretGoal::Builder turret_goal_builder =
builder.MakeBuilder<superstructure::TurretGoal>();
turret_goal_builder.add_angle(turret_goal_);
turret_goal_builder.add_track(vision_track);
turret_goal_builder.add_profile_params(turret_profile_parameters_offset);
flatbuffers::Offset<superstructure::TurretGoal> turret_goal_offset =
turret_goal_builder.Finish();
flatbuffers::Offset<frc971::ProfileParameters>
intake_profile_parameters_offset =
frc971::CreateProfileParameters(*builder.fbb(), 0.5, 3.0);
superstructure::IntakeGoal::Builder intake_goal_builder =
builder.MakeBuilder<superstructure::IntakeGoal>();
intake_goal_builder.add_voltage_rollers(intake_voltage_rollers);
intake_goal_builder.add_distance(intake_goal_);
intake_goal_builder.add_disable_intake(intake_disable_intake);
intake_goal_builder.add_gear_servo(intake_gear_servo);
intake_goal_builder.add_profile_params(intake_profile_parameters_offset);
flatbuffers::Offset<superstructure::IntakeGoal> intake_goal_offset =
intake_goal_builder.Finish();
flatbuffers::Offset<frc971::ProfileParameters>
hood_profile_parameters_offset =
frc971::CreateProfileParameters(*builder.fbb(), 5.0, 25.0);
superstructure::HoodGoal::Builder hood_goal_builder =
builder.MakeBuilder<superstructure::HoodGoal>();
hood_goal_builder.add_angle(hood_goal_);
hood_goal_builder.add_profile_params(hood_profile_parameters_offset);
flatbuffers::Offset<superstructure::HoodGoal> hood_goal_offset =
hood_goal_builder.Finish();
superstructure::ShooterGoal::Builder shooter_goal_builder =
builder.MakeBuilder<superstructure::ShooterGoal>();
shooter_goal_builder.add_angular_velocity(shooter_velocity_);
flatbuffers::Offset<superstructure::ShooterGoal> shooter_goal_offset =
shooter_goal_builder.Finish();
superstructure::Goal::Builder goal_builder =
builder.MakeBuilder<superstructure::Goal>();
goal_builder.add_lights_on(lights_on);
if (data.IsPressed(kVisionAlign) && vision_distance_shot_) {
goal_builder.add_use_vision_for_shots(true);
} else {
goal_builder.add_use_vision_for_shots(false);
}
goal_builder.add_intake(intake_goal_offset);
goal_builder.add_indexer(indexer_goal_offset);
goal_builder.add_turret(turret_goal_offset);
goal_builder.add_hood(hood_goal_offset);
goal_builder.add_shooter(shooter_goal_offset);
if (builder.Send(goal_builder.Finish()) != aos::RawSender::Error::kOk) {
AOS_LOG(ERROR, "Sending superstructure goal failed.\n");
}
}
private:
::aos::Fetcher<::y2017::control_loops::superstructure::Status>
superstructure_status_fetcher_;
::aos::Sender<::y2017::control_loops::superstructure::Goal>
superstructure_goal_sender_;
ShotDistance last_shot_distance_ = ShotDistance::VISION_SHOT;
// Current goals to send to the robot.
double intake_goal_ = 0.0;
double turret_goal_ = 0.0;
double hood_goal_ = 0.3;
double shooter_velocity_ = 0.0;
int intake_accumulator_ = 0;
bool vision_distance_shot_ = false;
bool fire_ = false;
};
} // namespace y2017::input::joysticks
int main(int argc, char **argv) {
::aos::InitGoogle(&argc, &argv);
aos::FlatbufferDetachedBuffer<aos::Configuration> config =
aos::configuration::ReadConfig("aos_config.json");
::aos::ShmEventLoop event_loop(&config.message());
::y2017::input::joysticks::Reader reader(&event_loop);
event_loop.Run();
return 0;
}