blob: 82e97750a0587db5c8d80ec41c1b6a21cda301c6 [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"
Philipp Schrader29d54f22016-04-02 22:14:48 +000013#include "frc971/zeroing/averager.h"
Brian Silverman07ec88e2014-12-28 00:13:08 -080014
15namespace frc971 {
16namespace wpilib {
17
18GyroSender::GyroSender() {}
19
20void GyroSender::operator()() {
21 ::aos::SetCurrentThreadName("Gyro");
22
23 // Try to initialize repeatedly as long as we're supposed to be running.
24 while (run_ && !gyro_.InitializeGyro()) {
25 ::aos::time::SleepFor(::aos::time::Time::InMS(50));
26 }
27 LOG(INFO, "gyro initialized successfully\n");
28
29 auto message = ::frc971::sensors::gyro_part_id.MakeMessage();
30 message->uid = gyro_.ReadPartID();
31 LOG_STRUCT(INFO, "gyro ID", *message);
32 message.Send();
33
34 // In radians, ready to send out.
35 double angle = 0;
36
37 int startup_cycles_left = 2 * kReadingRate;
38
Philipp Schrader29d54f22016-04-02 22:14:48 +000039 zeroing::Averager<double, 6 * kReadingRate> zeroing_data;
Brian Silverman07ec88e2014-12-28 00:13:08 -080040 bool zeroed = false;
Brian Silverman07ec88e2014-12-28 00:13:08 -080041 double zero_offset = 0;
42
Brian Silvermandcaa3f72015-11-29 05:32:08 +000043 ::aos::time::PhasedLoop phased_loop(
44 ::aos::time::Time::FromRate(kReadingRate));
45 // How many timesteps the next reading represents.
46 int number_readings = 0;
47
Brian Silverman07ec88e2014-12-28 00:13:08 -080048 while (run_) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +000049 number_readings += phased_loop.SleepUntilNext();
Brian Silverman07ec88e2014-12-28 00:13:08 -080050
51 const uint32_t result = gyro_.GetReading();
52 if (result == 0) {
53 LOG(WARNING, "normal gyro read failed\n");
54 continue;
55 }
56 switch (gyro_.ExtractStatus(result)) {
57 case 0:
58 LOG(WARNING, "gyro says data is bad\n");
59 continue;
60 case 1:
61 break;
62 default:
63 LOG(WARNING, "gyro gave weird status 0x%" PRIx8 "\n",
64 gyro_.ExtractStatus(result));
65 continue;
66 }
67 if (gyro_.ExtractErrors(result) != 0) {
68 const uint8_t errors = gyro_.ExtractErrors(result);
69 if (errors & (1 << 6)) {
70 LOG(WARNING, "gyro gave PLL error\n");
71 }
72 if (errors & (1 << 5)) {
73 LOG(WARNING, "gyro gave quadrature error\n");
74 }
75 if (errors & (1 << 4)) {
76 LOG(WARNING, "gyro gave non-volatile memory error\n");
77 }
78 if (errors & (1 << 3)) {
79 LOG(WARNING, "gyro gave volatile memory error\n");
80 }
81 if (errors & (1 << 2)) {
82 LOG(WARNING, "gyro gave power error\n");
83 }
84 if (errors & (1 << 1)) {
85 LOG(WARNING, "gyro gave continuous self-test error\n");
86 }
87 if (errors & 1) {
88 LOG(WARNING, "gyro gave unexpected self-test mode\n");
89 }
90 continue;
91 }
92
93 if (startup_cycles_left > 0) {
94 --startup_cycles_left;
95 continue;
96 }
97
Austin Schuhc5a23752015-10-28 19:45:24 -070098 const double angle_rate = gyro_.ExtractAngle(result);
99 const double new_angle = angle_rate / static_cast<double>(kReadingRate);
Brian Silverman07ec88e2014-12-28 00:13:08 -0800100 auto message = ::frc971::sensors::gyro_reading.MakeMessage();
101 if (zeroed) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000102 angle += (new_angle + zero_offset) * number_readings;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800103 message->angle = angle;
Austin Schuhc5a23752015-10-28 19:45:24 -0700104 message->velocity = angle_rate + zero_offset * kReadingRate;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800105 LOG_STRUCT(DEBUG, "sending", *message);
106 message.Send();
107 } else {
108 // TODO(brian): Don't break without 6 seconds of standing still before
109 // enabling. Ideas:
110 // Don't allow driving until we have at least some data?
111 // Some kind of indicator light?
112 {
113 message->angle = new_angle;
Austin Schuhc5a23752015-10-28 19:45:24 -0700114 message->velocity = angle_rate;
Austin Schuh58d8cdf2015-02-15 21:04:42 -0800115 LOG_STRUCT(DEBUG, "collected while zeroing", *message);
Austin Schuh5125e082015-04-18 22:56:04 -0700116 message->angle = 0.0;
Austin Schuhc5a23752015-10-28 19:45:24 -0700117 message->velocity = 0.0;
Austin Schuh5125e082015-04-18 22:56:04 -0700118 message.Send();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800119 }
Philipp Schrader29d54f22016-04-02 22:14:48 +0000120 zeroing_data.AddData(new_angle);
Brian Silverman07ec88e2014-12-28 00:13:08 -0800121
Brian Silverman699f0cb2015-02-05 19:45:01 -0500122 ::aos::joystick_state.FetchLatest();
123 if (::aos::joystick_state.get() && ::aos::joystick_state->enabled &&
Philipp Schrader29d54f22016-04-02 22:14:48 +0000124 zeroing_data.full()) {
125 zero_offset = -zeroing_data.GetAverage();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800126 LOG(INFO, "total zero offset %f\n", zero_offset);
127 zeroed = true;
128 }
129 }
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000130 number_readings = 0;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800131 }
132}
133
134} // namespace wpilib
135} // namespace frc971