blob: 2bdcc76b4ebd9db12114163611fad027ad0420b9 [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 Schuh217a9782019-12-21 23:02:50 -080010#include "aos/events/shm_event_loop.h"
Austin Schuhdf6cbb12019-02-02 13:46:52 -080011#include "aos/init.h"
John Park33858a32018-09-28 23:05:48 -070012#include "aos/logging/logging.h"
Alex Perrycb7da4b2019-08-28 19:35:56 -070013#include "aos/robot_state/robot_state_generated.h"
John Park33858a32018-09-28 23:05:48 -070014#include "aos/time/time.h"
Brian Silverman07ec88e2014-12-28 00:13:08 -080015
Alex Perrycb7da4b2019-08-28 19:35:56 -070016#include "frc971/queues/gyro_generated.h"
Tyler Chatow24b5db12020-01-06 21:16:56 -080017#include "frc971/queues/gyro_uid_generated.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
Austin Schuhf2a50ba2016-12-24 16:16:26 -080023namespace chrono = ::std::chrono;
24using ::aos::monotonic_clock;
Brian Silverman07ec88e2014-12-28 00:13:08 -080025
Austin Schuh217a9782019-12-21 23:02:50 -080026GyroSender::GyroSender(::aos::ShmEventLoop *event_loop)
Austin Schuhdf6cbb12019-02-02 13:46:52 -080027 : event_loop_(event_loop),
Alex Perrycb7da4b2019-08-28 19:35:56 -070028 joystick_state_fetcher_(
29 event_loop_->MakeFetcher<aos::RobotState>("/aos")),
30 uid_sender_(event_loop_->MakeSender<frc971::sensors::Uid>("/drivetrain")),
Austin Schuh1ea89bb2019-05-27 16:59:59 -070031 gyro_reading_sender_(
Alex Perrycb7da4b2019-08-28 19:35:56 -070032 event_loop_->MakeSender<frc971::sensors::GyroReading>(
33 "/drivetrain")) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070034 AOS_PCHECK(
Austin Schuha3f2a312020-02-22 21:03:00 -080035 system("busybox ps -ef | grep '\\[spi0\\]' | awk '{print $1}' | xargs chrt -f -p "
Austin Schuh268e13c2017-02-03 20:33:23 -080036 "33") == 0);
Austin Schuh217a9782019-12-21 23:02:50 -080037 event_loop->set_name("Gyro");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070038 event_loop_->SetRuntimeRealtimePriority(33);
39
40 // TODO(austin): This should be synchronized with SensorReader... Pull out
41 // the sync logic and re-use it here.
42 event_loop_->AddPhasedLoop([this](int iterations) { Loop(iterations); },
43 ::aos::time::FromRate(kReadingRate),
44 chrono::milliseconds(4));
Austin Schuh268e13c2017-02-03 20:33:23 -080045}
46
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070047void GyroSender::Loop(const int iterations) {
48 switch (state_) {
49 case State::INITIALIZING: {
50 const monotonic_clock::time_point monotonic_now =
51 event_loop_->monotonic_now();
52 if (last_initialize_time_ + chrono::milliseconds(50) < monotonic_now) {
53 if (gyro_.InitializeGyro()) {
54 state_ = State::RUNNING;
Austin Schuhf257f3c2019-10-27 21:00:43 -070055 AOS_LOG(INFO, "gyro initialized successfully\n");
Brian Silverman07ec88e2014-12-28 00:13:08 -080056
Alex Perrycb7da4b2019-08-28 19:35:56 -070057 auto builder = uid_sender_.MakeBuilder();
58 builder.Send(
59 frc971::sensors::CreateUid(*builder.fbb(), gyro_.ReadPartID()));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070060 }
61 last_initialize_time_ = monotonic_now;
Brian Silverman07ec88e2014-12-28 00:13:08 -080062 }
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070063 } break;
64 case State::RUNNING: {
65 const uint32_t result = gyro_.GetReading();
66 if (result == 0) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070067 AOS_LOG(WARNING, "normal gyro read failed\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070068 return;
Brian Silverman07ec88e2014-12-28 00:13:08 -080069 }
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070070 switch (gyro_.ExtractStatus(result)) {
71 case 0:
Austin Schuhf257f3c2019-10-27 21:00:43 -070072 AOS_LOG(WARNING, "gyro says data is bad\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070073 return;
74 case 1:
75 break;
76 default:
Austin Schuhf257f3c2019-10-27 21:00:43 -070077 AOS_LOG(WARNING, "gyro gave weird status 0x%" PRIx8 "\n",
78 gyro_.ExtractStatus(result));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070079 return;
Brian Silverman07ec88e2014-12-28 00:13:08 -080080 }
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070081 if (gyro_.ExtractErrors(result) != 0) {
82 const uint8_t errors = gyro_.ExtractErrors(result);
83 if (errors & (1 << 6)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070084 AOS_LOG(WARNING, "gyro gave PLL error\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070085 }
86 if (errors & (1 << 5)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070087 AOS_LOG(WARNING, "gyro gave quadrature error\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070088 }
89 if (errors & (1 << 4)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070090 AOS_LOG(WARNING, "gyro gave non-volatile memory error\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070091 }
92 if (errors & (1 << 3)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070093 AOS_LOG(WARNING, "gyro gave volatile memory error\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070094 }
95 if (errors & (1 << 2)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070096 AOS_LOG(WARNING, "gyro gave power error\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070097 }
98 if (errors & (1 << 1)) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070099 AOS_LOG(WARNING, "gyro gave continuous self-test error\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700100 }
101 if (errors & 1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700102 AOS_LOG(WARNING, "gyro gave unexpected self-test mode\n");
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700103 }
104 return;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800105 }
Brian Silverman07ec88e2014-12-28 00:13:08 -0800106
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700107 if (startup_cycles_left_ > 0) {
108 --startup_cycles_left_;
109 return;
110 }
Brian Silverman07ec88e2014-12-28 00:13:08 -0800111
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700112 const double angle_rate = gyro_.ExtractAngle(result);
113 const double new_angle = angle_rate / static_cast<double>(kReadingRate);
Alex Perrycb7da4b2019-08-28 19:35:56 -0700114 auto builder = gyro_reading_sender_.MakeBuilder();
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700115 if (zeroed_) {
116 angle_ += (new_angle + zero_offset_) * iterations;
Alex Perrycb7da4b2019-08-28 19:35:56 -0700117 sensors::GyroReading::Builder gyro_builder =
118 builder.MakeBuilder<sensors::GyroReading>();
119 gyro_builder.add_angle(angle_);
120 gyro_builder.add_velocity(angle_rate + zero_offset_ * kReadingRate);
121 builder.Send(gyro_builder.Finish());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700122 } else {
123 // TODO(brian): Don't break without 6 seconds of standing still before
124 // enabling. Ideas:
125 // Don't allow driving until we have at least some data?
126 // Some kind of indicator light?
127 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700128 sensors::GyroReading::Builder gyro_builder =
129 builder.MakeBuilder<sensors::GyroReading>();
130 gyro_builder.add_angle(0.0);
131 gyro_builder.add_velocity(0.0);
132 builder.Send(gyro_builder.Finish());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700133 }
134 zeroing_data_.AddData(new_angle);
Brian Silverman07ec88e2014-12-28 00:13:08 -0800135
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700136 joystick_state_fetcher_.Fetch();
Alex Perrycb7da4b2019-08-28 19:35:56 -0700137 if (joystick_state_fetcher_.get() &&
138 joystick_state_fetcher_->outputs_enabled() &&
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700139 zeroing_data_.full()) {
James Kuszmauld3f9eb22020-01-12 15:02:07 -0800140 zero_offset_ = -zeroing_data_.GetAverage()(0, 0);
Austin Schuhf257f3c2019-10-27 21:00:43 -0700141 AOS_LOG(INFO, "total zero offset %f\n", zero_offset_);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700142 zeroed_ = true;
143 }
Brian Silverman07ec88e2014-12-28 00:13:08 -0800144 }
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700145 } break;
Brian Silverman07ec88e2014-12-28 00:13:08 -0800146 }
147}
148
149} // namespace wpilib
150} // namespace frc971