blob: 0c43d99afb629f17a6be1a575ab33fedee9782dd [file] [log] [blame]
#ifndef AOS_INPUT_DRIVETRAIN_INPUT_H_
#define AOS_INPUT_DRIVETRAIN_INPUT_H_
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <cmath>
#include <memory>
#include "aos/input/driver_station_data.h"
#include "aos/logging/logging.h"
#include "frc971/control_loops/control_loops_generated.h"
#include "frc971/control_loops/drivetrain/drivetrain_config.h"
#include "frc971/control_loops/drivetrain/drivetrain_goal_generated.h"
#include "frc971/control_loops/drivetrain/drivetrain_status_generated.h"
namespace aos {
namespace input {
// We have a couple different joystick configurations used to drive our skid
// steer robots. These configurations don't change very often, and there are a
// small, discrete, set of them. The interface to the drivetrain is the same
// across all of our drivetrains, so we can abstract that away from our users.
//
// We want to be able to re-use that code across years, and switch joystick
// types quickly and efficiently.
//
// DrivetrainInputReader is the abstract base class which provides a consistent
// API to control drivetrains.
//
// To construct the appropriate DrivetrainInputReader, call
// DrivetrainInputReader::Make with the input type enum.
// To use it, call HandleDrivetrain(data) every time a joystick packet is
// received.
//
// Base class for the interface to the drivetrain implemented by multiple
// joystick types.
class DrivetrainInputReader {
public:
// What to use the turn1/2 buttons for.
enum class TurnButtonUse {
// Use the button to enable control loop driving.
kControlLoopDriving,
// Use the button to set line following mode.
kLineFollow,
};
// Inputs driver station button and joystick locations
DrivetrainInputReader(::aos::EventLoop *event_loop,
driver_station::JoystickAxis wheel,
driver_station::JoystickAxis throttle,
driver_station::ButtonLocation quick_turn,
driver_station::ButtonLocation turn1,
TurnButtonUse turn1_use,
driver_station::ButtonLocation turn2,
TurnButtonUse turn2_use)
: wheel_(wheel),
throttle_(throttle),
quick_turn_(quick_turn),
turn1_(turn1),
turn1_use_(turn1_use),
turn2_(turn2),
turn2_use_(turn2_use),
drivetrain_status_fetcher_(
event_loop
->MakeFetcher<::frc971::control_loops::drivetrain::Status>(
"/drivetrain")),
drivetrain_goal_sender_(
event_loop->MakeSender<::frc971::control_loops::drivetrain::Goal>(
"/drivetrain")) {}
virtual ~DrivetrainInputReader() = default;
// List of driver joystick types.
enum class InputType {
kSteeringWheel,
kPistol,
kXbox,
};
// Constructs the appropriate DrivetrainInputReader.
static std::unique_ptr<DrivetrainInputReader> Make(
::aos::EventLoop *event_loop, InputType type,
const ::frc971::control_loops::drivetrain::DrivetrainConfig<double>
&dt_config);
// Processes new joystick data and publishes drivetrain goal messages.
void HandleDrivetrain(const ::aos::input::driver_station::Data &data);
// Sets the scalar for the steering wheel for closed loop mode converting
// steering ratio to meters displacement on the two wheels.
void set_wheel_multiplier(double wheel_multiplier) {
wheel_multiplier_ = wheel_multiplier;
}
// Returns the current robot velocity in m/s.
double robot_velocity() const { return robot_velocity_; }
void set_vision_align_fn(
::std::function<bool(const ::aos::input::driver_station::Data &data)>
vision_align_fn) {
vision_align_fn_ = vision_align_fn;
}
protected:
const driver_station::JoystickAxis wheel_;
const driver_station::JoystickAxis throttle_;
const driver_station::ButtonLocation quick_turn_;
// Button for enabling control loop driving.
const driver_station::ButtonLocation turn1_;
const TurnButtonUse turn1_use_;
// But for enabling line following.
const driver_station::ButtonLocation turn2_;
const TurnButtonUse turn2_use_;
bool last_is_control_loop_driving_ = false;
// Structure containing the (potentially adjusted) steering and throttle
// values from the joysticks.
struct WheelAndThrottle {
double wheel;
double wheel_velocity;
double wheel_torque;
double throttle;
double throttle_velocity;
double throttle_torque;
bool high_gear;
};
private:
// Computes the steering and throttle from the provided driverstation data.
virtual WheelAndThrottle GetWheelAndThrottle(
const ::aos::input::driver_station::Data &data) = 0;
::aos::Fetcher<::frc971::control_loops::drivetrain::Status>
drivetrain_status_fetcher_;
::aos::Sender<::frc971::control_loops::drivetrain::Goal>
drivetrain_goal_sender_;
double robot_velocity_ = 0.0;
// Goals to send to the drivetrain in closed loop mode.
double left_goal_ = 0.0;
double right_goal_ = 0.0;
// The scale for the joysticks for closed loop mode converting
// joysticks to meters displacement on the two wheels.
double wheel_multiplier_ = 0.5;
::std::function<bool(const ::aos::input::driver_station::Data &data)>
vision_align_fn_;
};
// Implements DrivetrainInputReader for the original steering wheel.
class SteeringWheelDrivetrainInputReader : public DrivetrainInputReader {
public:
using DrivetrainInputReader::DrivetrainInputReader;
// Creates a DrivetrainInputReader with the corresponding joystick ports and
// axis for the big steering wheel and throttle stick.
static std::unique_ptr<SteeringWheelDrivetrainInputReader> Make(
::aos::EventLoop *event_loop, bool default_high_gear);
// Sets the default shifter position
void set_default_high_gear(bool default_high_gear) {
high_gear_ = default_high_gear;
default_high_gear_ = default_high_gear;
}
private:
WheelAndThrottle GetWheelAndThrottle(
const ::aos::input::driver_station::Data &data) override;
bool high_gear_;
bool default_high_gear_;
};
class PistolDrivetrainInputReader : public DrivetrainInputReader {
public:
using DrivetrainInputReader::DrivetrainInputReader;
// What to use the top two buttons for on the pistol grip.
enum class TopButtonUse {
// Normal shifting.
kShift,
// Line following (currently just uses top button).
kLineFollow,
};
// Creates a DrivetrainInputReader with the corresponding joystick ports and
// axis for the (cheap) pistol grip controller.
static std::unique_ptr<PistolDrivetrainInputReader> Make(
::aos::EventLoop *event_loop, bool default_high_gear,
TopButtonUse top_button_use);
private:
PistolDrivetrainInputReader(
::aos::EventLoop *event_loop, driver_station::JoystickAxis wheel_high,
driver_station::JoystickAxis wheel_low,
driver_station::JoystickAxis wheel_velocity_high,
driver_station::JoystickAxis wheel_velocity_low,
driver_station::JoystickAxis wheel_torque_high,
driver_station::JoystickAxis wheel_torque_low,
driver_station::JoystickAxis throttle_high,
driver_station::JoystickAxis throttle_low,
driver_station::JoystickAxis throttle_velocity_high,
driver_station::JoystickAxis throttle_velocity_low,
driver_station::JoystickAxis throttle_torque_high,
driver_station::JoystickAxis throttle_torque_low,
driver_station::ButtonLocation quick_turn,
driver_station::ButtonLocation shift_high,
driver_station::ButtonLocation shift_low,
driver_station::ButtonLocation turn1,
driver_station::ButtonLocation turn2,
driver_station::ButtonLocation slow_down)
: DrivetrainInputReader(event_loop, wheel_high, throttle_high, quick_turn,
turn1, TurnButtonUse::kLineFollow, turn2,
TurnButtonUse::kControlLoopDriving),
wheel_low_(wheel_low),
wheel_velocity_high_(wheel_velocity_high),
wheel_velocity_low_(wheel_velocity_low),
wheel_torque_high_(wheel_torque_high),
wheel_torque_low_(wheel_torque_low),
throttle_low_(throttle_low),
throttle_velocity_high_(throttle_velocity_high),
throttle_velocity_low_(throttle_velocity_low),
throttle_torque_high_(throttle_torque_high),
throttle_torque_low_(throttle_torque_low),
shift_high_(shift_high),
shift_low_(shift_low),
slow_down_(slow_down) {}
WheelAndThrottle GetWheelAndThrottle(
const ::aos::input::driver_station::Data &data) override;
// Sets the default shifter position
void set_default_high_gear(bool default_high_gear) {
high_gear_ = default_high_gear;
default_high_gear_ = default_high_gear;
}
const driver_station::JoystickAxis wheel_low_;
const driver_station::JoystickAxis wheel_velocity_high_;
const driver_station::JoystickAxis wheel_velocity_low_;
const driver_station::JoystickAxis wheel_torque_high_;
const driver_station::JoystickAxis wheel_torque_low_;
const driver_station::JoystickAxis throttle_low_;
const driver_station::JoystickAxis throttle_velocity_high_;
const driver_station::JoystickAxis throttle_velocity_low_;
const driver_station::JoystickAxis throttle_torque_high_;
const driver_station::JoystickAxis throttle_torque_low_;
const driver_station::ButtonLocation shift_high_;
const driver_station::ButtonLocation shift_low_;
const driver_station::ButtonLocation slow_down_;
bool high_gear_;
bool default_high_gear_;
};
class XboxDrivetrainInputReader : public DrivetrainInputReader {
public:
using DrivetrainInputReader::DrivetrainInputReader;
// Creates a DrivetrainInputReader with the corresponding joystick ports and
// axis for the Xbox controller.
static std::unique_ptr<XboxDrivetrainInputReader> Make(
::aos::EventLoop *event_loop);
private:
WheelAndThrottle GetWheelAndThrottle(
const ::aos::input::driver_station::Data &data) override;
};
} // namespace input
} // namespace aos
#endif // AOS_INPUT_DRIVETRAIN_INPUT_H_