This tutorial covers what the code that is generated from a .q file looks like.
Each .q
file generates a .cc
and .h
pair that can be #include'd in your c++ code.
We're going to use //frc971/queues:gyro.q
as our example.
.q
files usually start with a package
declaration. The package
declaration directly converts to a set of namespace declarations. So
package frc971.sensors;
generates the namespace definitions
namespace frc971 { namespace sensors { // All of the code for the queue } // namespace sensors } // namespace frc971
Each message declared in the queue generates a class that can be instantiated in your code easily.
For a simple example, lets use the Uid
message in //frc971/queues:gyro.q
:
message Uid { uint32_t uid; };
Let's take a look at the actual class definition that is created. If you ever want to inspect the code that is generated from a .q file, you can take a look in bazel-genfiles
after you build your code. So after running bazel build //frc971/queues:gyro
there will be a bazel-genfiles/frc971/queues/gyro.q.h
and bazel-genfiles/frc971/queues/gyro.q.cc
.
Here's the definition of the Uid
class from bazel-genfiles/frc971/queues/gyro.q.h
(comments mine):
struct Uid : public ::aos::Message { // Used to identify queues uniquely even if they have the same name. enum { kQueueLength = 100, kHash = 0x0837c541 }; // The actual data that we requested be part of the message. uint32_t uid; // Writes the message to a byte buffer. size_t Serialize(char *buffer) const; // Reads the message from a byte buffer. size_t Deserialize(const char *buffer); // Zeroes all of the fields in the message. void Zero(); // Returns the size of message. Not used static size_t Size() { return 4 + ::aos::Message::Size(); } // Prints the contents of the message to a string that is human readable. size_t Print(char *buffer, size_t length) const; // Gets information about this message's type. static const ::aos::MessageType *GetType(); static const ::aos::MessageType *DoGetType(); // Default constructor, zeroes the struct. Uid(); // Value constructor, sets the data at construction. Uid(uint32_t uid_in); bool EqualsNoTime(const Uid &other) const; };
Every queue
declaration in the .q
file creates an aos::Queue
variable that uses the message type given. So the declaration
queue Uid gyro_part_id;
will generate a variable in gyro.q.h
static UNUSED_VARIABLE::aos::Queue<Uid> &gyro_part_id;
which can then be used in any file that includes the header file.
queue_group
declares a set of queues and some associated helpers for them. There are two kinds of queue_groups
, declarations and aliases. Here's an example of a queue_group
definition:
queue_group SuperstructureQueue { implements aos.control_loops.ControlLoop; message Goal { IntakeGoal intake; // Used to identify a position in the planned set of positions on the arm. uint32_t arm_goal_position; // If true, start the grab box sequence. bool grab_box; bool open_claw; bool close_claw; bool deploy_fork; bool hook_release; double voltage_winch; double open_threshold; bool disable_box_correct; bool trajectory_override; }; message Status { // Are all the subsystems zeroed? bool zeroed; // If true, any of the subsystems have aborted. bool estopped; // Status of both intake sides. IntakeSideStatus left_intake; IntakeSideStatus right_intake; ArmStatus arm; double filtered_box_velocity; uint32_t rotation_state; }; message Position { // Values of the series elastic encoders on the left side of the robot from // the rear perspective in radians. IntakeElasticSensors left_intake; // Values of the series elastic encoders on the right side of the robot from // the rear perspective in radians. IntakeElasticSensors right_intake; ArmPosition arm; // Value of the beam breaker sensor. This value is true if the beam is // broken, false if the beam isn't broken. bool claw_beambreak_triggered; // Value of the beambreak sensor detecting when the box has hit the frame // cutout. bool box_back_beambreak_triggered; // Distance to the box in meters. double box_distance; }; message Output { // Voltage sent to the parts on the left side of the intake. IntakeVoltage left_intake; // Voltage sent to the parts on the right side of the intake. IntakeVoltage right_intake; // Voltage sent to the motors on the proximal joint of the arm. double voltage_proximal; // Voltage sent to the motors on the distal joint of the arm. double voltage_distal; // Voltage sent to the hanger. Positive pulls the robot up. double voltage_winch; // Clamped (when true) or unclamped (when false) status sent to the // pneumatic claw on the arm. bool claw_grabbed; // If true, release the arm brakes. bool release_arm_brake; // If true, release the hook bool hook_release; // If true, release the forks bool forks_release; }; queue Goal goal; queue Output output; queue Status status; queue Position position; };
and aliases look like:
queue_group SuperstructureQueue superstructure_queue;
The declaration type creates the definition of the queue group and what messages and queues it contains. The alias type creates a variable with the given name.
This queue group results in the following code in bazel-genfiles/y2018/control_loops/superstructure/superstructure.q.h
struct SuperstructureQueue_Goal : public ::aos::Message { /* ... */ } struct SuperstructureQueue_Output : public ::aos::Message { /* ... */ } struct SuperstructureQueue_Status : public ::aos::Message { /* ... */ } struct SuperstructureQueue_Position : public ::aos::Message { /* ... */ } class SuperstructureQueue : public ::aos::QueueGroup { public: typedef SuperstructureQueue_Goal Goal; ::aos::Queue<SuperstructureQueue_Goal> goal; typedef SuperstructureQueue_Output Output; ::aos::Queue<SuperstructureQueue_Output> output; typedef SuperstructureQueue_Status Status; ::aos::Queue<SuperstructureQueue_Status> status; typedef SuperstructureQueue_Position Position; ::aos::Queue<SuperstructureQueue_Position> position; SuperstructureQueue(const char *name, uint32_t hash, const char *goal_name, const char *output_name, const char *status_name, const char *position_name); };
and a definition of a variable:
static UNUSED_VARIABLE SuperstructureQueue &superstructure_queue;