blob: 9acb6fca7a5c96835c1eac1ca31c8b6ebabdd9f1 [file] [log] [blame]
Brian Silverman07ec88e2014-12-28 00:13:08 -08001#include "frc971/wpilib/gyro_sender.h"
2
Austin Schuhf2a50ba2016-12-24 16:16:26 -08003#include <fcntl.h>
Brian Silverman07ec88e2014-12-28 00:13:08 -08004#include <inttypes.h>
Austin Schuhf2a50ba2016-12-24 16:16:26 -08005#include <sys/stat.h>
6#include <sys/types.h>
7
8#include <chrono>
Brian Silverman07ec88e2014-12-28 00:13:08 -08009
10#include "aos/common/logging/logging.h"
11#include "aos/common/logging/queue_logging.h"
12#include "aos/common/util/phased_loop.h"
13#include "aos/common/messages/robot_state.q.h"
14#include "aos/common/time.h"
15#include "aos/linux_code/init.h"
16
17#include "frc971/queues/gyro.q.h"
Philipp Schrader29d54f22016-04-02 22:14:48 +000018#include "frc971/zeroing/averager.h"
Brian Silverman07ec88e2014-12-28 00:13:08 -080019
20namespace frc971 {
21namespace wpilib {
22
23GyroSender::GyroSender() {}
Austin Schuhf2a50ba2016-12-24 16:16:26 -080024namespace chrono = ::std::chrono;
25using ::aos::monotonic_clock;
Brian Silverman07ec88e2014-12-28 00:13:08 -080026
27void GyroSender::operator()() {
28 ::aos::SetCurrentThreadName("Gyro");
29
30 // Try to initialize repeatedly as long as we're supposed to be running.
31 while (run_ && !gyro_.InitializeGyro()) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080032 ::std::this_thread::sleep_for(::std::chrono::milliseconds(50));
Brian Silverman07ec88e2014-12-28 00:13:08 -080033 }
34 LOG(INFO, "gyro initialized successfully\n");
35
36 auto message = ::frc971::sensors::gyro_part_id.MakeMessage();
37 message->uid = gyro_.ReadPartID();
38 LOG_STRUCT(INFO, "gyro ID", *message);
39 message.Send();
40
41 // In radians, ready to send out.
42 double angle = 0;
43
44 int startup_cycles_left = 2 * kReadingRate;
45
Philipp Schrader29d54f22016-04-02 22:14:48 +000046 zeroing::Averager<double, 6 * kReadingRate> zeroing_data;
Brian Silverman07ec88e2014-12-28 00:13:08 -080047 bool zeroed = false;
Brian Silverman07ec88e2014-12-28 00:13:08 -080048 double zero_offset = 0;
49
Brian Silvermandcaa3f72015-11-29 05:32:08 +000050 ::aos::time::PhasedLoop phased_loop(
51 ::aos::time::Time::FromRate(kReadingRate));
52 // How many timesteps the next reading represents.
53 int number_readings = 0;
54
Austin Schuh70ae5932016-11-27 19:09:25 -080055 ::aos::SetCurrentThreadRealtimePriority(33);
56
Brian Silverman07ec88e2014-12-28 00:13:08 -080057 while (run_) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +000058 number_readings += phased_loop.SleepUntilNext();
Brian Silverman07ec88e2014-12-28 00:13:08 -080059
60 const uint32_t result = gyro_.GetReading();
61 if (result == 0) {
62 LOG(WARNING, "normal gyro read failed\n");
63 continue;
64 }
65 switch (gyro_.ExtractStatus(result)) {
66 case 0:
67 LOG(WARNING, "gyro says data is bad\n");
68 continue;
69 case 1:
70 break;
71 default:
72 LOG(WARNING, "gyro gave weird status 0x%" PRIx8 "\n",
73 gyro_.ExtractStatus(result));
74 continue;
75 }
76 if (gyro_.ExtractErrors(result) != 0) {
77 const uint8_t errors = gyro_.ExtractErrors(result);
78 if (errors & (1 << 6)) {
79 LOG(WARNING, "gyro gave PLL error\n");
80 }
81 if (errors & (1 << 5)) {
82 LOG(WARNING, "gyro gave quadrature error\n");
83 }
84 if (errors & (1 << 4)) {
85 LOG(WARNING, "gyro gave non-volatile memory error\n");
86 }
87 if (errors & (1 << 3)) {
88 LOG(WARNING, "gyro gave volatile memory error\n");
89 }
90 if (errors & (1 << 2)) {
91 LOG(WARNING, "gyro gave power error\n");
92 }
93 if (errors & (1 << 1)) {
94 LOG(WARNING, "gyro gave continuous self-test error\n");
95 }
96 if (errors & 1) {
97 LOG(WARNING, "gyro gave unexpected self-test mode\n");
98 }
99 continue;
100 }
101
102 if (startup_cycles_left > 0) {
103 --startup_cycles_left;
104 continue;
105 }
106
Austin Schuhc5a23752015-10-28 19:45:24 -0700107 const double angle_rate = gyro_.ExtractAngle(result);
108 const double new_angle = angle_rate / static_cast<double>(kReadingRate);
Brian Silverman07ec88e2014-12-28 00:13:08 -0800109 auto message = ::frc971::sensors::gyro_reading.MakeMessage();
110 if (zeroed) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000111 angle += (new_angle + zero_offset) * number_readings;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800112 message->angle = angle;
Austin Schuhc5a23752015-10-28 19:45:24 -0700113 message->velocity = angle_rate + zero_offset * kReadingRate;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800114 LOG_STRUCT(DEBUG, "sending", *message);
115 message.Send();
116 } else {
117 // TODO(brian): Don't break without 6 seconds of standing still before
118 // enabling. Ideas:
119 // Don't allow driving until we have at least some data?
120 // Some kind of indicator light?
121 {
122 message->angle = new_angle;
Austin Schuhc5a23752015-10-28 19:45:24 -0700123 message->velocity = angle_rate;
Austin Schuh58d8cdf2015-02-15 21:04:42 -0800124 LOG_STRUCT(DEBUG, "collected while zeroing", *message);
Austin Schuh5125e082015-04-18 22:56:04 -0700125 message->angle = 0.0;
Austin Schuhc5a23752015-10-28 19:45:24 -0700126 message->velocity = 0.0;
Austin Schuh5125e082015-04-18 22:56:04 -0700127 message.Send();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800128 }
Philipp Schrader29d54f22016-04-02 22:14:48 +0000129 zeroing_data.AddData(new_angle);
Brian Silverman07ec88e2014-12-28 00:13:08 -0800130
Brian Silverman699f0cb2015-02-05 19:45:01 -0500131 ::aos::joystick_state.FetchLatest();
132 if (::aos::joystick_state.get() && ::aos::joystick_state->enabled &&
Philipp Schrader29d54f22016-04-02 22:14:48 +0000133 zeroing_data.full()) {
134 zero_offset = -zeroing_data.GetAverage();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800135 LOG(INFO, "total zero offset %f\n", zero_offset);
136 zeroed = true;
137 }
138 }
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000139 number_readings = 0;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800140 }
141}
142
143} // namespace wpilib
144} // namespace frc971