blob: a155b7eeb83916f604d9ad8c1513afb1d579e1b7 [file] [log] [blame]
Brian Silverman07ec88e2014-12-28 00:13:08 -08001#include "frc971/wpilib/gyro_sender.h"
2
3#include <inttypes.h>
4
5#include "aos/common/logging/logging.h"
6#include "aos/common/logging/queue_logging.h"
7#include "aos/common/util/phased_loop.h"
8#include "aos/common/messages/robot_state.q.h"
9#include "aos/common/time.h"
10#include "aos/linux_code/init.h"
11
12#include "frc971/queues/gyro.q.h"
13
14namespace frc971 {
15namespace wpilib {
16
17GyroSender::GyroSender() {}
18
19void GyroSender::operator()() {
20 ::aos::SetCurrentThreadName("Gyro");
21
22 // Try to initialize repeatedly as long as we're supposed to be running.
23 while (run_ && !gyro_.InitializeGyro()) {
24 ::aos::time::SleepFor(::aos::time::Time::InMS(50));
25 }
26 LOG(INFO, "gyro initialized successfully\n");
27
28 auto message = ::frc971::sensors::gyro_part_id.MakeMessage();
29 message->uid = gyro_.ReadPartID();
30 LOG_STRUCT(INFO, "gyro ID", *message);
31 message.Send();
32
33 // In radians, ready to send out.
34 double angle = 0;
35
36 int startup_cycles_left = 2 * kReadingRate;
37
38 double zeroing_data[6 * kReadingRate];
39 size_t zeroing_index = 0;
40 bool zeroed = false;
41 bool have_zeroing_data = false;
42 double zero_offset = 0;
43
44 while (run_) {
45 ::aos::time::PhasedLoopXMS(1000 / kReadingRate, 0);
46
47 const uint32_t result = gyro_.GetReading();
48 if (result == 0) {
49 LOG(WARNING, "normal gyro read failed\n");
50 continue;
51 }
52 switch (gyro_.ExtractStatus(result)) {
53 case 0:
54 LOG(WARNING, "gyro says data is bad\n");
55 continue;
56 case 1:
57 break;
58 default:
59 LOG(WARNING, "gyro gave weird status 0x%" PRIx8 "\n",
60 gyro_.ExtractStatus(result));
61 continue;
62 }
63 if (gyro_.ExtractErrors(result) != 0) {
64 const uint8_t errors = gyro_.ExtractErrors(result);
65 if (errors & (1 << 6)) {
66 LOG(WARNING, "gyro gave PLL error\n");
67 }
68 if (errors & (1 << 5)) {
69 LOG(WARNING, "gyro gave quadrature error\n");
70 }
71 if (errors & (1 << 4)) {
72 LOG(WARNING, "gyro gave non-volatile memory error\n");
73 }
74 if (errors & (1 << 3)) {
75 LOG(WARNING, "gyro gave volatile memory error\n");
76 }
77 if (errors & (1 << 2)) {
78 LOG(WARNING, "gyro gave power error\n");
79 }
80 if (errors & (1 << 1)) {
81 LOG(WARNING, "gyro gave continuous self-test error\n");
82 }
83 if (errors & 1) {
84 LOG(WARNING, "gyro gave unexpected self-test mode\n");
85 }
86 continue;
87 }
88
89 if (startup_cycles_left > 0) {
90 --startup_cycles_left;
91 continue;
92 }
93
94 const double new_angle =
95 gyro_.ExtractAngle(result) / static_cast<double>(kReadingRate);
96 auto message = ::frc971::sensors::gyro_reading.MakeMessage();
97 if (zeroed) {
98 angle += new_angle;
99 angle += zero_offset;
100 message->angle = angle;
101 LOG_STRUCT(DEBUG, "sending", *message);
102 message.Send();
103 } else {
104 // TODO(brian): Don't break without 6 seconds of standing still before
105 // enabling. Ideas:
106 // Don't allow driving until we have at least some data?
107 // Some kind of indicator light?
108 {
109 message->angle = new_angle;
110 LOG_STRUCT(DEBUG, "collected", *message);
111 }
112 zeroing_data[zeroing_index] = new_angle;
113 ++zeroing_index;
114 if (zeroing_index >= sizeof(zeroing_data) / sizeof(zeroing_data[0])) {
115 zeroing_index = 0;
116 have_zeroing_data = true;
117 }
118
119 ::aos::robot_state.FetchLatest();
120 if (::aos::robot_state.get() && ::aos::robot_state->enabled &&
121 have_zeroing_data) {
122 zero_offset = 0;
123 for (size_t i = 0; i < sizeof(zeroing_data) / sizeof(zeroing_data[0]);
124 ++i) {
125 zero_offset -= zeroing_data[i];
126 }
127 zero_offset /= sizeof(zeroing_data) / sizeof(zeroing_data[0]);
128 LOG(INFO, "total zero offset %f\n", zero_offset);
129 zeroed = true;
130 }
131 }
132 }
133}
134
135} // namespace wpilib
136} // namespace frc971