blob: 99dc73501f1347dfc59747eb96125dc01a5f5a56 [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
Austin Schuhdf6cbb12019-02-02 13:46:52 -080010#include "aos/events/event-loop.h"
11#include "aos/init.h"
John Park33858a32018-09-28 23:05:48 -070012#include "aos/logging/logging.h"
13#include "aos/logging/queue_logging.h"
John Park33858a32018-09-28 23:05:48 -070014#include "aos/robot_state/robot_state.q.h"
15#include "aos/time/time.h"
Austin Schuhdf6cbb12019-02-02 13:46:52 -080016#include "aos/util/phased_loop.h"
Brian Silverman07ec88e2014-12-28 00:13:08 -080017
18#include "frc971/queues/gyro.q.h"
Philipp Schrader29d54f22016-04-02 22:14:48 +000019#include "frc971/zeroing/averager.h"
Brian Silverman07ec88e2014-12-28 00:13:08 -080020
21namespace frc971 {
22namespace wpilib {
23
Austin Schuhf2a50ba2016-12-24 16:16:26 -080024namespace chrono = ::std::chrono;
25using ::aos::monotonic_clock;
Brian Silverman07ec88e2014-12-28 00:13:08 -080026
Austin Schuhdf6cbb12019-02-02 13:46:52 -080027GyroSender::GyroSender(::aos::EventLoop *event_loop)
28 : event_loop_(event_loop),
29 joystick_state_fetcher_(event_loop_->MakeFetcher<::aos::JoystickState>(
Austin Schuhcc1010e2019-05-12 20:38:01 -070030 ".aos.joystick_state")),
31 uid_sender_(event_loop_->MakeSender<::frc971::sensors::Uid>(
Austin Schuh1ea89bb2019-05-27 16:59:59 -070032 ".frc971.sensors.gyro_part_id")),
33 gyro_reading_sender_(
34 event_loop_->MakeSender<::frc971::sensors::GyroReading>(
35 ".frc971.sensors.gyro_reading")) {
Austin Schuhdf6cbb12019-02-02 13:46:52 -080036 PCHECK(
37 system("ps -ef | grep '\\[spi0\\]' | awk '{print $1}' | xargs chrt -f -p "
Austin Schuh268e13c2017-02-03 20:33:23 -080038 "33") == 0);
39}
40
Brian Silverman07ec88e2014-12-28 00:13:08 -080041void GyroSender::operator()() {
42 ::aos::SetCurrentThreadName("Gyro");
43
44 // Try to initialize repeatedly as long as we're supposed to be running.
45 while (run_ && !gyro_.InitializeGyro()) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080046 ::std::this_thread::sleep_for(::std::chrono::milliseconds(50));
Brian Silverman07ec88e2014-12-28 00:13:08 -080047 }
48 LOG(INFO, "gyro initialized successfully\n");
49
Austin Schuhcc1010e2019-05-12 20:38:01 -070050 auto message = uid_sender_.MakeMessage();
Brian Silverman07ec88e2014-12-28 00:13:08 -080051 message->uid = gyro_.ReadPartID();
52 LOG_STRUCT(INFO, "gyro ID", *message);
53 message.Send();
54
55 // In radians, ready to send out.
56 double angle = 0;
57
58 int startup_cycles_left = 2 * kReadingRate;
59
Philipp Schrader29d54f22016-04-02 22:14:48 +000060 zeroing::Averager<double, 6 * kReadingRate> zeroing_data;
Brian Silverman07ec88e2014-12-28 00:13:08 -080061 bool zeroed = false;
Brian Silverman07ec88e2014-12-28 00:13:08 -080062 double zero_offset = 0;
63
Austin Schuh268e13c2017-02-03 20:33:23 -080064 ::aos::SetCurrentThreadRealtimePriority(33);
65
66 ::aos::time::PhasedLoop phased_loop(::aos::time::FromRate(kReadingRate),
Austin Schuhd32b3622019-06-23 18:49:06 -070067 event_loop_->monotonic_now(),
Austin Schuh268e13c2017-02-03 20:33:23 -080068 chrono::milliseconds(4));
Brian Silvermandcaa3f72015-11-29 05:32:08 +000069 // How many timesteps the next reading represents.
70 int number_readings = 0;
71
Austin Schuh70ae5932016-11-27 19:09:25 -080072 ::aos::SetCurrentThreadRealtimePriority(33);
73
Brian Silverman07ec88e2014-12-28 00:13:08 -080074 while (run_) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +000075 number_readings += phased_loop.SleepUntilNext();
Brian Silverman07ec88e2014-12-28 00:13:08 -080076
77 const uint32_t result = gyro_.GetReading();
78 if (result == 0) {
79 LOG(WARNING, "normal gyro read failed\n");
80 continue;
81 }
82 switch (gyro_.ExtractStatus(result)) {
83 case 0:
84 LOG(WARNING, "gyro says data is bad\n");
85 continue;
86 case 1:
87 break;
88 default:
89 LOG(WARNING, "gyro gave weird status 0x%" PRIx8 "\n",
90 gyro_.ExtractStatus(result));
91 continue;
92 }
93 if (gyro_.ExtractErrors(result) != 0) {
94 const uint8_t errors = gyro_.ExtractErrors(result);
95 if (errors & (1 << 6)) {
96 LOG(WARNING, "gyro gave PLL error\n");
97 }
98 if (errors & (1 << 5)) {
99 LOG(WARNING, "gyro gave quadrature error\n");
100 }
101 if (errors & (1 << 4)) {
102 LOG(WARNING, "gyro gave non-volatile memory error\n");
103 }
104 if (errors & (1 << 3)) {
105 LOG(WARNING, "gyro gave volatile memory error\n");
106 }
107 if (errors & (1 << 2)) {
108 LOG(WARNING, "gyro gave power error\n");
109 }
110 if (errors & (1 << 1)) {
111 LOG(WARNING, "gyro gave continuous self-test error\n");
112 }
113 if (errors & 1) {
114 LOG(WARNING, "gyro gave unexpected self-test mode\n");
115 }
116 continue;
117 }
118
119 if (startup_cycles_left > 0) {
120 --startup_cycles_left;
121 continue;
122 }
123
Austin Schuhc5a23752015-10-28 19:45:24 -0700124 const double angle_rate = gyro_.ExtractAngle(result);
125 const double new_angle = angle_rate / static_cast<double>(kReadingRate);
Austin Schuh1ea89bb2019-05-27 16:59:59 -0700126 auto message = gyro_reading_sender_.MakeMessage();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800127 if (zeroed) {
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000128 angle += (new_angle + zero_offset) * number_readings;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800129 message->angle = angle;
Austin Schuhc5a23752015-10-28 19:45:24 -0700130 message->velocity = angle_rate + zero_offset * kReadingRate;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800131 LOG_STRUCT(DEBUG, "sending", *message);
132 message.Send();
133 } else {
134 // TODO(brian): Don't break without 6 seconds of standing still before
135 // enabling. Ideas:
136 // Don't allow driving until we have at least some data?
137 // Some kind of indicator light?
138 {
139 message->angle = new_angle;
Austin Schuhc5a23752015-10-28 19:45:24 -0700140 message->velocity = angle_rate;
Austin Schuh58d8cdf2015-02-15 21:04:42 -0800141 LOG_STRUCT(DEBUG, "collected while zeroing", *message);
Austin Schuh5125e082015-04-18 22:56:04 -0700142 message->angle = 0.0;
Austin Schuhc5a23752015-10-28 19:45:24 -0700143 message->velocity = 0.0;
Austin Schuh5125e082015-04-18 22:56:04 -0700144 message.Send();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800145 }
Philipp Schrader29d54f22016-04-02 22:14:48 +0000146 zeroing_data.AddData(new_angle);
Brian Silverman07ec88e2014-12-28 00:13:08 -0800147
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800148 joystick_state_fetcher_.Fetch();
149 if (joystick_state_fetcher_.get() && joystick_state_fetcher_->enabled &&
Philipp Schrader29d54f22016-04-02 22:14:48 +0000150 zeroing_data.full()) {
151 zero_offset = -zeroing_data.GetAverage();
Brian Silverman07ec88e2014-12-28 00:13:08 -0800152 LOG(INFO, "total zero offset %f\n", zero_offset);
153 zeroed = true;
154 }
155 }
Brian Silvermandcaa3f72015-11-29 05:32:08 +0000156 number_readings = 0;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800157 }
158}
159
160} // namespace wpilib
161} // namespace frc971