blob: 2dc8dea25ba147e1ad3d46e9adcf6039278419d5 [file] [log] [blame]
Parker Schuh18dbbb42017-10-18 21:45:33 -07001#include "frc971/codelab/basic.h"
2
3#include <unistd.h>
4
5#include <chrono>
6#include <memory>
7
John Park33858a32018-09-28 23:05:48 -07008#include "aos/controls/control_loop_test.h"
Austin Schuh55a13dc2019-01-27 22:39:03 -08009#include "aos/events/shm-event-loop.h"
John Park33858a32018-09-28 23:05:48 -070010#include "aos/queue.h"
Parker Schuh18dbbb42017-10-18 21:45:33 -070011#include "frc971/codelab/basic.q.h"
12#include "frc971/control_loops/team_number_test_environment.h"
13#include "gtest/gtest.h"
14
15namespace frc971 {
16namespace codelab {
17namespace testing {
18
19// Class which simulates stuff and sends out queue messages with the
20// position.
21class BasicSimulation {
22 public:
23 BasicSimulation()
Austin Schuh7660fcd2019-01-27 13:07:52 -080024 : basic_queue_(".frc971.codelab.basic_queue",
Parker Schuh18dbbb42017-10-18 21:45:33 -070025 ".frc971.codelab.basic_queue.goal",
26 ".frc971.codelab.basic_queue.position",
27 ".frc971.codelab.basic_queue.output",
28 ".frc971.codelab.basic_queue.status") {}
29
30 // Sends a queue message with the position data.
31 void SendPositionMessage() {
32 ::aos::ScopedMessagePtr<BasicQueue::Position> position =
33 basic_queue_.position.MakeMessage();
34
35 position->limit_sensor = limit_sensor_;
36
37 position.Send();
38 }
39
40 void VerifyResults(double voltage, bool status) {
41 basic_queue_.output.FetchLatest();
42 basic_queue_.status.FetchLatest();
43
44 ASSERT_TRUE(basic_queue_.output.get() != nullptr);
45 ASSERT_TRUE(basic_queue_.status.get() != nullptr);
46
47 EXPECT_EQ(basic_queue_.output->intake_voltage, voltage);
48 EXPECT_EQ(basic_queue_.status->intake_complete, status);
49 }
50
51 void set_limit_sensor(bool value) { limit_sensor_ = value; }
52
53 // Simulates basic control loop for a single timestep.
54 void Simulate() { EXPECT_TRUE(basic_queue_.output.FetchLatest()); }
55
56 private:
57 BasicQueue basic_queue_;
58 bool limit_sensor_ = false;
59};
60
61class BasicControlLoopTest : public ::aos::testing::ControlLoopTest {
62 public:
63 BasicControlLoopTest()
Austin Schuh7660fcd2019-01-27 13:07:52 -080064 : basic_queue_(".frc971.codelab.basic_queue",
Parker Schuh18dbbb42017-10-18 21:45:33 -070065 ".frc971.codelab.basic_queue.goal",
66 ".frc971.codelab.basic_queue.position",
67 ".frc971.codelab.basic_queue.output",
68 ".frc971.codelab.basic_queue.status"),
Austin Schuh55a13dc2019-01-27 22:39:03 -080069 basic_loop_(&event_loop_, ".frc971.codelab.basic_queue") {
Parker Schuh18dbbb42017-10-18 21:45:33 -070070 set_team_id(control_loops::testing::kTeamNumber);
71 }
72
73 // Runs one iteration of the whole simulation.
74 void RunIteration(bool enabled = true) {
75 SendMessages(enabled);
76
77 basic_simulation_.SendPositionMessage();
78 basic_loop_.Iterate();
79 basic_simulation_.Simulate();
80
81 TickTime();
82 }
83
84 BasicQueue basic_queue_;
Austin Schuh55a13dc2019-01-27 22:39:03 -080085 ::aos::ShmEventLoop event_loop_;
Parker Schuh18dbbb42017-10-18 21:45:33 -070086 Basic basic_loop_;
87 BasicSimulation basic_simulation_;
88};
89
90// Tests that when the motor has finished intaking it stops.
91TEST_F(BasicControlLoopTest, IntakeLimitTransitionsToTrue) {
92 ASSERT_TRUE(basic_queue_.goal.MakeWithBuilder().intake(true).Send());
93 basic_simulation_.set_limit_sensor(false);
94
95 RunIteration();
96
97 basic_simulation_.VerifyResults(12.0, false);
98
99 ASSERT_TRUE(basic_queue_.goal.MakeWithBuilder().intake(true).Send());
100 basic_simulation_.set_limit_sensor(true);
101
102 RunIteration();
103
104 basic_simulation_.VerifyResults(0.0, true);
105}
106
107// Tests that the intake goes on if the sensor is not pressed
108// and intake is requested.
109TEST_F(BasicControlLoopTest, IntakeLimitNotSet) {
110 ASSERT_TRUE(basic_queue_.goal.MakeWithBuilder().intake(true).Send());
111 basic_simulation_.set_limit_sensor(false);
112
113 RunIteration();
114
115 basic_simulation_.VerifyResults(12.0, false);
116}
117
118// Tests that the intake is off if no intake is requested,
119// even if the limit sensor is off.
120TEST_F(BasicControlLoopTest, NoIntakeLimitNotSet) {
121 ASSERT_TRUE(basic_queue_.goal.MakeWithBuilder().intake(false).Send());
122 basic_simulation_.set_limit_sensor(false);
123
124 RunIteration();
125
126 basic_simulation_.VerifyResults(0.0, false);
127}
128
129// Tests that the intake is off even if the limit sensor
130// is pressed and intake is requested.
131TEST_F(BasicControlLoopTest, IntakeLimitSet) {
132 ASSERT_TRUE(basic_queue_.goal.MakeWithBuilder().intake(true).Send());
133 basic_simulation_.set_limit_sensor(true);
134
135 RunIteration();
136
137 basic_simulation_.VerifyResults(0.0, true);
138}
139
140// Tests that the intake is off if no intake is requested,
141TEST_F(BasicControlLoopTest, NoIntakeLimitSet) {
142 ASSERT_TRUE(basic_queue_.goal.MakeWithBuilder().intake(false).Send());
143 basic_simulation_.set_limit_sensor(true);
144
145 RunIteration();
146
147 basic_simulation_.VerifyResults(0.0, false);
148}
149
150// Tests that the control loop handles things properly if no goal is set.
151TEST_F(BasicControlLoopTest, NoGoalSet) {
152 basic_simulation_.set_limit_sensor(true);
153
154 RunIteration();
155
156 basic_simulation_.VerifyResults(0.0, false);
157}
158
159// Tests that the control loop handles things properly if disabled.
160TEST_F(BasicControlLoopTest, Disabled) {
161 basic_simulation_.set_limit_sensor(true);
162
163 ASSERT_TRUE(basic_queue_.goal.MakeWithBuilder().intake(true).Send());
164
165 RunIteration(false);
166
167 basic_simulation_.VerifyResults(0.0, false);
168}
169
170} // namespace testing
171} // namespace codelab
172} // namespace frc971