blob: 6f8e6cc0694a74962b7215ac807b5d0640639cec [file] [log] [blame]
Sabina Leaver7d9220d2021-06-30 20:55:15 -07001// In this file, you can view the tests that are being run to determine
2// if the code works properly in different situations.
3
Parker Schuh18dbbb42017-10-18 21:45:33 -07004#include "frc971/codelab/basic.h"
5
6#include <unistd.h>
7
8#include <chrono>
9#include <memory>
10
Alex Perrycb7da4b2019-08-28 19:35:56 -070011#include "aos/events/shm_event_loop.h"
James Kuszmaul78e29ac2020-07-28 21:07:03 -070012#include "frc971/codelab/basic_goal_generated.h"
13#include "frc971/codelab/basic_output_generated.h"
14#include "frc971/codelab/basic_position_generated.h"
15#include "frc971/codelab/basic_status_generated.h"
James Kuszmaul61750662021-06-21 21:32:33 -070016#include "frc971/control_loops/control_loop_test.h"
Parker Schuh18dbbb42017-10-18 21:45:33 -070017#include "frc971/control_loops/team_number_test_environment.h"
18#include "gtest/gtest.h"
19
20namespace frc971 {
21namespace codelab {
22namespace testing {
23
Austin Schuh9fe68f72019-08-10 19:32:03 -070024namespace chrono = ::std::chrono;
25using aos::monotonic_clock;
26
Parker Schuh18dbbb42017-10-18 21:45:33 -070027// Class which simulates stuff and sends out queue messages with the
28// position.
29class BasicSimulation {
30 public:
Austin Schuh9fe68f72019-08-10 19:32:03 -070031 BasicSimulation(::aos::EventLoop *event_loop, chrono::nanoseconds dt)
32 : event_loop_(event_loop),
Alex Perrycb7da4b2019-08-28 19:35:56 -070033 position_sender_(event_loop_->MakeSender<Position>("/codelab")),
34 status_fetcher_(event_loop_->MakeFetcher<Status>("/codelab")),
35 output_fetcher_(event_loop_->MakeFetcher<Output>("/codelab")) {
Austin Schuh9fe68f72019-08-10 19:32:03 -070036 event_loop_->AddPhasedLoop(
37 [this](int) {
38 // Skip this the first time.
39 if (!first_) {
40 Simulate();
41 }
42 first_ = false;
43 SendPositionMessage();
44 },
45 dt);
46 }
Parker Schuh18dbbb42017-10-18 21:45:33 -070047
48 // Sends a queue message with the position data.
49 void SendPositionMessage() {
Alex Perrycb7da4b2019-08-28 19:35:56 -070050 auto builder = position_sender_.MakeBuilder();
Parker Schuh18dbbb42017-10-18 21:45:33 -070051
Alex Perrycb7da4b2019-08-28 19:35:56 -070052 Position::Builder position_builder = builder.MakeBuilder<Position>();
Parker Schuh18dbbb42017-10-18 21:45:33 -070053
Alex Perrycb7da4b2019-08-28 19:35:56 -070054 position_builder.add_limit_sensor(limit_sensor_);
55
milind1f1dca32021-07-03 13:50:07 -070056 EXPECT_EQ(builder.Send(position_builder.Finish()),
57 aos::RawSender::Error::kOk);
Parker Schuh18dbbb42017-10-18 21:45:33 -070058 }
59
Sabina Leaver7d9220d2021-06-30 20:55:15 -070060 // This is a helper function that is used in the tests to check
61 // if the output of the test is equal to the expected output.
62 // It takes in two expected values and ompares them to the values
63 // it recieves from the code.
Parker Schuh18dbbb42017-10-18 21:45:33 -070064 void VerifyResults(double voltage, bool status) {
Austin Schuh9fe68f72019-08-10 19:32:03 -070065 output_fetcher_.Fetch();
66 status_fetcher_.Fetch();
Parker Schuh18dbbb42017-10-18 21:45:33 -070067
Austin Schuh9fe68f72019-08-10 19:32:03 -070068 ASSERT_TRUE(output_fetcher_.get() != nullptr);
69 ASSERT_TRUE(status_fetcher_.get() != nullptr);
Parker Schuh18dbbb42017-10-18 21:45:33 -070070
Alex Perrycb7da4b2019-08-28 19:35:56 -070071 EXPECT_EQ(output_fetcher_->intake_voltage(), voltage);
72 EXPECT_EQ(status_fetcher_->intake_complete(), status);
Parker Schuh18dbbb42017-10-18 21:45:33 -070073 }
74
75 void set_limit_sensor(bool value) { limit_sensor_ = value; }
76
77 // Simulates basic control loop for a single timestep.
Austin Schuh9fe68f72019-08-10 19:32:03 -070078 void Simulate() { EXPECT_TRUE(output_fetcher_.Fetch()); }
Parker Schuh18dbbb42017-10-18 21:45:33 -070079
80 private:
Austin Schuh9fe68f72019-08-10 19:32:03 -070081 ::aos::EventLoop *event_loop_;
82
Alex Perrycb7da4b2019-08-28 19:35:56 -070083 ::aos::Sender<Position> position_sender_;
84 ::aos::Fetcher<Status> status_fetcher_;
85 ::aos::Fetcher<Output> output_fetcher_;
Austin Schuh9fe68f72019-08-10 19:32:03 -070086
Parker Schuh18dbbb42017-10-18 21:45:33 -070087 bool limit_sensor_ = false;
Austin Schuh9fe68f72019-08-10 19:32:03 -070088
89 bool first_ = true;
Parker Schuh18dbbb42017-10-18 21:45:33 -070090};
91
James Kuszmaul61750662021-06-21 21:32:33 -070092class BasicControlLoopTest : public ::frc971::testing::ControlLoopTest {
Parker Schuh18dbbb42017-10-18 21:45:33 -070093 public:
94 BasicControlLoopTest()
James Kuszmaul61750662021-06-21 21:32:33 -070095 : ::frc971::testing::ControlLoopTest(
Austin Schuhc5fa6d92022-02-25 14:36:28 -080096 aos::configuration::ReadConfig("frc971/codelab/aos_config.json"),
Alex Perrycb7da4b2019-08-28 19:35:56 -070097 chrono::microseconds(5050)),
Austin Schuh5f1cc5c2019-12-01 18:01:11 -080098 test_event_loop_(MakeEventLoop("test")),
Alex Perrycb7da4b2019-08-28 19:35:56 -070099 goal_sender_(test_event_loop_->MakeSender<Goal>("/codelab")),
Austin Schuh9fe68f72019-08-10 19:32:03 -0700100
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800101 basic_event_loop_(MakeEventLoop("basic")),
Alex Perrycb7da4b2019-08-28 19:35:56 -0700102 basic_(basic_event_loop_.get(), "/codelab"),
Austin Schuh9fe68f72019-08-10 19:32:03 -0700103
Austin Schuh5f1cc5c2019-12-01 18:01:11 -0800104 basic_simulation_event_loop_(MakeEventLoop("simulation")),
Austin Schuh9fe68f72019-08-10 19:32:03 -0700105 basic_simulation_(basic_simulation_event_loop_.get(), dt()) {
Parker Schuh18dbbb42017-10-18 21:45:33 -0700106 set_team_id(control_loops::testing::kTeamNumber);
James Kuszmaul78e29ac2020-07-28 21:07:03 -0700107 SetEnabled(true);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700108 }
109
Austin Schuh9fe68f72019-08-10 19:32:03 -0700110 ::std::unique_ptr<::aos::EventLoop> test_event_loop_;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700111 ::aos::Sender<Goal> goal_sender_;
Parker Schuh18dbbb42017-10-18 21:45:33 -0700112
Austin Schuh9fe68f72019-08-10 19:32:03 -0700113 ::std::unique_ptr<::aos::EventLoop> basic_event_loop_;
114 Basic basic_;
Parker Schuh18dbbb42017-10-18 21:45:33 -0700115
Austin Schuh9fe68f72019-08-10 19:32:03 -0700116 ::std::unique_ptr<::aos::EventLoop> basic_simulation_event_loop_;
Parker Schuh18dbbb42017-10-18 21:45:33 -0700117 BasicSimulation basic_simulation_;
118};
119
120// Tests that when the motor has finished intaking it stops.
121TEST_F(BasicControlLoopTest, IntakeLimitTransitionsToTrue) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700122 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700123 auto builder = goal_sender_.MakeBuilder();
124 Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
125 goal_builder.add_intake(true);
milind1f1dca32021-07-03 13:50:07 -0700126 ASSERT_EQ(builder.Send(goal_builder.Finish()),
127 aos::RawSender::Error::kOk);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700128 }
129
Parker Schuh18dbbb42017-10-18 21:45:33 -0700130 basic_simulation_.set_limit_sensor(false);
131
Austin Schuh9fe68f72019-08-10 19:32:03 -0700132 RunFor(dt() * 2);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700133
134 basic_simulation_.VerifyResults(12.0, false);
135
Austin Schuh9fe68f72019-08-10 19:32:03 -0700136 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700137 auto builder = goal_sender_.MakeBuilder();
138 Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
139 goal_builder.add_intake(true);
milind1f1dca32021-07-03 13:50:07 -0700140 ASSERT_EQ(builder.Send(goal_builder.Finish()),
141 aos::RawSender::Error::kOk);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700142 }
Parker Schuh18dbbb42017-10-18 21:45:33 -0700143 basic_simulation_.set_limit_sensor(true);
144
Austin Schuh9fe68f72019-08-10 19:32:03 -0700145 RunFor(dt() * 2);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700146
147 basic_simulation_.VerifyResults(0.0, true);
148}
149
150// Tests that the intake goes on if the sensor is not pressed
151// and intake is requested.
152TEST_F(BasicControlLoopTest, IntakeLimitNotSet) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700153 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700154 auto builder = goal_sender_.MakeBuilder();
155 Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
156 goal_builder.add_intake(true);
milind1f1dca32021-07-03 13:50:07 -0700157 ASSERT_EQ(builder.Send(goal_builder.Finish()),
158 aos::RawSender::Error::kOk);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700159 }
Parker Schuh18dbbb42017-10-18 21:45:33 -0700160 basic_simulation_.set_limit_sensor(false);
161
Austin Schuh9fe68f72019-08-10 19:32:03 -0700162 RunFor(dt() * 2);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700163
164 basic_simulation_.VerifyResults(12.0, false);
165}
166
167// Tests that the intake is off if no intake is requested,
168// even if the limit sensor is off.
169TEST_F(BasicControlLoopTest, NoIntakeLimitNotSet) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700170 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700171 auto builder = goal_sender_.MakeBuilder();
172 Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
173 goal_builder.add_intake(false);
milind1f1dca32021-07-03 13:50:07 -0700174 ASSERT_EQ(builder.Send(goal_builder.Finish()),
175 aos::RawSender::Error::kOk);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700176 }
Parker Schuh18dbbb42017-10-18 21:45:33 -0700177 basic_simulation_.set_limit_sensor(false);
178
Austin Schuh9fe68f72019-08-10 19:32:03 -0700179 RunFor(dt() * 2);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700180
181 basic_simulation_.VerifyResults(0.0, false);
182}
183
184// Tests that the intake is off even if the limit sensor
185// is pressed and intake is requested.
186TEST_F(BasicControlLoopTest, IntakeLimitSet) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700187 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700188 auto builder = goal_sender_.MakeBuilder();
189 Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
190 goal_builder.add_intake(true);
milind1f1dca32021-07-03 13:50:07 -0700191 ASSERT_EQ(builder.Send(goal_builder.Finish()),
192 aos::RawSender::Error::kOk);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700193 }
Parker Schuh18dbbb42017-10-18 21:45:33 -0700194 basic_simulation_.set_limit_sensor(true);
195
Austin Schuh9fe68f72019-08-10 19:32:03 -0700196 RunFor(dt() * 2);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700197
198 basic_simulation_.VerifyResults(0.0, true);
199}
200
201// Tests that the intake is off if no intake is requested,
202TEST_F(BasicControlLoopTest, NoIntakeLimitSet) {
Austin Schuh9fe68f72019-08-10 19:32:03 -0700203 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700204 auto builder = goal_sender_.MakeBuilder();
205 Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
206 goal_builder.add_intake(false);
milind1f1dca32021-07-03 13:50:07 -0700207 ASSERT_EQ(builder.Send(goal_builder.Finish()),
208 aos::RawSender::Error::kOk);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700209 }
Parker Schuh18dbbb42017-10-18 21:45:33 -0700210 basic_simulation_.set_limit_sensor(true);
211
Austin Schuh9fe68f72019-08-10 19:32:03 -0700212 RunFor(dt() * 2);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700213
214 basic_simulation_.VerifyResults(0.0, false);
215}
216
217// Tests that the control loop handles things properly if no goal is set.
218TEST_F(BasicControlLoopTest, NoGoalSet) {
219 basic_simulation_.set_limit_sensor(true);
220
Austin Schuh9fe68f72019-08-10 19:32:03 -0700221 RunFor(dt() * 2);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700222
223 basic_simulation_.VerifyResults(0.0, false);
224}
225
226// Tests that the control loop handles things properly if disabled.
Sabina Leaver7d9220d2021-06-30 20:55:15 -0700227// Note: "output" will be null when the robot is disabled. This is
228// a tricky test to get to pass, it should pass at first but fail
229// as you add more code.
Parker Schuh18dbbb42017-10-18 21:45:33 -0700230TEST_F(BasicControlLoopTest, Disabled) {
231 basic_simulation_.set_limit_sensor(true);
232
Austin Schuh9fe68f72019-08-10 19:32:03 -0700233 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700234 auto builder = goal_sender_.MakeBuilder();
235 Goal::Builder goal_builder = builder.MakeBuilder<Goal>();
236 goal_builder.add_intake(true);
milind1f1dca32021-07-03 13:50:07 -0700237 ASSERT_EQ(builder.Send(goal_builder.Finish()),
238 aos::RawSender::Error::kOk);
Austin Schuh9fe68f72019-08-10 19:32:03 -0700239 }
Parker Schuh18dbbb42017-10-18 21:45:33 -0700240
Austin Schuh9fe68f72019-08-10 19:32:03 -0700241 SetEnabled(false);
242 RunFor(dt() * 2);
Parker Schuh18dbbb42017-10-18 21:45:33 -0700243
244 basic_simulation_.VerifyResults(0.0, false);
245}
246
247} // namespace testing
248} // namespace codelab
249} // namespace frc971