Convert aos over to flatbuffers
Everything builds, and all the tests pass. I suspect that some entries
are missing from the config files, but those will be found pretty
quickly on startup.
There is no logging or live introspection of queue messages.
Change-Id: I496ee01ed68f202c7851bed7e8786cee30df29f5
diff --git a/y2016/control_loops/shooter/BUILD b/y2016/control_loops/shooter/BUILD
index 8938a2b..794c4fc 100644
--- a/y2016/control_loops/shooter/BUILD
+++ b/y2016/control_loops/shooter/BUILD
@@ -1,16 +1,37 @@
package(default_visibility = ["//visibility:public"])
-load("//aos/build:queues.bzl", "queue_library")
+load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")
-queue_library(
- name = "shooter_queue",
+flatbuffer_cc_library(
+ name = "shooter_goal_fbs",
srcs = [
- "shooter.q",
+ "shooter_goal.fbs",
],
- deps = [
- "//aos/controls:control_loop_queues",
- "//frc971/control_loops:queues",
+ gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+ name = "shooter_position_fbs",
+ srcs = [
+ "shooter_position.fbs",
],
+ gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+ name = "shooter_output_fbs",
+ srcs = [
+ "shooter_output.fbs",
+ ],
+ gen_reflections = 1,
+)
+
+flatbuffer_cc_library(
+ name = "shooter_status_fbs",
+ srcs = [
+ "shooter_status.fbs",
+ ],
+ gen_reflections = 1,
)
genrule(
@@ -52,8 +73,11 @@
"shooter.h",
],
deps = [
+ ":shooter_goal_fbs",
+ ":shooter_output_fbs",
":shooter_plants",
- ":shooter_queue",
+ ":shooter_position_fbs",
+ ":shooter_status_fbs",
"//aos/controls:control_loop",
],
)
@@ -63,10 +87,13 @@
srcs = [
"shooter_lib_test.cc",
],
+ data = ["//y2016:config.json"],
deps = [
+ ":shooter_goal_fbs",
":shooter_lib",
- ":shooter_queue",
- "//aos:queues",
+ ":shooter_output_fbs",
+ ":shooter_position_fbs",
+ ":shooter_status_fbs",
"//aos/controls:control_loop_test",
"//aos/testing:googletest",
"//frc971/control_loops:state_feedback_loop",
@@ -80,9 +107,12 @@
"shooter_main.cc",
],
deps = [
+ ":shooter_goal_fbs",
":shooter_lib",
- ":shooter_queue",
+ ":shooter_output_fbs",
+ ":shooter_position_fbs",
+ ":shooter_status_fbs",
"//aos:init",
- "//aos/events:shm-event-loop",
+ "//aos/events:shm_event_loop",
],
)
diff --git a/y2016/control_loops/shooter/shooter.cc b/y2016/control_loops/shooter/shooter.cc
index bf527ec..5156a61 100644
--- a/y2016/control_loops/shooter/shooter.cc
+++ b/y2016/control_loops/shooter/shooter.cc
@@ -2,10 +2,7 @@
#include <chrono>
-#include "aos/controls/control_loops.q.h"
#include "aos/logging/logging.h"
-#include "aos/logging/queue_logging.h"
-
#include "y2016/control_loops/shooter/shooter_plant.h"
namespace y2016 {
@@ -49,80 +46,99 @@
loop_->Update(disabled);
}
-void ShooterSide::SetStatus(ShooterSideStatus *status) {
+flatbuffers::Offset<ShooterSideStatus> ShooterSide::SetStatus(
+ flatbuffers::FlatBufferBuilder *fbb) {
+ ShooterSideStatus::Builder shooter_side_status_builder(*fbb);
// Compute the oldest point in the history.
const int oldest_history_position =
((history_position_ == 0) ? kHistoryLength : history_position_) - 1;
// Compute the distance moved over that time period.
- status->avg_angular_velocity =
+ const double avg_angular_velocity =
(history_[oldest_history_position] - history_[history_position_]) /
(::aos::time::DurationInSeconds(::aos::controls::kLoopFrequency) *
static_cast<double>(kHistoryLength - 1));
+ shooter_side_status_builder.add_avg_angular_velocity(avg_angular_velocity);
- status->angular_velocity = loop_->X_hat(1, 0);
+ shooter_side_status_builder.add_angular_velocity(loop_->X_hat(1, 0));
// Ready if average angular velocity is close to the goal.
- status->ready = (std::abs(loop_->next_R(1, 0) -
- status->avg_angular_velocity) < kTolerance &&
- loop_->next_R(1, 0) > 1.0);
+ shooter_side_status_builder.add_ready(
+ (std::abs(loop_->next_R(1, 0) - avg_angular_velocity) < kTolerance &&
+ loop_->next_R(1, 0) > 1.0));
+
+ return shooter_side_status_builder.Finish();
}
Shooter::Shooter(::aos::EventLoop *event_loop, const ::std::string &name)
- : aos::controls::ControlLoop<ShooterQueue>(event_loop, name),
+ : aos::controls::ControlLoop<Goal, Position, Status, Output>(event_loop,
+ name),
shots_(0),
last_pre_shot_timeout_(::aos::monotonic_clock::min_time) {}
-void Shooter::RunIteration(const ShooterQueue::Goal *goal,
- const ShooterQueue::Position *position,
- ShooterQueue::Output *output,
- ShooterQueue::Status *status) {
+void Shooter::RunIteration(const Goal *goal, const Position *position,
+ aos::Sender<Output>::Builder *output,
+ aos::Sender<Status>::Builder *status) {
const ::aos::monotonic_clock::time_point monotonic_now =
event_loop()->monotonic_now();
if (goal) {
// Update position/goal for our two shooter sides.
- left_.set_goal(goal->angular_velocity);
- right_.set_goal(goal->angular_velocity);
-
- // Turn the lights on if we are supposed to spin.
- if (output) {
- if (::std::abs(goal->angular_velocity) > 0.0) {
- output->lights_on = true;
- if (goal->shooting_forwards) {
- output->forwards_flashlight = true;
- output->backwards_flashlight = false;
- } else {
- output->forwards_flashlight = false;
- output->backwards_flashlight = true;
- }
- }
- if (goal->force_lights_on) {
- output->lights_on = true;
- }
- }
+ left_.set_goal(goal->angular_velocity());
+ right_.set_goal(goal->angular_velocity());
}
- left_.set_position(position->theta_left);
- right_.set_position(position->theta_right);
+ left_.set_position(position->theta_left());
+ right_.set_position(position->theta_right());
left_.Update(output == nullptr);
right_.Update(output == nullptr);
- left_.SetStatus(&status->left);
- right_.SetStatus(&status->right);
- status->ready = (status->left.ready && status->right.ready);
+ flatbuffers::Offset<ShooterSideStatus> left_status_offset =
+ left_.SetStatus(status->fbb());
+ flatbuffers::Offset<ShooterSideStatus> right_status_offset =
+ right_.SetStatus(status->fbb());
+
+ ShooterSideStatus *left_status =
+ GetMutableTemporaryPointer(*status->fbb(), left_status_offset);
+ ShooterSideStatus *right_status =
+ GetMutableTemporaryPointer(*status->fbb(), right_status_offset);
+
+ const bool ready = (left_status->ready() && right_status->ready());
+
+ Status::Builder status_builder = status->MakeBuilder<Status>();
+ status_builder.add_ready((left_status->ready() && right_status->ready()));
+ status_builder.add_left(left_status_offset);
+ status_builder.add_right(right_status_offset);
if (output) {
- output->voltage_left = left_.voltage();
- output->voltage_right = right_.voltage();
+ Output::Builder output_builder = output->MakeBuilder<Output>();
+ output_builder.add_voltage_left(left_.voltage());
+ output_builder.add_voltage_right(right_.voltage());
+ // Turn the lights on if we are supposed to spin.
if (goal) {
+ bool lights_on = false;
+ if (::std::abs(goal->angular_velocity()) > 0.0) {
+ lights_on = true;
+ if (goal->shooting_forwards()) {
+ output_builder.add_forwards_flashlight(true);
+ output_builder.add_backwards_flashlight(false);
+ } else {
+ output_builder.add_forwards_flashlight(false);
+ output_builder.add_backwards_flashlight(true);
+ }
+ }
+ if (goal->force_lights_on()) {
+ lights_on = true;
+ }
+ output_builder.add_lights_on(lights_on);
+
bool shoot = false;
switch (state_) {
case ShooterLatchState::PASS_THROUGH:
- if (goal->push_to_shooter) {
- if (::std::abs(goal->angular_velocity) > 10) {
- if (status->ready) {
+ if (goal->push_to_shooter()) {
+ if (::std::abs(goal->angular_velocity()) > 10) {
+ if (ready) {
state_ = ShooterLatchState::WAITING_FOR_SPINDOWN;
shoot = true;
}
@@ -134,22 +150,22 @@
break;
case ShooterLatchState::WAITING_FOR_SPINDOWN:
shoot = true;
- if (left_.velocity() < goal->angular_velocity * 0.9 ||
- right_.velocity() < goal->angular_velocity * 0.9) {
+ if (left_.velocity() < goal->angular_velocity() * 0.9 ||
+ right_.velocity() < goal->angular_velocity() * 0.9) {
state_ = ShooterLatchState::WAITING_FOR_SPINUP;
}
- if (::std::abs(goal->angular_velocity) < 10 ||
+ if (::std::abs(goal->angular_velocity()) < 10 ||
last_pre_shot_timeout_ < monotonic_now) {
state_ = ShooterLatchState::INCREMENT_SHOT_COUNT;
}
break;
case ShooterLatchState::WAITING_FOR_SPINUP:
shoot = true;
- if (left_.velocity() > goal->angular_velocity * 0.95 &&
- right_.velocity() > goal->angular_velocity * 0.95) {
+ if (left_.velocity() > goal->angular_velocity() * 0.95 &&
+ right_.velocity() > goal->angular_velocity() * 0.95) {
state_ = ShooterLatchState::INCREMENT_SHOT_COUNT;
}
- if (::std::abs(goal->angular_velocity) < 10 ||
+ if (::std::abs(goal->angular_velocity()) < 10 ||
last_pre_shot_timeout_ < monotonic_now) {
state_ = ShooterLatchState::INCREMENT_SHOT_COUNT;
}
@@ -160,18 +176,22 @@
break;
case ShooterLatchState::WAITING_FOR_SHOT_NEGEDGE:
shoot = true;
- if (!goal->push_to_shooter) {
+ if (!goal->push_to_shooter()) {
state_ = ShooterLatchState::PASS_THROUGH;
}
break;
}
- output->clamp_open = goal->clamp_open;
- output->push_to_shooter = shoot;
+ output_builder.add_clamp_open(goal->clamp_open());
+ output_builder.add_push_to_shooter(shoot);
}
+
+ output->Send(output_builder.Finish());
}
- status->shots = shots_;
+ status_builder.add_shots(shots_);
+
+ status->Send(status_builder.Finish());
}
} // namespace shooter
diff --git a/y2016/control_loops/shooter/shooter.h b/y2016/control_loops/shooter/shooter.h
index 9e6968f..07fee84 100644
--- a/y2016/control_loops/shooter/shooter.h
+++ b/y2016/control_loops/shooter/shooter.h
@@ -4,11 +4,14 @@
#include <memory>
#include "aos/controls/control_loop.h"
-#include "aos/events/event-loop.h"
+#include "aos/events/event_loop.h"
#include "aos/time/time.h"
#include "frc971/control_loops/state_feedback_loop.h"
-#include "y2016/control_loops/shooter/shooter.q.h"
+#include "y2016/control_loops/shooter/shooter_goal_generated.h"
#include "y2016/control_loops/shooter/shooter_integral_plant.h"
+#include "y2016/control_loops/shooter/shooter_output_generated.h"
+#include "y2016/control_loops/shooter/shooter_position_generated.h"
+#include "y2016/control_loops/shooter/shooter_status_generated.h"
namespace y2016 {
namespace control_loops {
@@ -28,7 +31,8 @@
void set_position(double current_position);
// Populates the status structure.
- void SetStatus(ShooterSideStatus *status);
+ flatbuffers::Offset<ShooterSideStatus> SetStatus(
+ flatbuffers::FlatBufferBuilder *fbb);
// Returns the control loop calculated voltage.
double voltage() const;
@@ -53,11 +57,11 @@
DISALLOW_COPY_AND_ASSIGN(ShooterSide);
};
-class Shooter : public ::aos::controls::ControlLoop<ShooterQueue> {
+class Shooter
+ : public ::aos::controls::ControlLoop<Goal, Position, Status, Output> {
public:
- explicit Shooter(
- ::aos::EventLoop *event_loop,
- const ::std::string &name = ".y2016.control_loops.shooter.shooter_queue");
+ explicit Shooter(::aos::EventLoop *event_loop,
+ const ::std::string &name = "/shooter");
enum class ShooterLatchState {
// Any shoot commands will be passed through without modification.
@@ -73,10 +77,9 @@
};
protected:
- void RunIteration(const ShooterQueue::Goal *goal,
- const ShooterQueue::Position *position,
- ShooterQueue::Output *output,
- ShooterQueue::Status *status) override;
+ void RunIteration(const Goal *goal, const Position *position,
+ aos::Sender<Output>::Builder *output,
+ aos::Sender<Status>::Builder *status) override;
private:
ShooterSide left_, right_;
diff --git a/y2016/control_loops/shooter/shooter.q b/y2016/control_loops/shooter/shooter.q
deleted file mode 100644
index 583b762..0000000
--- a/y2016/control_loops/shooter/shooter.q
+++ /dev/null
@@ -1,81 +0,0 @@
-package y2016.control_loops.shooter;
-
-import "aos/controls/control_loops.q";
-import "frc971/control_loops/control_loops.q";
-
-struct ShooterSideStatus {
- // True if the shooter side is up to speed and stable.
- bool ready;
- // The current average velocity in radians/second.
- double avg_angular_velocity;
- // The current instantaneous filtered velocity in radians/second.
- double angular_velocity;
-};
-
-// Published on ".y2016.control_loops.shooter.shooter_queue"
-queue_group ShooterQueue {
- implements aos.control_loops.ControlLoop;
-
- // All angles are in radians, and angular velocities are in radians/second.
- // For all angular velocities, positive is shooting the ball out of the robot.
-
- message Goal {
- // Angular velocity goals in radians/second.
- double angular_velocity;
-
- bool clamp_open; // True to release our clamp on the ball.
- // True to push the ball into the shooter.
- // If we are in the act of shooting with a goal velocity != 0, wait until it
- // is up to speed, push the ball into the shooter, and then wait until it
- // spins up and down before letting the piston be released.
- bool push_to_shooter;
-
- // Forces the lights on.
- bool force_lights_on;
-
- // If true, the robot is shooting forwards.
- bool shooting_forwards;
- };
-
- message Position {
- // Wheel angle in radians/second.
- double theta_left;
- double theta_right;
- };
-
- message Status {
- // Left side status.
- ShooterSideStatus left;
- // Right side status.
- ShooterSideStatus right;
-
- // True if the shooter is ready. It is better to compare the velocities
- // directly so there isn't confusion on if the goal is up to date.
- bool ready;
-
- // The number of shots that have been fired since the start of the shooter
- // control loop.
- uint32_t shots;
- };
-
- message Output {
- // Voltage in volts of the left and right shooter motors.
- double voltage_left;
- double voltage_right;
-
- // See comments on the identical fields in Goal for details.
- bool clamp_open;
- bool push_to_shooter;
-
- // If true, the lights are on.
- bool lights_on;
-
- bool forwards_flashlight;
- bool backwards_flashlight;
- };
-
- queue Goal goal;
- queue Position position;
- queue Output output;
- queue Status status;
-};
diff --git a/y2016/control_loops/shooter/shooter_goal.fbs b/y2016/control_loops/shooter/shooter_goal.fbs
new file mode 100644
index 0000000..f041503
--- /dev/null
+++ b/y2016/control_loops/shooter/shooter_goal.fbs
@@ -0,0 +1,23 @@
+namespace y2016.control_loops.shooter;
+
+// All angles are in radians, and angular velocities are in radians/second.
+// For all angular velocities, positive is shooting the ball out of the robot.
+table Goal {
+ // Angular velocity goals in radians/second.
+ angular_velocity:double;
+
+ clamp_open:bool; // True to release our clamp on the ball.
+ // True to push the ball into the shooter.
+ // If we are in the act of shooting with a goal velocity != 0, wait until it
+ // is up to speed, push the ball into the shooter, and then wait until it
+ // spins up and down before letting the piston be released.
+ push_to_shooter:bool;
+
+ // Forces the lights on.
+ force_lights_on:bool;
+
+ // If true, the robot is shooting forwards.
+ shooting_forwards:bool;
+}
+
+root_type Goal;
diff --git a/y2016/control_loops/shooter/shooter_lib_test.cc b/y2016/control_loops/shooter/shooter_lib_test.cc
index 30b5166..b432049 100644
--- a/y2016/control_loops/shooter/shooter_lib_test.cc
+++ b/y2016/control_loops/shooter/shooter_lib_test.cc
@@ -5,13 +5,15 @@
#include <chrono>
#include <memory>
-#include "gtest/gtest.h"
-#include "aos/queue.h"
#include "aos/controls/control_loop_test.h"
#include "frc971/control_loops/team_number_test_environment.h"
-#include "y2016/control_loops/shooter/shooter.q.h"
+#include "gtest/gtest.h"
#include "y2016/control_loops/shooter/shooter.h"
+#include "y2016/control_loops/shooter/shooter_goal_generated.h"
+#include "y2016/control_loops/shooter/shooter_output_generated.h"
#include "y2016/control_loops/shooter/shooter_plant.h"
+#include "y2016/control_loops/shooter/shooter_position_generated.h"
+#include "y2016/control_loops/shooter/shooter_status_generated.h"
using ::frc971::control_loops::testing::kTeamNumber;
@@ -50,11 +52,8 @@
// Constructs a shooter simulation.
ShooterSimulation(::aos::EventLoop *event_loop, chrono::nanoseconds dt)
: event_loop_(event_loop),
- shooter_position_sender_(
- event_loop_->MakeSender<ShooterQueue::Position>(
- ".y2016.control_loops.shooter.shooter_queue.position")),
- shooter_output_fetcher_(event_loop_->MakeFetcher<ShooterQueue::Output>(
- ".y2016.control_loops.shooter.shooter_queue.output")),
+ shooter_position_sender_(event_loop_->MakeSender<Position>("/shooter")),
+ shooter_output_fetcher_(event_loop_->MakeFetcher<Output>("/shooter")),
shooter_plant_left_(new ShooterPlant(
::y2016::control_loops::shooter::MakeShooterPlant())),
shooter_plant_right_(new ShooterPlant(
@@ -73,12 +72,14 @@
// Sends a queue message with the position of the shooter.
void SendPositionMessage() {
- ::aos::Sender<ShooterQueue::Position>::Message position =
- shooter_position_sender_.MakeMessage();
+ ::aos::Sender<Position>::Builder builder =
+ shooter_position_sender_.MakeBuilder();
- position->theta_left = shooter_plant_left_->Y(0, 0);
- position->theta_right = shooter_plant_right_->Y(0, 0);
- position.Send();
+ Position::Builder position_builder = builder.MakeBuilder<Position>();
+
+ position_builder.add_theta_left(shooter_plant_left_->Y(0, 0));
+ position_builder.add_theta_right(shooter_plant_right_->Y(0, 0));
+ builder.Send(position_builder.Finish());
}
void set_left_voltage_offset(double voltage_offset) {
@@ -95,9 +96,9 @@
::Eigen::Matrix<double, 1, 1> U_left;
::Eigen::Matrix<double, 1, 1> U_right;
- U_left(0, 0) = shooter_output_fetcher_->voltage_left +
+ U_left(0, 0) = shooter_output_fetcher_->voltage_left() +
shooter_plant_left_->voltage_offset();
- U_right(0, 0) = shooter_output_fetcher_->voltage_right +
+ U_right(0, 0) = shooter_output_fetcher_->voltage_right() +
shooter_plant_right_->voltage_offset();
shooter_plant_left_->Update(U_left);
@@ -107,8 +108,8 @@
private:
::aos::EventLoop *event_loop_;
- ::aos::Sender<ShooterQueue::Position> shooter_position_sender_;
- ::aos::Fetcher<ShooterQueue::Output> shooter_output_fetcher_;
+ ::aos::Sender<Position> shooter_position_sender_;
+ ::aos::Fetcher<Output> shooter_output_fetcher_;
::std::unique_ptr<ShooterPlant> shooter_plant_left_, shooter_plant_right_;
@@ -118,18 +119,16 @@
class ShooterTest : public ::aos::testing::ControlLoopTest {
protected:
ShooterTest()
- : ::aos::testing::ControlLoopTest(chrono::microseconds(5000)),
+ : ::aos::testing::ControlLoopTest(
+ aos::configuration::ReadConfig("y2016/config.json"),
+ chrono::microseconds(5000)),
test_event_loop_(MakeEventLoop()),
- shooter_goal_fetcher_(test_event_loop_->MakeFetcher<ShooterQueue::Goal>(
- ".y2016.control_loops.shooter.shooter_queue.goal")),
- shooter_goal_sender_(test_event_loop_->MakeSender<ShooterQueue::Goal>(
- ".y2016.control_loops.shooter.shooter_queue.goal")),
+ shooter_goal_fetcher_(test_event_loop_->MakeFetcher<Goal>("/shooter")),
+ shooter_goal_sender_(test_event_loop_->MakeSender<Goal>("/shooter")),
shooter_status_fetcher_(
- test_event_loop_->MakeFetcher<ShooterQueue::Status>(
- ".y2016.control_loops.shooter.shooter_queue.status")),
+ test_event_loop_->MakeFetcher<Status>("/shooter")),
shooter_output_fetcher_(
- test_event_loop_->MakeFetcher<ShooterQueue::Output>(
- ".y2016.control_loops.shooter.shooter_queue.output")),
+ test_event_loop_->MakeFetcher<Output>("/shooter")),
shooter_event_loop_(MakeEventLoop()),
shooter_(shooter_event_loop_.get()),
shooter_plant_event_loop_(MakeEventLoop()),
@@ -144,22 +143,22 @@
EXPECT_TRUE(shooter_goal_fetcher_.get() != nullptr);
EXPECT_TRUE(shooter_status_fetcher_.get() != nullptr);
- EXPECT_NEAR(shooter_goal_fetcher_->angular_velocity,
- shooter_status_fetcher_->left.angular_velocity, 10.0);
- EXPECT_NEAR(shooter_goal_fetcher_->angular_velocity,
- shooter_status_fetcher_->right.angular_velocity, 10.0);
+ EXPECT_NEAR(shooter_goal_fetcher_->angular_velocity(),
+ shooter_status_fetcher_->left()->angular_velocity(), 10.0);
+ EXPECT_NEAR(shooter_goal_fetcher_->angular_velocity(),
+ shooter_status_fetcher_->right()->angular_velocity(), 10.0);
- EXPECT_NEAR(shooter_goal_fetcher_->angular_velocity,
- shooter_status_fetcher_->left.avg_angular_velocity, 10.0);
- EXPECT_NEAR(shooter_goal_fetcher_->angular_velocity,
- shooter_status_fetcher_->right.avg_angular_velocity, 10.0);
+ EXPECT_NEAR(shooter_goal_fetcher_->angular_velocity(),
+ shooter_status_fetcher_->left()->avg_angular_velocity(), 10.0);
+ EXPECT_NEAR(shooter_goal_fetcher_->angular_velocity(),
+ shooter_status_fetcher_->right()->avg_angular_velocity(), 10.0);
}
::std::unique_ptr<::aos::EventLoop> test_event_loop_;
- ::aos::Fetcher<ShooterQueue::Goal> shooter_goal_fetcher_;
- ::aos::Sender<ShooterQueue::Goal> shooter_goal_sender_;
- ::aos::Fetcher<ShooterQueue::Status> shooter_status_fetcher_;
- ::aos::Fetcher<ShooterQueue::Output> shooter_output_fetcher_;
+ ::aos::Fetcher<Goal> shooter_goal_fetcher_;
+ ::aos::Sender<Goal> shooter_goal_sender_;
+ ::aos::Fetcher<Status> shooter_status_fetcher_;
+ ::aos::Fetcher<Output> shooter_output_fetcher_;
// Create a control loop and simulation.
::std::unique_ptr<::aos::EventLoop> shooter_event_loop_;
@@ -173,9 +172,10 @@
TEST_F(ShooterTest, DoesNothing) {
SetEnabled(true);
{
- auto message = shooter_goal_sender_.MakeMessage();
- message->angular_velocity = 0.0;
- EXPECT_TRUE(message.Send());
+ auto builder = shooter_goal_sender_.MakeBuilder();
+ Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_angular_velocity(0.0);
+ EXPECT_TRUE(builder.Send(goal_builder.Finish()));
}
RunFor(dt());
@@ -183,8 +183,8 @@
VerifyNearGoal();
EXPECT_TRUE(shooter_output_fetcher_.Fetch());
- EXPECT_EQ(shooter_output_fetcher_->voltage_left, 0.0);
- EXPECT_EQ(shooter_output_fetcher_->voltage_right, 0.0);
+ EXPECT_EQ(shooter_output_fetcher_->voltage_left(), 0.0);
+ EXPECT_EQ(shooter_output_fetcher_->voltage_right(), 0.0);
}
// Tests that the shooter spins up to speed and that it then spins down
@@ -193,32 +193,34 @@
SetEnabled(true);
// Spin up.
{
- auto message = shooter_goal_sender_.MakeMessage();
- message->angular_velocity = 450.0;
- EXPECT_TRUE(message.Send());
+ auto builder = shooter_goal_sender_.MakeBuilder();
+ Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_angular_velocity(450.0);
+ EXPECT_TRUE(builder.Send(goal_builder.Finish()));
}
RunFor(chrono::seconds(1));
VerifyNearGoal();
shooter_status_fetcher_.Fetch();
- EXPECT_TRUE(shooter_status_fetcher_->ready);
+ EXPECT_TRUE(shooter_status_fetcher_->ready());
{
- auto message = shooter_goal_sender_.MakeMessage();
- message->angular_velocity = 0.0;
- EXPECT_TRUE(message.Send());
+ auto builder = shooter_goal_sender_.MakeBuilder();
+ Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_angular_velocity(0.0);
+ EXPECT_TRUE(builder.Send(goal_builder.Finish()));
}
// Make sure we don't apply voltage on spin-down.
RunFor(dt());
EXPECT_TRUE(shooter_output_fetcher_.Fetch());
- EXPECT_EQ(0.0, shooter_output_fetcher_->voltage_left);
- EXPECT_EQ(0.0, shooter_output_fetcher_->voltage_right);
+ EXPECT_EQ(0.0, shooter_output_fetcher_->voltage_left());
+ EXPECT_EQ(0.0, shooter_output_fetcher_->voltage_right());
// Continue to stop.
RunFor(chrono::seconds(5));
EXPECT_TRUE(shooter_output_fetcher_.Fetch());
- EXPECT_EQ(0.0, shooter_output_fetcher_->voltage_left);
- EXPECT_EQ(0.0, shooter_output_fetcher_->voltage_right);
+ EXPECT_EQ(0.0, shooter_output_fetcher_->voltage_left());
+ EXPECT_EQ(0.0, shooter_output_fetcher_->voltage_right());
}
// Tests that the shooter doesn't say it is ready if one side isn't up to speed.
@@ -228,9 +230,10 @@
SetEnabled(true);
// Spin up.
{
- auto message = shooter_goal_sender_.MakeMessage();
- message->angular_velocity = 20.0;
- EXPECT_TRUE(message.Send());
+ auto builder = shooter_goal_sender_.MakeBuilder();
+ Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_angular_velocity(20.0);
+ EXPECT_TRUE(builder.Send(goal_builder.Finish()));
}
// Cause problems by adding a voltage error on one side.
shooter_plant_.set_right_voltage_offset(-4.0);
@@ -243,9 +246,9 @@
EXPECT_TRUE(shooter_status_fetcher_.get() != nullptr);
// Left should be up to speed, right shouldn't.
- EXPECT_TRUE(shooter_status_fetcher_->left.ready);
- EXPECT_FALSE(shooter_status_fetcher_->right.ready);
- EXPECT_FALSE(shooter_status_fetcher_->ready);
+ EXPECT_TRUE(shooter_status_fetcher_->left()->ready());
+ EXPECT_FALSE(shooter_status_fetcher_->right()->ready());
+ EXPECT_FALSE(shooter_status_fetcher_->ready());
RunFor(chrono::seconds(5));
@@ -256,22 +259,23 @@
EXPECT_TRUE(shooter_status_fetcher_.get() != nullptr);
// Both should be up to speed.
- EXPECT_TRUE(shooter_status_fetcher_->left.ready);
- EXPECT_TRUE(shooter_status_fetcher_->right.ready);
- EXPECT_TRUE(shooter_status_fetcher_->ready);
+ EXPECT_TRUE(shooter_status_fetcher_->left()->ready());
+ EXPECT_TRUE(shooter_status_fetcher_->right()->ready());
+ EXPECT_TRUE(shooter_status_fetcher_->ready());
}
// Tests that the shooter can spin up nicely after being disabled for a while.
TEST_F(ShooterTest, Disabled) {
{
- auto message = shooter_goal_sender_.MakeMessage();
- message->angular_velocity = 200.0;
- EXPECT_TRUE(message.Send());
+ auto builder = shooter_goal_sender_.MakeBuilder();
+ Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
+ goal_builder.add_angular_velocity(200.0);
+ EXPECT_TRUE(builder.Send(goal_builder.Finish()));
}
RunFor(chrono::seconds(5));
EXPECT_TRUE(shooter_output_fetcher_.Fetch());
- EXPECT_EQ(shooter_output_fetcher_->voltage_left, 0.0);
- EXPECT_EQ(shooter_output_fetcher_->voltage_right, 0.0);
+ EXPECT_EQ(shooter_output_fetcher_->voltage_left(), 0.0);
+ EXPECT_EQ(shooter_output_fetcher_->voltage_right(), 0.0);
SetEnabled(true);
RunFor(chrono::seconds(5));
diff --git a/y2016/control_loops/shooter/shooter_main.cc b/y2016/control_loops/shooter/shooter_main.cc
index b9737fd..6e46114 100644
--- a/y2016/control_loops/shooter/shooter_main.cc
+++ b/y2016/control_loops/shooter/shooter_main.cc
@@ -1,12 +1,15 @@
#include "y2016/control_loops/shooter/shooter.h"
-#include "aos/events/shm-event-loop.h"
+#include "aos/events/shm_event_loop.h"
#include "aos/init.h"
int main() {
::aos::InitNRT(true);
- ::aos::ShmEventLoop event_loop;
+ aos::FlatbufferDetachedBuffer<aos::Configuration> config =
+ aos::configuration::ReadConfig("config.json");
+
+ ::aos::ShmEventLoop event_loop(&config.message());
::y2016::control_loops::shooter::Shooter shooter(&event_loop);
event_loop.Run();
diff --git a/y2016/control_loops/shooter/shooter_output.fbs b/y2016/control_loops/shooter/shooter_output.fbs
new file mode 100644
index 0000000..6d7fcdf
--- /dev/null
+++ b/y2016/control_loops/shooter/shooter_output.fbs
@@ -0,0 +1,19 @@
+namespace y2016.control_loops.shooter;
+
+table Output {
+ // Voltage in volts of the left and right shooter motors.
+ voltage_left:double;
+ voltage_right:double;
+
+ // See comments on the identical fields in Goal for details.
+ clamp_open:bool;
+ push_to_shooter:bool;
+
+ // If true, the lights are on.
+ lights_on:bool;
+
+ forwards_flashlight:bool;
+ backwards_flashlight:bool;
+}
+
+root_type Output;
diff --git a/y2016/control_loops/shooter/shooter_position.fbs b/y2016/control_loops/shooter/shooter_position.fbs
new file mode 100644
index 0000000..d97268c
--- /dev/null
+++ b/y2016/control_loops/shooter/shooter_position.fbs
@@ -0,0 +1,11 @@
+namespace y2016.control_loops.shooter;
+
+// All angles are in radians, and angular velocities are in radians/second.
+// For all angular velocities, positive is shooting the ball out of the robot.
+table Position {
+ // Wheel angle in radians/second.
+ theta_left:double;
+ theta_right:double;
+}
+
+root_type Position;
diff --git a/y2016/control_loops/shooter/shooter_status.fbs b/y2016/control_loops/shooter/shooter_status.fbs
new file mode 100644
index 0000000..6f6262b
--- /dev/null
+++ b/y2016/control_loops/shooter/shooter_status.fbs
@@ -0,0 +1,27 @@
+namespace y2016.control_loops.shooter;
+
+table ShooterSideStatus {
+ // True if the shooter side is up to speed and stable.
+ ready:bool;
+ // The current average velocity in radians/second.
+ avg_angular_velocity:double;
+ // The current instantaneous filtered velocity in radians/second.
+ angular_velocity:double;
+}
+
+table Status {
+ // Left side status.
+ left:ShooterSideStatus;
+ // Right side status.
+ right:ShooterSideStatus;
+
+ // True if the shooter is ready. It is better to compare the velocities
+ // directly so there isn't confusion on if the goal is up to date.
+ ready:bool;
+
+ // The number of shots that have been fired since the start of the shooter
+ // control loop.
+ shots:uint;
+}
+
+root_type Status;