blob: fc5e917db4f3d8953576039f4d027632498802b5 [file] [log] [blame]
#ifndef FRC971_CONTROL_LOOPS_CLAW_CLAW_H_
#define FRC971_CONTROL_LOOPS_CLAW_CLAW_H_
#include <memory>
#include "aos/common/control_loop/ControlLoop.h"
#include "frc971/control_loops/state_feedback_loop.h"
#include "frc971/control_loops/claw/claw.q.h"
#include "frc971/control_loops/claw/top_claw_motor_plant.h"
#include "frc971/control_loops/claw/bottom_claw_motor_plant.h"
namespace frc971 {
namespace control_loops {
namespace testing {
class ClawTest_NoWindupPositive_Test;
class ClawTest_NoWindupNegative_Test;
};
// Note: Everything in this file assumes that there is a 1 cycle delay between
// power being requested and it showing up at the motor. It assumes that
// X_hat(2, 1) is the voltage being applied as well. It will go unstable if
// that isn't true.
// This class implements the CapU function correctly given all the extra
// information that we know about from the wrist motor.
// It does not have any zeroing logic in it, only logic to deal with a delta U
// controller.
class ZeroedStateFeedbackLoop : public StateFeedbackLoop<3, 1, 1> {
public:
ZeroedStateFeedbackLoop(StateFeedbackLoop<3, 1, 1> loop)
: StateFeedbackLoop<3, 1, 1>(loop),
voltage_(0.0),
last_voltage_(0.0),
uncapped_voltage_(0.0),
front_hall_effect_posedge_count_(0.0),
previous_front_hall_effect_posedge_count_(0.0),
front_hall_effect_negedge_count_(0.0),
previous_front_hall_effect_negedge_count_(0.0),
calibration_hall_effect_posedge_count_(0.0),
previous_calibration_hall_effect_posedge_count_(0.0),
calibration_hall_effect_negedge_count_(0.0),
previous_calibration_hall_effect_negedge_count_(0.0),
back_hall_effect_posedge_count_(0.0),
previous_back_hall_effect_posedge_count_(0.0),
back_hall_effect_negedge_count_(0.0),
previous_back_hall_effect_negedge_count_(0.0),
zeroing_state_(UNKNOWN_POSITION) {}
const static int kZeroingMaxVoltage = 5;
// Caps U, but this time respects the state of the wrist as well.
virtual void CapU();
// Returns the accumulated voltage.
double voltage() const { return voltage_; }
// Returns the uncapped voltage.
double uncapped_voltage() const { return uncapped_voltage_; }
// Zeros the accumulator.
void ZeroPower() { voltage_ = 0.0; }
enum JointZeroingState {
// We don't know where the joint is at all.
UNKNOWN_POSITION,
// We have an approximate position for where the claw is using.
APPROXIMATE_CALIBRATION,
// We observed the calibration edge while disabled. This is good enough for
// autonomous mode.
DISABLED_CALIBRATION,
// Ready for use during teleop.
CALIBRATED
};
void set_zeroing_state(JointZeroingState zeroing_state) {
zeroing_state_ = zeroing_state;
}
JointZeroingState zeroing_state() const { return zeroing_state_; }
#define COUNT_SETTER_GETTER(variable) \
void set_##variable(int32_t value) { \
previous_##variable##_ = variable##_; \
variable##_ = value; \
} \
int32_t variable() const { return variable##_; } \
bool variable##_changed() const { \
return previous_##variable##_ != variable##_; \
}
COUNT_SETTER_GETTER(front_hall_effect_posedge_count);
COUNT_SETTER_GETTER(front_hall_effect_negedge_count);
COUNT_SETTER_GETTER(calibration_hall_effect_posedge_count);
COUNT_SETTER_GETTER(calibration_hall_effect_negedge_count);
COUNT_SETTER_GETTER(back_hall_effect_posedge_count);
COUNT_SETTER_GETTER(back_hall_effect_negedge_count);
bool any_hall_effect_changed() const {
return front_hall_effect_posedge_count_changed() ||
front_hall_effect_negedge_count_changed() ||
calibration_hall_effect_posedge_count_changed() ||
calibration_hall_effect_negedge_count_changed() ||
back_hall_effect_posedge_count_changed() ||
back_hall_effect_negedge_count_changed();
}
#undef COUNT_SETTER_GETTER
private:
// The accumulated voltage to apply to the motor.
double voltage_;
double last_voltage_;
double uncapped_voltage_;
int32_t front_hall_effect_posedge_count_;
int32_t previous_front_hall_effect_posedge_count_;
int32_t front_hall_effect_negedge_count_;
int32_t previous_front_hall_effect_negedge_count_;
int32_t calibration_hall_effect_posedge_count_;
int32_t previous_calibration_hall_effect_posedge_count_;
int32_t calibration_hall_effect_negedge_count_;
int32_t previous_calibration_hall_effect_negedge_count_;
int32_t back_hall_effect_posedge_count_;
int32_t previous_back_hall_effect_posedge_count_;
int32_t back_hall_effect_negedge_count_;
int32_t previous_back_hall_effect_negedge_count_;
JointZeroingState zeroing_state_;
};
class ClawMotor
: public aos::control_loops::ControlLoop<control_loops::ClawGroup> {
public:
explicit ClawMotor(control_loops::ClawGroup *my_claw =
&control_loops::claw_queue_group);
// True if the state machine is ready.
bool is_ready() const { return false; }
protected:
virtual void RunIteration(const control_loops::ClawGroup::Goal *goal,
const control_loops::ClawGroup::Position *position,
control_loops::ClawGroup::Output *output,
::aos::control_loops::Status *status);
double top_absolute_position() const { return top_claw_.X_hat(0, 0); }
double bottom_absolute_position() const { return bottom_claw_.X_hat(0, 0); }
private:
// Friend the test classes for acces to the internal state.
friend class testing::ClawTest_NoWindupPositive_Test;
friend class testing::ClawTest_NoWindupNegative_Test;
// The zeroed joint to use.
bool has_top_claw_goal_;
double top_claw_goal_;
ZeroedStateFeedbackLoop top_claw_;
bool has_bottom_claw_goal_;
double bottom_claw_goal_;
ZeroedStateFeedbackLoop bottom_claw_;
bool was_enabled_;
DISALLOW_COPY_AND_ASSIGN(ClawMotor);
};
} // namespace control_loops
} // namespace frc971
#endif // FRC971_CONTROL_LOOPS_CLAW_CLAW_H_