blob: dd3b3e18ed4f73c048c90d793326bc8ac392f542 [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
Brian Silvermandcaa3f72015-11-29 05:32:08 +000044 ::aos::time::PhasedLoop phased_loop(
45 ::aos::time::Time::FromRate(kReadingRate));
46 // How many timesteps the next reading represents.
47 int number_readings = 0;
48
Brian Silverman07ec88e2014-12-28 00:13:08 -080049 while (run_) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +000050 number_readings += phased_loop.SleepUntilNext();
Brian Silverman07ec88e2014-12-28 00:13:08 -080051
52 const uint32_t result = gyro_.GetReading();
53 if (result == 0) {
54 LOG(WARNING, "normal gyro read failed\n");
55 continue;
56 }
57 switch (gyro_.ExtractStatus(result)) {
58 case 0:
59 LOG(WARNING, "gyro says data is bad\n");
60 continue;
61 case 1:
62 break;
63 default:
64 LOG(WARNING, "gyro gave weird status 0x%" PRIx8 "\n",
65 gyro_.ExtractStatus(result));
66 continue;
67 }
68 if (gyro_.ExtractErrors(result) != 0) {
69 const uint8_t errors = gyro_.ExtractErrors(result);
70 if (errors & (1 << 6)) {
71 LOG(WARNING, "gyro gave PLL error\n");
72 }
73 if (errors & (1 << 5)) {
74 LOG(WARNING, "gyro gave quadrature error\n");
75 }
76 if (errors & (1 << 4)) {
77 LOG(WARNING, "gyro gave non-volatile memory error\n");
78 }
79 if (errors & (1 << 3)) {
80 LOG(WARNING, "gyro gave volatile memory error\n");
81 }
82 if (errors & (1 << 2)) {
83 LOG(WARNING, "gyro gave power error\n");
84 }
85 if (errors & (1 << 1)) {
86 LOG(WARNING, "gyro gave continuous self-test error\n");
87 }
88 if (errors & 1) {
89 LOG(WARNING, "gyro gave unexpected self-test mode\n");
90 }
91 continue;
92 }
93
94 if (startup_cycles_left > 0) {
95 --startup_cycles_left;
96 continue;
97 }
98
Austin Schuhc5a23752015-10-28 19:45:24 -070099 const double angle_rate = gyro_.ExtractAngle(result);
100 const double new_angle = angle_rate / static_cast<double>(kReadingRate);
Brian Silverman07ec88e2014-12-28 00:13:08 -0800101 auto message = ::frc971::sensors::gyro_reading.MakeMessage();
102 if (zeroed) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000103 angle += (new_angle + zero_offset) * number_readings;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800104 message->angle = angle;
Austin Schuhc5a23752015-10-28 19:45:24 -0700105 message->velocity = angle_rate + zero_offset * kReadingRate;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800106 LOG_STRUCT(DEBUG, "sending", *message);
107 message.Send();
108 } else {
109 // TODO(brian): Don't break without 6 seconds of standing still before
110 // enabling. Ideas:
111 // Don't allow driving until we have at least some data?
112 // Some kind of indicator light?
113 {
114 message->angle = new_angle;
Austin Schuhc5a23752015-10-28 19:45:24 -0700115 message->velocity = angle_rate;
Austin Schuh58d8cdf2015-02-15 21:04:42 -0800116 LOG_STRUCT(DEBUG, "collected while zeroing", *message);
Austin Schuh5125e082015-04-18 22:56:04 -0700117 message->angle = 0.0;
Austin Schuhc5a23752015-10-28 19:45:24 -0700118 message->velocity = 0.0;
Austin Schuh5125e082015-04-18 22:56:04 -0700119 message.Send();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800120 }
121 zeroing_data[zeroing_index] = new_angle;
122 ++zeroing_index;
123 if (zeroing_index >= sizeof(zeroing_data) / sizeof(zeroing_data[0])) {
124 zeroing_index = 0;
125 have_zeroing_data = true;
126 }
127
Brian Silverman699f0cb2015-02-05 19:45:01 -0500128 ::aos::joystick_state.FetchLatest();
129 if (::aos::joystick_state.get() && ::aos::joystick_state->enabled &&
Brian Silverman07ec88e2014-12-28 00:13:08 -0800130 have_zeroing_data) {
131 zero_offset = 0;
132 for (size_t i = 0; i < sizeof(zeroing_data) / sizeof(zeroing_data[0]);
133 ++i) {
134 zero_offset -= zeroing_data[i];
135 }
136 zero_offset /= sizeof(zeroing_data) / sizeof(zeroing_data[0]);
137 LOG(INFO, "total zero offset %f\n", zero_offset);
138 zeroed = true;
139 }
140 }
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000141 number_readings = 0;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800142 }
143}
144
145} // namespace wpilib
146} // namespace frc971