Convert control loop tests over to simulated event loop
This makes it so that we properly only use ShmEventLoop for running in
realtime on a robot. Very nice.
Change-Id: I46b770b336f59e08cfaf28511b3bd5689f72fff1
diff --git a/y2014/control_loops/claw/claw_lib_test.cc b/y2014/control_loops/claw/claw_lib_test.cc
index 6545dcb..c88daa8 100644
--- a/y2014/control_loops/claw/claw_lib_test.cc
+++ b/y2014/control_loops/claw/claw_lib_test.cc
@@ -34,15 +34,27 @@
public:
// Constructs a motor simulation. initial_position is the inital angle of the
// wrist, which will be treated as 0 by the encoder.
- ClawMotorSimulation(double initial_top_position,
+ ClawMotorSimulation(::aos::EventLoop *event_loop, chrono::nanoseconds dt,
+ double initial_top_position,
double initial_bottom_position)
- : claw_plant_(new StateFeedbackPlant<4, 2, 2>(MakeClawPlant())),
- claw_queue(".y2014.control_loops.claw_queue",
- ".y2014.control_loops.claw_queue.goal",
- ".y2014.control_loops.claw_queue.position",
- ".y2014.control_loops.claw_queue.output",
- ".y2014.control_loops.claw_queue.status") {
+ : event_loop_(event_loop),
+ claw_position_sender_(event_loop_->MakeSender<ClawQueue::Position>(
+ ".y2014.control_loops.claw_queue.position")),
+ claw_output_fetcher_(event_loop_->MakeFetcher<ClawQueue::Output>(
+ ".y2014.control_loops.claw_queue.output")),
+ claw_plant_(new StateFeedbackPlant<4, 2, 2>(MakeClawPlant())) {
Reinitialize(initial_top_position, initial_bottom_position);
+
+ event_loop_->AddPhasedLoop(
+ [this](int) {
+ // Skip this the first time.
+ if (!first_) {
+ Simulate();
+ }
+ first_ = false;
+ SendPositionMessage();
+ },
+ dt);
}
void Reinitialize(double initial_top_position,
@@ -177,8 +189,8 @@
// Sends out the position queue messages.
void SendPositionMessage() {
- ::aos::ScopedMessagePtr<::y2014::control_loops::ClawQueue::Position>
- position = claw_queue.position.MakeMessage();
+ ::aos::Sender<::y2014::control_loops::ClawQueue::Position>::Message
+ position = claw_position_sender_.MakeMessage();
// Initialize all the counters to their previous values.
*position = last_position_;
@@ -203,11 +215,11 @@
// Simulates the claw moving for one timestep.
void Simulate() {
const constants::Values& v = constants::GetValues();
- EXPECT_TRUE(claw_queue.output.FetchLatest());
+ EXPECT_TRUE(claw_output_fetcher_.Fetch());
Eigen::Matrix<double, 2, 1> U;
- U << claw_queue.output->bottom_claw_voltage,
- claw_queue.output->top_claw_voltage;
+ U << claw_output_fetcher_->bottom_claw_voltage,
+ claw_output_fetcher_->top_claw_voltage;
claw_plant_->Update(U);
// Check that the claw is within the limits.
@@ -222,87 +234,92 @@
EXPECT_GE(claw_plant_->Y(1, 0) - claw_plant_->Y(0, 0),
v.claw.claw_min_separation);
}
+
+ private:
+ ::aos::EventLoop *event_loop_;
+ ::aos::Sender<ClawQueue::Position> claw_position_sender_;
+ ::aos::Fetcher<ClawQueue::Output> claw_output_fetcher_;
+
// The whole claw.
::std::unique_ptr<StateFeedbackPlant<4, 2, 2>> claw_plant_;
- private:
+ bool first_ = true;
+
// Resets the plant so that it starts at initial_position.
void ReinitializePartial(ClawType type, double initial_position) {
initial_position_[type] = initial_position;
}
- ::y2014::control_loops::ClawQueue claw_queue;
double initial_position_[CLAW_COUNT];
::y2014::control_loops::ClawQueue::Position last_position_;
};
-
class ClawTest : public ::aos::testing::ControlLoopTest {
protected:
- // Create a new instance of the test queue so that it invalidates the queue
- // that it points to. Otherwise, we will have a pointer to shared memory that
- // is no longer valid.
- ::y2014::control_loops::ClawQueue claw_queue;
+ ClawTest()
+ : ::aos::testing::ControlLoopTest(chrono::microseconds(5000)),
+ test_event_loop_(MakeEventLoop()),
+ claw_goal_sender_(test_event_loop_->MakeSender<ClawQueue::Goal>(
+ ".y2014.control_loops.claw_queue.goal")),
+ claw_goal_fetcher_(test_event_loop_->MakeFetcher<ClawQueue::Goal>(
+ ".y2014.control_loops.claw_queue.goal")),
+ claw_event_loop_(MakeEventLoop()),
+ claw_motor_(claw_event_loop_.get()),
+ claw_plant_event_loop_(MakeEventLoop()),
+ claw_motor_plant_(claw_plant_event_loop_.get(), dt(), 0.4, 0.2),
+ min_separation_(constants::GetValues().claw.claw_min_separation) {}
- ::aos::ShmEventLoop event_loop_;
+ void VerifyNearGoal() {
+ claw_goal_fetcher_.Fetch();
+ double bottom = claw_motor_plant_.GetAbsolutePosition(BOTTOM_CLAW);
+ double separation =
+ claw_motor_plant_.GetAbsolutePosition(TOP_CLAW) - bottom;
+ EXPECT_NEAR(claw_goal_fetcher_->bottom_angle, bottom, 1e-4);
+ EXPECT_NEAR(claw_goal_fetcher_->separation_angle, separation, 1e-4);
+ EXPECT_LE(min_separation_, separation);
+ }
+
+ ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
+ ::aos::Sender<ClawQueue::Goal> claw_goal_sender_;
+ ::aos::Fetcher<ClawQueue::Goal> claw_goal_fetcher_;
+
// Create a loop and simulation plant.
+ ::std::unique_ptr<::aos::EventLoop> claw_event_loop_;
ClawMotor claw_motor_;
+
+ ::std::unique_ptr<::aos::EventLoop> claw_plant_event_loop_;
ClawMotorSimulation claw_motor_plant_;
// Minimum amount of acceptable separation between the top and bottom of the
// claw.
double min_separation_;
- ClawTest()
- : claw_queue(".y2014.control_loops.claw_queue",
- ".y2014.control_loops.claw_queue.goal",
- ".y2014.control_loops.claw_queue.position",
- ".y2014.control_loops.claw_queue.output",
- ".y2014.control_loops.claw_queue.status"),
- claw_motor_(&event_loop_),
- claw_motor_plant_(0.4, 0.2),
- min_separation_(constants::GetValues().claw.claw_min_separation) {}
-
- void VerifyNearGoal() {
- claw_queue.goal.FetchLatest();
- claw_queue.position.FetchLatest();
- double bottom = claw_motor_plant_.GetAbsolutePosition(BOTTOM_CLAW);
- double separation =
- claw_motor_plant_.GetAbsolutePosition(TOP_CLAW) - bottom;
- EXPECT_NEAR(claw_queue.goal->bottom_angle, bottom, 1e-4);
- EXPECT_NEAR(claw_queue.goal->separation_angle, separation, 1e-4);
- EXPECT_LE(min_separation_, separation);
- }
};
TEST_F(ClawTest, HandlesNAN) {
- claw_queue.goal.MakeWithBuilder()
- .bottom_angle(::std::nan(""))
- .separation_angle(::std::nan(""))
- .Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::seconds(5))) {
- claw_motor_plant_.SendPositionMessage();
- claw_motor_.Iterate();
- claw_motor_plant_.Simulate();
- SimulateTimestep(true);
+ {
+ auto message = claw_goal_sender_.MakeMessage();
+ message->bottom_angle = ::std::nan("");
+ message->separation_angle = ::std::nan("");
+ EXPECT_TRUE(message.Send());
}
+
+ SetEnabled(true);
+ RunFor(chrono::seconds(5));
}
// Tests that the wrist zeros correctly and goes to a position.
TEST_F(ClawTest, ZerosCorrectly) {
- claw_queue.goal.MakeWithBuilder()
- .bottom_angle(0.1)
- .separation_angle(0.2)
- .Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::seconds(5))) {
- claw_motor_plant_.SendPositionMessage();
- claw_motor_.Iterate();
- claw_motor_plant_.Simulate();
- SimulateTimestep(true);
+ {
+ auto message = claw_goal_sender_.MakeMessage();
+ message->bottom_angle = 0.1;
+ message->separation_angle = 0.2;
+ EXPECT_TRUE(message.Send());
}
+
+ SetEnabled(true);
+ RunFor(chrono::seconds(5));
VerifyNearGoal();
}
@@ -391,18 +408,16 @@
TEST_P(ZeroingClawTest, ParameterizedZero) {
claw_motor_plant_.Reinitialize(GetParam().first, GetParam().second);
- claw_queue.goal.MakeWithBuilder()
- .bottom_angle(0.1)
- .separation_angle(0.2)
- .Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::seconds(7))) {
- claw_motor_plant_.SendPositionMessage();
- claw_motor_.Iterate();
- claw_motor_plant_.Simulate();
-
- SimulateTimestep(true);
+ {
+ auto message = claw_goal_sender_.MakeMessage();
+ message->bottom_angle = 0.1;
+ message->separation_angle = 0.2;
+ EXPECT_TRUE(message.Send());
}
+
+ SetEnabled(true);
+ RunFor(chrono::seconds(7));
+
VerifyNearGoal();
}
@@ -509,15 +524,15 @@
protected:
void TestWindup(ClawMotor::CalibrationMode mode,
monotonic_clock::time_point start_time, double offset) {
+ SetEnabled(true);
int capped_count = 0;
const constants::Values& values = constants::GetValues();
bool kicked = false;
bool measured = false;
- while (monotonic_clock::now() <
+ while (test_event_loop_->monotonic_now() <
monotonic_clock::time_point(chrono::seconds(7))) {
- claw_motor_plant_.SendPositionMessage();
- if (monotonic_clock::now() >= start_time && mode == claw_motor_.mode() &&
- !kicked) {
+ if (test_event_loop_->monotonic_now() >= start_time &&
+ mode == claw_motor_.mode() && !kicked) {
EXPECT_EQ(mode, claw_motor_.mode());
// Move the zeroing position far away and verify that it gets moved
// back.
@@ -558,9 +573,7 @@
}
}
- claw_motor_.Iterate();
- claw_motor_plant_.Simulate();
- SimulateTimestep(true);
+ RunFor(dt());
}
EXPECT_TRUE(kicked);
EXPECT_TRUE(measured);
@@ -572,10 +585,12 @@
// Tests that the wrist can't get too far away from the zeroing position if the
// zeroing position is saturating the goal.
TEST_F(WindupClawTest, NoWindupPositive) {
- claw_queue.goal.MakeWithBuilder()
- .bottom_angle(0.1)
- .separation_angle(0.2)
- .Send();
+ {
+ auto message = claw_goal_sender_.MakeMessage();
+ message->bottom_angle = 0.1;
+ message->separation_angle = 0.2;
+ EXPECT_TRUE(message.Send());
+ }
TestWindup(ClawMotor::UNKNOWN_LOCATION,
monotonic_clock::time_point(chrono::seconds(1)), 971.0);
@@ -586,10 +601,12 @@
// Tests that the wrist can't get too far away from the zeroing position if the
// zeroing position is saturating the goal.
TEST_F(WindupClawTest, NoWindupNegative) {
- claw_queue.goal.MakeWithBuilder()
- .bottom_angle(0.1)
- .separation_angle(0.2)
- .Send();
+ {
+ auto message = claw_goal_sender_.MakeMessage();
+ message->bottom_angle = 0.1;
+ message->separation_angle = 0.2;
+ EXPECT_TRUE(message.Send());
+ }
TestWindup(ClawMotor::UNKNOWN_LOCATION,
monotonic_clock::time_point(chrono::seconds(1)), -971.0);
@@ -600,10 +617,12 @@
// Tests that the wrist can't get too far away from the zeroing position if the
// zeroing position is saturating the goal.
TEST_F(WindupClawTest, NoWindupNegativeFineTune) {
- claw_queue.goal.MakeWithBuilder()
- .bottom_angle(0.1)
- .separation_angle(0.2)
- .Send();
+ {
+ auto message = claw_goal_sender_.MakeMessage();
+ message->bottom_angle = 0.1;
+ message->separation_angle = 0.2;
+ EXPECT_TRUE(message.Send());
+ }
TestWindup(ClawMotor::FINE_TUNE_BOTTOM,
monotonic_clock::time_point(chrono::seconds(2)), -971.0);
diff --git a/y2014/control_loops/claw/claw_main.cc b/y2014/control_loops/claw/claw_main.cc
index 85497d9..65627d5 100644
--- a/y2014/control_loops/claw/claw_main.cc
+++ b/y2014/control_loops/claw/claw_main.cc
@@ -4,10 +4,13 @@
#include "aos/init.h"
int main() {
- ::aos::Init();
+ ::aos::InitNRT(true);
+
::aos::ShmEventLoop event_loop;
::y2014::control_loops::ClawMotor claw(&event_loop);
- claw.Run();
+
+ event_loop.Run();
+
::aos::Cleanup();
return 0;
}
diff --git a/y2014/control_loops/drivetrain/drivetrain_main.cc b/y2014/control_loops/drivetrain/drivetrain_main.cc
index 21dfcd2..7749631 100644
--- a/y2014/control_loops/drivetrain/drivetrain_main.cc
+++ b/y2014/control_loops/drivetrain/drivetrain_main.cc
@@ -7,13 +7,16 @@
using ::frc971::control_loops::drivetrain::DrivetrainLoop;
int main() {
- ::aos::Init();
+ ::aos::InitNRT(true);
+
::aos::ShmEventLoop event_loop;
::frc971::control_loops::drivetrain::DeadReckonEkf localizer(
- ::y2014::control_loops::GetDrivetrainConfig());
+ &event_loop, ::y2014::control_loops::GetDrivetrainConfig());
DrivetrainLoop drivetrain(::y2014::control_loops::GetDrivetrainConfig(),
&event_loop, &localizer);
- drivetrain.Run();
+
+ event_loop.Run();
+
::aos::Cleanup();
return 0;
}
diff --git a/y2014/control_loops/shooter/shooter.cc b/y2014/control_loops/shooter/shooter.cc
index d87c638..d1ef2a5 100644
--- a/y2014/control_loops/shooter/shooter.cc
+++ b/y2014/control_loops/shooter/shooter.cc
@@ -219,6 +219,7 @@
const ::y2014::control_loops::ShooterQueue::Position *position,
::y2014::control_loops::ShooterQueue::Output *output,
::y2014::control_loops::ShooterQueue::Status *status) {
+ const monotonic_clock::time_point monotonic_now = event_loop()->monotonic_now();
if (goal && ::std::isnan(goal->shot_power)) {
state_ = STATE_ESTOP;
LOG(ERROR, "Estopping because got a shot power of NAN.\n");
@@ -332,11 +333,11 @@
// The plunger is back and we are latched. We most likely got here
// from Initialize, in which case we want to 'load' again anyways to
// zero.
- Load();
+ Load(monotonic_now);
latch_piston_ = true;
} else {
// Off the sensor, start loading.
- Load();
+ Load(monotonic_now);
latch_piston_ = false;
}
}
@@ -361,7 +362,7 @@
if (position) {
if (!position->pusher_distal.current &&
!position->pusher_proximal.current) {
- Load();
+ Load(monotonic_now);
}
latch_piston_ = position->plunger;
}
@@ -371,7 +372,7 @@
case STATE_LOAD:
// If we are disabled right now, reset the timer.
if (disabled) {
- Load();
+ Load(monotonic_now);
// Latch defaults to true when disabled. Leave it latched until we have
// useful sensor data.
latch_piston_ = true;
@@ -406,17 +407,17 @@
// We are at the goal, but not latched.
state_ = STATE_LOADING_PROBLEM;
loading_problem_end_time_ =
- monotonic_clock::now() + kLoadProblemEndTimeout;
+ monotonic_now + kLoadProblemEndTimeout;
}
}
- if (load_timeout_ < monotonic_clock::now()) {
+ if (load_timeout_ < monotonic_now) {
if (position) {
// If none of the sensors is triggered, estop.
// Otherwise, trigger anyways if it has been 0.5 seconds more.
if (!(position->pusher_distal.current ||
position->pusher_proximal.current) ||
(load_timeout_ + chrono::milliseconds(500) <
- monotonic_clock::now())) {
+ monotonic_now)) {
state_ = STATE_ESTOP;
LOG(ERROR, "Estopping because took too long to load.\n");
}
@@ -431,9 +432,9 @@
}
// We got to the goal, but the latch hasn't registered as down. It might
// be stuck, or on it's way but not there yet.
- if (monotonic_clock::now() > loading_problem_end_time_) {
+ if (monotonic_now > loading_problem_end_time_) {
// Timeout by unloading.
- Unload();
+ Unload(monotonic_now);
} else if (position && position->plunger && position->latch) {
// If both trigger, we are latched.
state_ = STATE_PREPARE_SHOT;
@@ -471,21 +472,21 @@
// We are there, set the brake and move on.
latch_piston_ = true;
brake_piston_ = true;
- shooter_brake_set_time_ = monotonic_clock::now() + kShooterBrakeSetTime;
+ shooter_brake_set_time_ = monotonic_now + kShooterBrakeSetTime;
state_ = STATE_READY;
} else {
latch_piston_ = true;
brake_piston_ = false;
}
if (goal && goal->unload_requested) {
- Unload();
+ Unload(monotonic_now);
}
break;
case STATE_READY:
LOG(DEBUG, "In ready\n");
// Wait until the brake is set, and a shot is requested or the shot power
// is changed.
- if (monotonic_clock::now() > shooter_brake_set_time_) {
+ if (monotonic_now > shooter_brake_set_time_) {
status->ready = true;
// We have waited long enough for the brake to set, turn the shooter
// control loop off.
@@ -494,7 +495,7 @@
if (goal && goal->shot_requested && !disabled) {
LOG(DEBUG, "Shooting now\n");
shooter_loop_disable = true;
- shot_end_time_ = monotonic_clock::now() + kShotEndTimeout;
+ shot_end_time_ = monotonic_now + kShotEndTimeout;
firing_starting_position_ = shooter_.absolute_position();
state_ = STATE_FIRE;
}
@@ -519,7 +520,7 @@
brake_piston_ = true;
if (goal && goal->unload_requested) {
- Unload();
+ Unload(monotonic_now);
}
break;
@@ -529,7 +530,7 @@
if (position->plunger) {
// If disabled and the plunger is still back there, reset the
// timeout.
- shot_end_time_ = monotonic_clock::now() + kShotEndTimeout;
+ shot_end_time_ = monotonic_now + kShotEndTimeout;
}
}
}
@@ -548,7 +549,7 @@
if (((::std::abs(firing_starting_position_ -
shooter_.absolute_position()) > 0.0005 &&
cycles_not_moved_ > 6) ||
- monotonic_clock::now() > shot_end_time_) &&
+ monotonic_now > shot_end_time_) &&
robot_state().voltage_battery > 10.5) {
state_ = STATE_REQUEST_LOAD;
++shot_count_;
@@ -558,7 +559,7 @@
break;
case STATE_UNLOAD:
// Reset the timeouts.
- if (disabled) Unload();
+ if (disabled) Unload(monotonic_now);
// If it is latched and the plunger is back, move the pusher back to catch
// the plunger.
@@ -588,10 +589,10 @@
shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
latch_piston_ = false;
state_ = STATE_UNLOAD_MOVE;
- unload_timeout_ = monotonic_clock::now() + kUnloadTimeout;
+ unload_timeout_ = monotonic_now + kUnloadTimeout;
}
- if (monotonic_clock::now() > unload_timeout_) {
+ if (monotonic_now > unload_timeout_) {
// We have been stuck trying to unload for way too long, give up and
// turn everything off.
state_ = STATE_ESTOP;
@@ -602,7 +603,7 @@
break;
case STATE_UNLOAD_MOVE: {
if (disabled) {
- unload_timeout_ = monotonic_clock::now() + kUnloadTimeout;
+ unload_timeout_ = monotonic_now + kUnloadTimeout;
shooter_.SetGoalPosition(shooter_.absolute_position(), 0.0);
}
cap_goal = true;
diff --git a/y2014/control_loops/shooter/shooter.h b/y2014/control_loops/shooter/shooter.h
index a9a255b..01096a0 100644
--- a/y2014/control_loops/shooter/shooter.h
+++ b/y2014/control_loops/shooter/shooter.h
@@ -175,14 +175,14 @@
friend class testing::ShooterTest_RezeroWhileUnloading_Test;
// Enter state STATE_UNLOAD
- void Unload() {
+ void Unload(::aos::monotonic_clock::time_point monotonic_now) {
state_ = STATE_UNLOAD;
- unload_timeout_ = ::aos::monotonic_clock::now() + kUnloadTimeout;
+ unload_timeout_ = monotonic_now + kUnloadTimeout;
}
// Enter state STATE_LOAD
- void Load() {
+ void Load(::aos::monotonic_clock::time_point monotonic_now) {
state_ = STATE_LOAD;
- load_timeout_ = ::aos::monotonic_clock::now() + kLoadTimeout;
+ load_timeout_ = monotonic_now + kLoadTimeout;
}
::y2014::control_loops::ShooterQueue::Position last_position_;
diff --git a/y2014/control_loops/shooter/shooter_lib_test.cc b/y2014/control_loops/shooter/shooter_lib_test.cc
index e88a33e..b6883ad 100644
--- a/y2014/control_loops/shooter/shooter_lib_test.cc
+++ b/y2014/control_loops/shooter/shooter_lib_test.cc
@@ -28,19 +28,32 @@
class ShooterSimulation {
public:
// Constructs a motor simulation.
- ShooterSimulation(double initial_position)
- : shooter_plant_(new StateFeedbackPlant<2, 1, 1>(MakeRawShooterPlant())),
+ ShooterSimulation(::aos::EventLoop *event_loop, chrono::nanoseconds dt,
+ double initial_position)
+ : event_loop_(event_loop),
+ shooter_position_sender_(
+ event_loop_->MakeSender<ShooterQueue::Position>(
+ ".y2014.control_loops.shooter_queue.position")),
+ shooter_output_fetcher_(event_loop_->MakeFetcher<ShooterQueue::Output>(
+ ".y2014.control_loops.shooter_queue.output")),
+ shooter_plant_(new StateFeedbackPlant<2, 1, 1>(MakeRawShooterPlant())),
latch_piston_state_(false),
latch_delay_count_(0),
plunger_latched_(false),
brake_piston_state_(true),
- brake_delay_count_(0),
- shooter_queue_(".y2014.control_loops.shooter_queue",
- ".y2014.control_loops.shooter_queue.goal",
- ".y2014.control_loops.shooter_queue.position",
- ".y2014.control_loops.shooter_queue.output",
- ".y2014.control_loops.shooter_queue.status") {
+ brake_delay_count_(0) {
Reinitialize(initial_position);
+
+ event_loop_->AddPhasedLoop(
+ [this](int) {
+ // Skip this the first time.
+ if (!first_) {
+ Simulate();
+ }
+ first_ = false;
+ SendPositionMessage();
+ },
+ dt);
}
// The difference between the position with 0 at the back, and the position
@@ -133,25 +146,24 @@
}
}
- void SendPositionMessage() {
- // the first bool is false
- SendPositionMessage(false, false, false, false);
- }
+ void set_use_passed(bool use_passed) { use_passed_ = use_passed; }
+ void set_plunger_in(bool plunger_in) { plunger_in_ = plunger_in; }
+ void set_latch_in(bool latch_in) { latch_in_ = latch_in; }
+ void set_brake_in(bool brake_in) { brake_in_ = brake_in; }
// Sends out the position queue messages.
- // if the first bool is false then this is
+ // if used_passed_ is false then this is
// just the default state, otherwise will force
- // it into a state using the passed values
- void SendPositionMessage(bool use_passed, bool plunger_in,
- bool latch_in, bool brake_in) {
+ // it into a state using the plunger_in_, brake_in_, and latch_in_ values.
+ void SendPositionMessage() {
const constants::Values &values = constants::GetValues();
- ::aos::ScopedMessagePtr<::y2014::control_loops::ShooterQueue::Position>
- position = shooter_queue_.position.MakeMessage();
+ ::aos::Sender<ShooterQueue::Position>::Message position =
+ shooter_position_sender_.MakeMessage();
- if (use_passed) {
- plunger_latched_ = latch_in && plunger_in;
+ if (use_passed_) {
+ plunger_latched_ = latch_in_ && plunger_in_;
latch_piston_state_ = plunger_latched_;
- brake_piston_state_ = brake_in;
+ brake_piston_state_ = brake_in_;
}
SetPhysicalSensors(position.get());
@@ -175,22 +187,22 @@
// Simulates the claw moving for one timestep.
void Simulate() {
last_plant_position_ = GetAbsolutePosition();
- EXPECT_TRUE(shooter_queue_.output.FetchLatest());
- if (shooter_queue_.output->latch_piston && !latch_piston_state_ &&
+ EXPECT_TRUE(shooter_output_fetcher_.Fetch());
+ if (shooter_output_fetcher_->latch_piston && !latch_piston_state_ &&
latch_delay_count_ <= 0) {
ASSERT_EQ(0, latch_delay_count_) << "The test doesn't support that.";
latch_delay_count_ = 6;
- } else if (!shooter_queue_.output->latch_piston &&
+ } else if (!shooter_output_fetcher_->latch_piston &&
latch_piston_state_ && latch_delay_count_ >= 0) {
ASSERT_EQ(0, latch_delay_count_) << "The test doesn't support that.";
latch_delay_count_ = -6;
}
- if (shooter_queue_.output->brake_piston && !brake_piston_state_ &&
+ if (shooter_output_fetcher_->brake_piston && !brake_piston_state_ &&
brake_delay_count_ <= 0) {
ASSERT_EQ(0, brake_delay_count_) << "The test doesn't support that.";
brake_delay_count_ = 5;
- } else if (!shooter_queue_.output->brake_piston &&
+ } else if (!shooter_output_fetcher_->brake_piston &&
brake_piston_state_ && brake_delay_count_ >= 0) {
ASSERT_EQ(0, brake_delay_count_) << "The test doesn't support that.";
brake_delay_count_ = -5;
@@ -251,10 +263,16 @@
EXPECT_LE(constants::GetValues().shooter.lower_hard_limit,
GetAbsolutePosition());
- last_voltage_ = shooter_queue_.output->voltage;
- ::aos::time::IncrementMockTime(chrono::milliseconds(10));
+ last_voltage_ = shooter_output_fetcher_->voltage;
}
+ private:
+ ::aos::EventLoop *event_loop_;
+ ::aos::Sender<ShooterQueue::Position> shooter_position_sender_;
+ ::aos::Fetcher<ShooterQueue::Output> shooter_output_fetcher_;
+
+ bool first_ = true;
+
// pointer to plant
const ::std::unique_ptr<StateFeedbackPlant<2, 1, 1>> shooter_plant_;
@@ -271,12 +289,16 @@
// greater than zero, delaying close. less than zero delaying open
int brake_delay_count_;
- private:
- ::y2014::control_loops::ShooterQueue shooter_queue_;
+ // Overrides for testing.
+ bool use_passed_ = false;
+ bool plunger_in_ = false;
+ bool latch_in_ = false;
+ bool brake_in_ = false;
+
double initial_position_;
double last_voltage_;
- ::y2014::control_loops::ShooterQueue::Position last_position_message_;
+ ShooterQueue::Position last_position_message_;
double last_plant_position_;
};
@@ -284,35 +306,40 @@
class ShooterTestTemplated
: public ::aos::testing::ControlLoopTestTemplated<TestType> {
protected:
- // Create a new instance of the test queue so that it invalidates the queue
- // that it points to. Otherwise, we will have a pointer to shared memory that
- // is no longer valid.
- ::y2014::control_loops::ShooterQueue shooter_queue_;
-
- ::aos::ShmEventLoop event_loop_;
- // Create a loop and simulation plant.
- ShooterMotor shooter_motor_;
- ShooterSimulation shooter_motor_plant_;
+ ShooterTestTemplated()
+ : ::aos::testing::ControlLoopTestTemplated<TestType>(
+ // TODO(austin): I think this runs at 5 ms in real life.
+ chrono::microseconds(5000)),
+ test_event_loop_(this->MakeEventLoop()),
+ shooter_goal_fetcher_(test_event_loop_->MakeFetcher<ShooterQueue::Goal>(
+ ".y2014.control_loops.shooter_queue.goal")),
+ shooter_goal_sender_(test_event_loop_->MakeSender<ShooterQueue::Goal>(
+ ".y2014.control_loops.shooter_queue.goal")),
+ shooter_event_loop_(this->MakeEventLoop()),
+ shooter_motor_(shooter_event_loop_.get()),
+ shooter_plant_event_loop_(this->MakeEventLoop()),
+ shooter_motor_plant_(shooter_plant_event_loop_.get(), this->dt(), 0.2) {
+ }
void Reinitialize(double position) {
shooter_motor_plant_.Reinitialize(position);
}
- ShooterTestTemplated()
- : shooter_queue_(".y2014.control_loops.shooter_queue",
- ".y2014.control_loops.shooter_queue.goal",
- ".y2014.control_loops.shooter_queue.position",
- ".y2014.control_loops.shooter_queue.output",
- ".y2014.control_loops.shooter_queue.status"),
- shooter_motor_(&event_loop_),
- shooter_motor_plant_(0.2) {}
-
void VerifyNearGoal() {
- shooter_queue_.goal.FetchLatest();
- shooter_queue_.position.FetchLatest();
- double pos = shooter_motor_plant_.GetAbsolutePosition();
- EXPECT_NEAR(shooter_queue_.goal->shot_power, pos, 1e-4);
+ shooter_goal_fetcher_.Fetch();
+ const double pos = shooter_motor_plant_.GetAbsolutePosition();
+ EXPECT_NEAR(shooter_goal_fetcher_->shot_power, pos, 1e-4);
}
+
+ ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
+ ::aos::Fetcher<ShooterQueue::Goal> shooter_goal_fetcher_;
+ ::aos::Sender<ShooterQueue::Goal> shooter_goal_sender_;
+
+ // Create a loop and simulation plant.
+ ::std::unique_ptr<::aos::EventLoop> shooter_event_loop_;
+ ShooterMotor shooter_motor_;
+ ::std::unique_ptr<::aos::EventLoop> shooter_plant_event_loop_;
+ ShooterSimulation shooter_motor_plant_;
};
typedef ShooterTestTemplated<::testing::Test> ShooterTest;
@@ -350,99 +377,104 @@
// Tests that the shooter zeros correctly and goes to a position.
TEST_F(ShooterTest, GoesToValue) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::seconds(2))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70.0;
+ EXPECT_TRUE(message.Send());
}
- // EXPECT_NEAR(0.0, shooter_motor_.GetPosition(), 0.01);
+ RunFor(chrono::seconds(2));
+
double pos = shooter_motor_plant_.GetAbsolutePosition();
- EXPECT_TRUE(shooter_queue_.goal.FetchLatest());
+ EXPECT_TRUE(shooter_goal_fetcher_.Fetch());
EXPECT_NEAR(
- shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+ shooter_motor_.PowerToPosition(shooter_goal_fetcher_->shot_power),
pos, 0.05);
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
}
// Tests that the shooter zeros correctly and goes to a position.
TEST_F(ShooterTest, Fire) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::milliseconds(1200))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70.0;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::milliseconds(1200));
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
- shooter_queue_.goal.MakeWithBuilder()
- .shot_power(35.0)
- .shot_requested(true)
- .Send();
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 35.0;
+ message->shot_requested = true;
+ EXPECT_TRUE(message.Send());
+ }
bool hit_fire = false;
- while (monotonic_clock::now() <
+ while (test_event_loop_->monotonic_now() <
monotonic_clock::time_point(chrono::milliseconds(5200))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ RunFor(dt());
if (shooter_motor_.state() == ShooterMotor::STATE_FIRE) {
if (!hit_fire) {
- shooter_queue_.goal.MakeWithBuilder()
- .shot_power(17.0)
- .shot_requested(false)
- .Send();
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 17.0;
+ message->shot_requested = false;
+ EXPECT_TRUE(message.Send());
}
hit_fire = true;
}
}
double pos = shooter_motor_plant_.GetAbsolutePosition();
- EXPECT_TRUE(shooter_queue_.goal.FetchLatest());
- EXPECT_NEAR(
- shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
- pos, 0.05);
+ EXPECT_TRUE(shooter_goal_fetcher_.Fetch());
+ EXPECT_NEAR(shooter_motor_.PowerToPosition(shooter_goal_fetcher_->shot_power),
+ pos, 0.05);
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
EXPECT_TRUE(hit_fire);
}
// Tests that the shooter zeros correctly and goes to a position.
TEST_F(ShooterTest, FireLong) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::milliseconds(1500))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70.0;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::milliseconds(1500));
+
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
- shooter_queue_.goal.MakeWithBuilder().shot_requested(true).Send();
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 0.0;
+ message->shot_requested = true;
+ EXPECT_TRUE(message.Send());
+ }
bool hit_fire = false;
- while (monotonic_clock::now() <
+ while (test_event_loop_->monotonic_now() <
monotonic_clock::time_point(chrono::milliseconds(5500))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ RunFor(dt());
if (shooter_motor_.state() == ShooterMotor::STATE_FIRE) {
if (!hit_fire) {
- shooter_queue_.goal.MakeWithBuilder()
- .shot_requested(false)
- .Send();
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_requested = false;
+ EXPECT_TRUE(message.Send());
}
hit_fire = true;
}
}
double pos = shooter_motor_plant_.GetAbsolutePosition();
- EXPECT_TRUE(shooter_queue_.goal.FetchLatest());
- EXPECT_NEAR(shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+ EXPECT_TRUE(shooter_goal_fetcher_.Fetch());
+ EXPECT_NEAR(shooter_motor_.PowerToPosition(shooter_goal_fetcher_->shot_power),
pos, 0.05);
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
EXPECT_TRUE(hit_fire);
@@ -451,13 +483,16 @@
// Verifies that it doesn't try to go out too far if you give it a ridicilous
// power.
TEST_F(ShooterTest, LoadTooFar) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(500.0).Send();
- while (monotonic_clock::now() <
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 500.0;
+ EXPECT_TRUE(message.Send());
+ }
+ while (test_event_loop_->monotonic_now() <
monotonic_clock::time_point(chrono::milliseconds(1600))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ RunFor(dt());
EXPECT_LT(shooter_motor_plant_.GetAbsolutePosition(),
constants::GetValuesForTeam(kTeamNumber).shooter.upper_limit);
}
@@ -466,53 +501,55 @@
// Tests that the shooter zeros correctly and goes to a position.
TEST_F(ShooterTest, MoveGoal) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::milliseconds(1500))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70.0;
+ EXPECT_TRUE(message.Send());
}
- EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
- shooter_queue_.goal.MakeWithBuilder().shot_power(14.0).Send();
+ RunFor(chrono::milliseconds(1500));
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::seconds(2))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 14.0;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::milliseconds(500));
+
double pos = shooter_motor_plant_.GetAbsolutePosition();
- EXPECT_TRUE(shooter_queue_.goal.FetchLatest());
+ EXPECT_TRUE(shooter_goal_fetcher_.Fetch());
EXPECT_NEAR(
- shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+ shooter_motor_.PowerToPosition(shooter_goal_fetcher_->shot_power),
pos, 0.05);
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
}
TEST_F(ShooterTest, Unload) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::milliseconds(1500))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70.0;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::milliseconds(1500));
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
- shooter_queue_.goal.MakeWithBuilder().unload_requested(true).Send();
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->unload_requested = true;
+ EXPECT_TRUE(message.Send());
+ }
- while (monotonic_clock::now() <
+ while (test_event_loop_->monotonic_now() <
monotonic_clock::time_point(chrono::seconds(8)) &&
shooter_motor_.state() != ShooterMotor::STATE_READY_UNLOAD) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ RunFor(dt());
}
EXPECT_NEAR(constants::GetValues().shooter.upper_limit,
@@ -522,34 +559,31 @@
// Tests that it rezeros while unloading.
TEST_F(ShooterTest, RezeroWhileUnloading) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::milliseconds(1500))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::milliseconds(1500));
+
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
shooter_motor_.shooter_.offset_ += 0.01;
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::seconds(2))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ RunFor(chrono::milliseconds(500));
+
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->unload_requested = true;
+ EXPECT_TRUE(message.Send());
}
- shooter_queue_.goal.MakeWithBuilder().unload_requested(true).Send();
-
- while (::aos::monotonic_clock::now() <
+ while (test_event_loop_->monotonic_now() <
::aos::monotonic_clock::time_point(chrono::seconds(10)) &&
shooter_motor_.state() != ShooterMotor::STATE_READY_UNLOAD) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ RunFor(dt());
}
EXPECT_NEAR(constants::GetValues().shooter.upper_limit,
@@ -559,24 +593,28 @@
// Tests that the shooter zeros correctly and goes to a position.
TEST_F(ShooterTest, UnloadWindupNegative) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::milliseconds(1500))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::milliseconds(1500));
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
- shooter_queue_.goal.MakeWithBuilder().unload_requested(true).Send();
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->unload_requested = true;
+ EXPECT_TRUE(message.Send());
+ }
int kicked_delay = 20;
int capped_goal_count = 0;
- while (monotonic_clock::now() <
+ while (test_event_loop_->monotonic_now() <
monotonic_clock::time_point(chrono::milliseconds(9500)) &&
shooter_motor_.state() != ShooterMotor::STATE_READY_UNLOAD) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
+ RunFor(dt());
if (shooter_motor_.state() == ShooterMotor::STATE_UNLOAD_MOVE) {
LOG(DEBUG, "State is UnloadMove\n");
--kicked_delay;
@@ -587,8 +625,6 @@
if (shooter_motor_.capped_goal() && kicked_delay < 0) {
++capped_goal_count;
}
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
}
EXPECT_NEAR(constants::GetValues().shooter.upper_limit,
@@ -600,24 +636,28 @@
// Tests that the shooter zeros correctly and goes to a position.
TEST_F(ShooterTest, UnloadWindupPositive) {
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::milliseconds(1500))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ SetEnabled(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::milliseconds(1500));
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
- shooter_queue_.goal.MakeWithBuilder().unload_requested(true).Send();
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->unload_requested = true;
+ EXPECT_TRUE(message.Send());
+ }
int kicked_delay = 20;
int capped_goal_count = 0;
- while (monotonic_clock::now() <
+ while (test_event_loop_->monotonic_now() <
monotonic_clock::time_point(chrono::milliseconds(9500)) &&
shooter_motor_.state() != ShooterMotor::STATE_READY_UNLOAD) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
+ RunFor(dt());
if (shooter_motor_.state() == ShooterMotor::STATE_UNLOAD_MOVE) {
LOG(DEBUG, "State is UnloadMove\n");
--kicked_delay;
@@ -628,8 +668,6 @@
if (shooter_motor_.capped_goal() && kicked_delay < 0) {
++capped_goal_count;
}
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
}
EXPECT_NEAR(constants::GetValues().shooter.upper_limit,
@@ -645,20 +683,20 @@
// Tests that the shooter zeros correctly and goes to a position.
TEST_F(ShooterTest, StartsOnDistal) {
+ SetEnabled(true);
Reinitialize(HallEffectMiddle(constants::GetValues().shooter.pusher_distal));
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::seconds(2))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70.0;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::seconds(2));
// EXPECT_NEAR(0.0, shooter_motor_.GetPosition(), 0.01);
double pos = shooter_motor_plant_.GetAbsolutePosition();
- EXPECT_TRUE(shooter_queue_.goal.FetchLatest());
+ EXPECT_TRUE(shooter_goal_fetcher_.Fetch());
EXPECT_NEAR(
- shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+ shooter_motor_.PowerToPosition(shooter_goal_fetcher_->shot_power),
pos, 0.05);
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
}
@@ -666,21 +704,21 @@
// Tests that the shooter zeros correctly and goes to a position.
TEST_F(ShooterTest, StartsOnProximal) {
+ SetEnabled(true);
Reinitialize(
HallEffectMiddle(constants::GetValues().shooter.pusher_proximal));
- shooter_queue_.goal.MakeWithBuilder().shot_power(70.0).Send();
- while (monotonic_clock::now() <
- monotonic_clock::time_point(chrono::seconds(3))) {
- shooter_motor_plant_.SendPositionMessage();
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 70.0;
+ EXPECT_TRUE(message.Send());
}
+ RunFor(chrono::seconds(3));
// EXPECT_NEAR(0.0, shooter_motor_.GetPosition(), 0.01);
double pos = shooter_motor_plant_.GetAbsolutePosition();
- EXPECT_TRUE(shooter_queue_.goal.FetchLatest());
+ EXPECT_TRUE(shooter_goal_fetcher_.Fetch());
EXPECT_NEAR(
- shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+ shooter_motor_.PowerToPosition(shooter_goal_fetcher_->shot_power),
pos, 0.05);
EXPECT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
}
@@ -690,6 +728,7 @@
::testing::TestWithParam<::std::tuple<bool, bool, bool, double>>> {};
TEST_P(ShooterZeroingTest, AllDisparateStartingZero) {
+ SetEnabled(true);
bool latch = ::std::get<0>(GetParam());
bool brake = ::std::get<1>(GetParam());
bool plunger_back = ::std::get<2>(GetParam());
@@ -699,20 +738,26 @@
// latch, brake, plunger_back, start_pos);
bool initialized = false;
Reinitialize(start_pos);
- shooter_queue_.goal.MakeWithBuilder().shot_power(120.0).Send();
- while (monotonic_clock::now() <
+ {
+ ::aos::Sender<ShooterQueue::Goal>::Message message =
+ shooter_goal_sender_.MakeMessage();
+ message->shot_power = 120.0;
+ EXPECT_TRUE(message.Send());
+ }
+ while (test_event_loop_->monotonic_now() <
monotonic_clock::time_point(chrono::seconds(2))) {
- shooter_motor_plant_.SendPositionMessage(!initialized, plunger_back, latch, brake);
+ shooter_motor_plant_.set_use_passed(!initialized);
+ shooter_motor_plant_.set_plunger_in(plunger_back);
+ shooter_motor_plant_.set_latch_in(latch);
+ shooter_motor_plant_.set_brake_in(brake);
initialized = true;
- shooter_motor_.Iterate();
- shooter_motor_plant_.Simulate();
- SimulateTimestep(true);
+ RunFor(dt());
}
// EXPECT_NEAR(0.0, shooter_motor_.GetPosition(), 0.01);
double pos = shooter_motor_plant_.GetAbsolutePosition();
- EXPECT_TRUE(shooter_queue_.goal.FetchLatest());
+ EXPECT_TRUE(shooter_goal_fetcher_.Fetch());
EXPECT_NEAR(
- shooter_motor_.PowerToPosition(shooter_queue_.goal->shot_power),
+ shooter_motor_.PowerToPosition(shooter_goal_fetcher_->shot_power),
pos, 0.05);
ASSERT_EQ(ShooterMotor::STATE_READY, shooter_motor_.state());
}
diff --git a/y2014/control_loops/shooter/shooter_main.cc b/y2014/control_loops/shooter/shooter_main.cc
index a7b60f9..2da76c3 100644
--- a/y2014/control_loops/shooter/shooter_main.cc
+++ b/y2014/control_loops/shooter/shooter_main.cc
@@ -4,10 +4,13 @@
#include "aos/init.h"
int main() {
- ::aos::Init();
+ ::aos::InitNRT(true);
+
::aos::ShmEventLoop event_loop;
::y2014::control_loops::ShooterMotor shooter(&event_loop);
- shooter.Run();
+
+ event_loop.Run();
+
::aos::Cleanup();
return 0;
}