blob: fdde74bd75ec7e5f7fbf2ed60ff0ff0cbc4fb5a7 [file] [log] [blame]
#ifndef Y2016_BOT3_CONTROL_LOOPS_INTAKE_INTAKE_H_
#define Y2016_BOT3_CONTROL_LOOPS_INTAKE_INTAKE_H_
#include <memory>
#include "aos/common/controls/control_loop.h"
#include "aos/common/util/trapezoid_profile.h"
#include "frc971/control_loops/state_feedback_loop.h"
#include "frc971/zeroing/zeroing.h"
#include "y2016_bot3/control_loops/intake/intake.q.h"
#include "y2016_bot3/control_loops/intake/intake_controls.h"
namespace y2016_bot3 {
namespace constants {
static const int kZeroingSampleSize = 200;
// Ratios for our subsystems.
// TODO(constants): Update these.
static constexpr double kIntakeEncoderRatio = 18.0 / 72.0 * 15.0 / 48.0;
static constexpr double kIntakePotRatio = 15.0 / 48.0;
// Difference in radians between index pulses.
static constexpr double kIntakeEncoderIndexDifference =
2.0 * M_PI * kIntakeEncoderRatio;
// Subsystem motion ranges, in whatever units that their respective queues say
// the use.
// TODO(constants): Update these.
static constexpr ::frc971::constants::Range kIntakeRange{// Lower hard stop
-0.4,
// Upper hard stop
2.90,
// Lower soft stop
-0.28,
// Uppper soft stop
2.77};
struct IntakeZero {
static constexpr double pot_offset = 5.462409 + 0.333162;
static constexpr ::frc971::constants::ZeroingConstants zeroing{
kZeroingSampleSize, kIntakeEncoderIndexDifference, 0.148604 - 0.291240,
0.3};
};
} // namespace constants
namespace control_loops {
namespace intake {
namespace testing {
class IntakeTest_RespectsRange_Test;
class IntakeTest_DisabledGoalTest_Test;
class IntakeTest_IntakeZeroingErrorTest_Test;
class IntakeTest_UpperHardstopStartup_Test;
class IntakeTest_DisabledWhileZeroingHigh_Test;
class IntakeTest_DisabledWhileZeroingLow_Test;
}
// TODO(Adam): Implement this class and delete it from here.
class LimitChecker {
public:
LimitChecker(IntakeArm *intake) : intake_(intake) {}
void UpdateGoal(double intake_angle_goal);
private:
IntakeArm *intake_;
};
class Intake : public ::aos::controls::ControlLoop<control_loops::IntakeQueue> {
public:
explicit Intake(
control_loops::IntakeQueue *my_intake = &control_loops::intake_queue);
static constexpr double kZeroingVoltage = 6.0;
static constexpr double kOperatingVoltage = 12.0;
// This is the large scale movement tolerance.
static constexpr double kLooseTolerance = 0.05;
// This is the small scale movement tolerance.
static constexpr double kTightTolerance = 0.03;
static constexpr double kIntakeUpAngle = M_PI / 2;
static constexpr double kIntakeDownAngle = 0.0;
static constexpr double kIntakeMiddleAngle =
(kIntakeUpAngle + kIntakeDownAngle) / 2;
enum State {
// Wait for all the filters to be ready before starting the initialization
// process.
UNINITIALIZED = 0,
// We now are ready to decide how to zero. Decide what to do once we are
// enabled.
DISABLED_INITIALIZED = 1,
ZERO_LOWER_INTAKE = 2,
ZERO_LIFT_INTAKE = 3,
// Run, but limit power to zeroing voltages.
SLOW_RUNNING = 12,
// Run with full power.
RUNNING = 13,
// Internal error caused the intake to abort.
ESTOP = 16,
};
bool IsRunning() const {
return (state_ == SLOW_RUNNING || state_ == RUNNING);
}
State state() const { return state_; }
protected:
void RunIteration(const control_loops::IntakeQueue::Goal *unsafe_goal,
const control_loops::IntakeQueue::Position *position,
control_loops::IntakeQueue::Output *output,
control_loops::IntakeQueue::Status *status) override;
private:
friend class testing::IntakeTest_DisabledGoalTest_Test;
friend class testing::IntakeTest_IntakeZeroingErrorTest_Test;
friend class testing::IntakeTest_RespectsRange_Test;
friend class testing::IntakeTest_UpperHardstopStartup_Test;
friend class testing::IntakeTest_DisabledWhileZeroingHigh_Test;
friend class testing::IntakeTest_DisabledWhileZeroingLow_Test;
IntakeArm intake_;
State state_ = UNINITIALIZED;
State last_state_ = UNINITIALIZED;
float last_intake_angle_ = 0.0;
LimitChecker limit_checker_;
// Returns true if the profile has finished, and the joint is within the
// specified tolerance.
bool IsIntakeNear(double tolerance);
DISALLOW_COPY_AND_ASSIGN(Intake);
};
} // namespace intake
} // namespace control_loops
} // namespace y2016_bot3
#endif // Y2016_BOT3_CONTROL_LOOPS_SUPERSTRUCTURE_SUPERSTRUCTURE_H_