Update 2020 wpilib_interface.
Also remove an unused output field.
Change-Id: I9721fe923104b48984ab5895e28ef111c810d611
diff --git a/y2020/wpilib_interface.cc b/y2020/wpilib_interface.cc
index 3276722..ab8b967 100644
--- a/y2020/wpilib_interface.cc
+++ b/y2020/wpilib_interface.cc
@@ -15,6 +15,7 @@
#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
#include "frc971/wpilib/ahal/DriverStation.h"
#include "frc971/wpilib/ahal/Encoder.h"
+#include "frc971/wpilib/ahal/TalonFX.h"
#include "frc971/wpilib/ahal/VictorSP.h"
#undef ERROR
@@ -30,6 +31,7 @@
#include "aos/util/log_interval.h"
#include "aos/util/phased_loop.h"
#include "aos/util/wrapping_counter.h"
+#include "ctre/phoenix/motorcontrol/can/TalonFX.h"
#include "frc971/autonomous/auto_mode_generated.h"
#include "frc971/control_loops/drivetrain/drivetrain_position_generated.h"
#include "frc971/wpilib/ADIS16470.h"
@@ -91,11 +93,18 @@
control_loops::drivetrain::kWheelRadius;
}
+double turret_pot_translate(double voltage) {
+ return voltage * Values::kTurretPotRatio() *
+ (10.0 /*turns*/ / 5.0 /*volts*/) * (2 * M_PI /*radians*/);
+}
+
+// TODO(Ravago): check with constants which are fast.
constexpr double kMaxFastEncoderPulsesPerSecond =
Values::kMaxDrivetrainEncoderPulsesPerSecond();
static_assert(kMaxFastEncoderPulsesPerSecond <= 1300000,
"fast encoders are too fast");
-constexpr double kMaxMediumEncoderPulsesPerSecond = kMaxFastEncoderPulsesPerSecond;
+constexpr double kMaxMediumEncoderPulsesPerSecond =
+ kMaxFastEncoderPulsesPerSecond;
static_assert(kMaxMediumEncoderPulsesPerSecond <= 400000,
"medium encoders are too fast");
@@ -123,6 +132,71 @@
UpdateMediumEncoderFilterHz(kMaxMediumEncoderPulsesPerSecond);
}
+ // Hood
+
+ void set_hood_encoder(::std::unique_ptr<frc::Encoder> encoder) {
+ medium_encoder_filter_.Add(encoder.get());
+ hood_encoder_.set_encoder(::std::move(encoder));
+ }
+
+ void set_hood_absolute_pwm(
+ ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
+ hood_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
+ }
+
+ // Intake
+
+ void set_intake_encoder(::std::unique_ptr<frc::Encoder> encoder) {
+ medium_encoder_filter_.Add(encoder.get());
+ intake_joint_encoder_.set_encoder(::std::move(encoder));
+ }
+
+ void set_intake_absolute_pwm(
+ ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
+ intake_joint_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
+ }
+
+ // Turret
+
+ void set_turret_encoder(::std::unique_ptr<frc::Encoder> encoder) {
+ medium_encoder_filter_.Add(encoder.get());
+ turret_encoder_.set_encoder(::std::move(encoder));
+ }
+
+ void set_turret_absolute_pwm(
+ ::std::unique_ptr<frc::DigitalInput> absolute_pwm) {
+ turret_encoder_.set_absolute_pwm(::std::move(absolute_pwm));
+ }
+
+ void set_turret_potentiometer(
+ ::std::unique_ptr<frc::AnalogInput> potentiometer) {
+ turret_encoder_.set_potentiometer(::std::move(potentiometer));
+ }
+
+ // Shooter
+
+ void set_flywheel_encoder(::std::unique_ptr<frc::Encoder> encoder) {
+ fast_encoder_filter_.Add(encoder.get());
+ flywheel_encoder_ = ::std::move(encoder);
+ }
+
+ void set_left_kicker_encoder(::std::unique_ptr<frc::Encoder> encoder) {
+ fast_encoder_filter_.Add(encoder.get());
+ left_kicker_encoder_ = ::std::move(encoder);
+ }
+
+ void set_right_kicker_encoder(::std::unique_ptr<frc::Encoder> encoder) {
+ fast_encoder_filter_.Add(encoder.get());
+ right_kicker_encoder_ = ::std::move(encoder);
+ }
+
+ // Control Panel
+
+ void set_control_panel_encoder(::std::unique_ptr<frc::Encoder> encoder) {
+ medium_encoder_filter_.Add(encoder.get());
+ control_panel_encoder_ = ::std::move(encoder);
+ }
+
// Auto mode switches.
void set_autonomous_mode(int i, ::std::unique_ptr<frc::DigitalInput> sensor) {
autonomous_modes_.at(i) = ::std::move(sensor);
@@ -149,11 +223,72 @@
builder.Send(drivetrain_builder.Finish());
}
+ const auto values = constants::GetValues();
{
auto builder = superstructure_position_sender_.MakeBuilder();
superstructure::Position::Builder position_builder =
builder.MakeBuilder<superstructure::Position>();
+ // TODO(alex): check new absolute encoder api.
+ // Hood
+ frc971::AbsolutePositionT hood;
+ CopyPosition(hood_encoder_, &hood,
+ Values::kHoodEncoderCountsPerRevolution(),
+ Values::kHoodEncoderRatio(), false);
+ flatbuffers::Offset<frc971::AbsolutePosition> hood_offset =
+ frc971::AbsolutePosition::Pack(*builder.fbb(), &hood);
+
+ // Intake
+ frc971::AbsolutePositionT intake_joint;
+ CopyPosition(intake_joint_encoder_, &intake_joint,
+ Values::kIntakeEncoderCountsPerRevolution(),
+ Values::kIntakeEncoderRatio(), false);
+ flatbuffers::Offset<frc971::AbsolutePosition> intake_joint_offset =
+ frc971::AbsolutePosition::Pack(*builder.fbb(), &intake_joint);
+
+ // Turret
+ frc971::PotAndAbsolutePositionT turret;
+ CopyPosition(turret_encoder_, &turret,
+ Values::kTurretEncoderCountsPerRevolution(),
+ Values::kTurretEncoderRatio(), turret_pot_translate, false,
+ values.turret.potentiometer_offset);
+ flatbuffers::Offset<frc971::PotAndAbsolutePosition> turret_offset =
+ frc971::PotAndAbsolutePosition::Pack(*builder.fbb(), &turret);
+
+ // Shooter
+ y2020::control_loops::superstructure::ShooterPositionT shooter;
+ shooter.theta_finisher =
+ encoder_translate(flywheel_encoder_->GetRaw(),
+ Values::kFinisherEncoderCountsPerRevolution(),
+ Values::kFinisherEncoderRatio());
+ // TODO; check sign
+ shooter.theta_accelerator_left =
+ encoder_translate(left_kicker_encoder_->GetRaw(),
+ Values::kAcceleratorEncoderCountsPerRevolution(),
+ Values::kAcceleratorEncoderRatio());
+ shooter.theta_accelerator_right =
+ encoder_translate(right_kicker_encoder_->GetRaw(),
+ Values::kAcceleratorEncoderCountsPerRevolution(),
+ Values::kAcceleratorEncoderRatio());
+ flatbuffers::Offset<y2020::control_loops::superstructure::ShooterPosition>
+ shooter_offset =
+ y2020::control_loops::superstructure::ShooterPosition::Pack(
+ *builder.fbb(), &shooter);
+
+ // Control Panel
+ frc971::RelativePositionT control_panel;
+ CopyPosition(*control_panel_encoder_, &control_panel,
+ Values::kControlPanelEncoderCountsPerRevolution(),
+ Values::kControlPanelEncoderRatio(), false);
+ flatbuffers::Offset<frc971::RelativePosition> control_panel_offset =
+ frc971::RelativePosition::Pack(*builder.fbb(), &control_panel);
+
+ position_builder.add_hood(hood_offset);
+ position_builder.add_intake_joint(intake_joint_offset);
+ position_builder.add_turret(turret_offset);
+ position_builder.add_shooter(shooter_offset);
+ position_builder.add_control_panel(control_panel_offset);
+
builder.Send(position_builder.Finish());
}
@@ -182,6 +317,13 @@
::aos::Sender<::frc971::control_loops::drivetrain::Position>
drivetrain_position_sender_;
+ ::frc971::wpilib::AbsoluteEncoderAndPotentiometer turret_encoder_;
+
+ ::frc971::wpilib::AbsoluteEncoder hood_encoder_, intake_joint_encoder_;
+
+ ::std::unique_ptr<::frc::Encoder> flywheel_encoder_, left_kicker_encoder_,
+ right_kicker_encoder_, control_panel_encoder_;
+
::std::array<::std::unique_ptr<frc::DigitalInput>, 2> autonomous_modes_;
frc971::wpilib::ADIS16470 *imu_ = nullptr;
@@ -194,17 +336,138 @@
: ::frc971::wpilib::LoopOutputHandler<superstructure::Output>(
event_loop, "/superstructure") {}
- private:
- void Write(const superstructure::Output & /*output*/) override {}
+ void set_hood_victor(::std::unique_ptr<::frc::VictorSP> t) {
+ hood_victor_ = ::std::move(t);
+ }
- void Stop() override { AOS_LOG(WARNING, "Superstructure output too old.\n"); }
+ void set_intake_joint_victor(::std::unique_ptr<::frc::VictorSP> t) {
+ intake_joint_victor_ = ::std::move(t);
+ }
+
+ void set_intake_roller_falcon(
+ ::std::unique_ptr<::ctre::phoenix::motorcontrol::can::TalonFX> t) {
+ intake_roller_falcon_ = ::std::move(t);
+ intake_roller_falcon_->ConfigSupplyCurrentLimit(
+ {true, Values::kIntakeRollerSupplyCurrentLimit(),
+ Values::kIntakeRollerSupplyCurrentLimit(), 0});
+ intake_roller_falcon_->ConfigStatorCurrentLimit(
+ {true, Values::kIntakeRollerStatorCurrentLimit(),
+ Values::kIntakeRollerStatorCurrentLimit(), 0});
+ }
+
+ void set_turret_victor(::std::unique_ptr<::frc::VictorSP> t) {
+ turret_victor_ = ::std::move(t);
+ }
+
+ void set_feeder_falcon(::std::unique_ptr<::frc::TalonFX> t) {
+ feeder_falcon_ = ::std::move(t);
+ }
+
+ void set_washing_machine_control_panel_victor(
+ ::std::unique_ptr<::frc::VictorSP> t) {
+ washing_machine_control_panel_victor_ = ::std::move(t);
+ }
+
+ void set_kicker_left_falcon(::std::unique_ptr<::frc::TalonFX> t) {
+ kicker_left_falcon_ = ::std::move(t);
+ }
+
+ void set_kicker_right_falcon(::std::unique_ptr<::frc::TalonFX> t) {
+ kicker_right_falcon_ = ::std::move(t);
+ }
+
+ void set_flywheel_falcon(::std::unique_ptr<::frc::TalonFX> t) {
+ flywheel_falcon_ = ::std::move(t);
+ }
+
+ void set_climber_falcon(
+ ::std::unique_ptr<::ctre::phoenix::motorcontrol::can::TalonFX> t) {
+ climber_falcon_ = ::std::move(t);
+ climber_falcon_->ConfigSupplyCurrentLimit(
+ {true, Values::kClimberSupplyCurrentLimit(),
+ Values::kClimberSupplyCurrentLimit(), 0});
+ }
+
+ private:
+ void Write(const superstructure::Output &output) override {
+ hood_victor_->SetSpeed(std::clamp(output.hood_voltage(), -kMaxBringupPower,
+ kMaxBringupPower) /
+ 12.0);
+
+ intake_joint_victor_->SetSpeed(std::clamp(output.intake_joint_voltage(),
+ -kMaxBringupPower,
+ kMaxBringupPower) /
+ 12.0);
+
+ intake_roller_falcon_->Set(
+ ctre::phoenix::motorcontrol::ControlMode::PercentOutput,
+ std::clamp(output.intake_roller_voltage(), -kMaxBringupPower,
+ kMaxBringupPower) /
+ 12.0);
+
+ turret_victor_->SetSpeed(std::clamp(output.turret_voltage(),
+ -kMaxBringupPower, kMaxBringupPower) /
+ 12.0);
+
+ feeder_falcon_->SetSpeed(std::clamp(output.feeder_voltage(),
+ -kMaxBringupPower, kMaxBringupPower) /
+ 12.0);
+
+ washing_machine_control_panel_victor_->SetSpeed(
+ std::clamp(output.washing_machine_spinner_voltage(), -kMaxBringupPower,
+ kMaxBringupPower) /
+ 12.0);
+
+ kicker_left_falcon_->SetSpeed(std::clamp(output.accelerator_left_voltage(),
+ -kMaxBringupPower,
+ kMaxBringupPower) /
+ 12.0);
+
+ kicker_right_falcon_->SetSpeed(
+ std::clamp(output.accelerator_right_voltage(), -kMaxBringupPower,
+ kMaxBringupPower) /
+ 12.0);
+
+ flywheel_falcon_->SetSpeed(std::clamp(output.finisher_voltage(),
+ -kMaxBringupPower,
+ kMaxBringupPower) /
+ 12.0);
+
+ climber_falcon_->Set(
+ ctre::phoenix::motorcontrol::ControlMode::PercentOutput,
+ std::clamp(output.climber_voltage(), -kMaxBringupPower,
+ kMaxBringupPower) /
+ 12.0);
+ }
+
+ void Stop() override {
+ AOS_LOG(WARNING, "Superstructure output too old.\n");
+ hood_victor_->SetDisabled();
+ intake_joint_victor_->SetDisabled();
+ turret_victor_->SetDisabled();
+ feeder_falcon_->SetDisabled();
+ washing_machine_control_panel_victor_->SetDisabled();
+ kicker_left_falcon_->SetDisabled();
+ kicker_right_falcon_->SetDisabled();
+ flywheel_falcon_->SetDisabled();
+ }
+
+ ::std::unique_ptr<::frc::VictorSP> hood_victor_, intake_joint_victor_,
+ turret_victor_, washing_machine_control_panel_victor_;
+
+ ::std::unique_ptr<::frc::TalonFX> feeder_falcon_, kicker_left_falcon_,
+ kicker_right_falcon_, flywheel_falcon_;
+
+ ::std::unique_ptr<::ctre::phoenix::motorcontrol::can::TalonFX>
+ intake_roller_falcon_, climber_falcon_;
};
class WPILibRobot : public ::frc971::wpilib::WPILibRobotBase {
public:
- ::std::unique_ptr<frc::Encoder> make_encoder(int index) {
+ ::std::unique_ptr<frc::Encoder> make_encoder(
+ int index, frc::Encoder::EncodingType encodingType = frc::Encoder::k4X) {
return make_unique<frc::Encoder>(10 + index * 2, 11 + index * 2, false,
- frc::Encoder::k4X);
+ encodingType);
}
void Run() override {
@@ -228,6 +491,23 @@
sensor_reader.set_drivetrain_left_encoder(make_encoder(0));
sensor_reader.set_drivetrain_right_encoder(make_encoder(1));
+ // TODO: pin numbers
+ sensor_reader.set_hood_encoder(make_encoder(2));
+ sensor_reader.set_hood_absolute_pwm(make_unique<frc::DigitalInput>(2));
+
+ sensor_reader.set_intake_encoder(make_encoder(3));
+ sensor_reader.set_intake_absolute_pwm(make_unique<frc::DigitalInput>(3));
+
+ sensor_reader.set_turret_encoder(make_encoder(4));
+ sensor_reader.set_turret_absolute_pwm(make_unique<frc::DigitalInput>(4));
+ sensor_reader.set_turret_potentiometer(make_unique<frc::AnalogInput>(4));
+
+ sensor_reader.set_flywheel_encoder(make_encoder(5));
+ sensor_reader.set_left_kicker_encoder(make_encoder(6));
+ sensor_reader.set_right_kicker_encoder(make_encoder(7));
+
+ sensor_reader.set_control_panel_encoder(make_encoder(8, frc::Encoder::k2X));
+
// Note: If ADIS16470 is plugged in directly to the roboRIO SPI port without
// the Spartan Board, then trigger is on 26, reset 27, and chip select is
// CS0.
@@ -250,6 +530,23 @@
::std::unique_ptr<::frc::VictorSP>(new ::frc::VictorSP(1)), false);
SuperstructureWriter superstructure_writer(&output_event_loop);
+ // TODO: check ports
+ superstructure_writer.set_hood_victor(make_unique<frc::VictorSP>(2));
+ superstructure_writer.set_intake_joint_victor(
+ make_unique<frc::VictorSP>(3));
+ superstructure_writer.set_intake_roller_falcon(
+ make_unique<::ctre::phoenix::motorcontrol::can::TalonFX>(4));
+ superstructure_writer.set_turret_victor(make_unique<frc::VictorSP>(5));
+ superstructure_writer.set_feeder_falcon(make_unique<frc::TalonFX>(6));
+ superstructure_writer.set_washing_machine_control_panel_victor(
+ make_unique<frc::VictorSP>(7));
+ superstructure_writer.set_kicker_left_falcon(
+ make_unique<::frc::TalonFX>(8));
+ superstructure_writer.set_kicker_right_falcon(
+ make_unique<::frc::TalonFX>(9));
+ superstructure_writer.set_flywheel_falcon(make_unique<::frc::TalonFX>(10));
+ superstructure_writer.set_climber_falcon(
+ make_unique<::ctre::phoenix::motorcontrol::can::TalonFX>(11));
AddLoop(&output_event_loop);