blob: 62c36574d163b700d4da58115831b84bfbfe857a [file] [log] [blame]
Daniel Petti3fe36542013-09-25 04:18:24 +00001#include <libusb-1.0/libusb.h>
2#include <memory>
3
4#include "aos/common/inttypes.h"
5#include "aos/atom_code/init.h"
6#include "aos/common/logging/logging.h"
7#include "aos/common/control_loop/Timing.h"
8#include "aos/common/time.h"
9
10#include "frc971/control_loops/drivetrain/drivetrain.q.h"
11#include "frc971/control_loops/wrist/wrist_motor.q.h"
12#include "frc971/control_loops/angle_adjust/angle_adjust_motor.q.h"
13#include "frc971/control_loops/index/index_motor.q.h"
14#include "frc971/control_loops/shooter/shooter_motor.q.h"
Daniel Pettibedbf8d2013-09-26 01:29:15 +000015#include "bot3/input/gyro_board_data.h"
Daniel Petti3fe36542013-09-25 04:18:24 +000016#include "gyro_board/src/libusb-driver/libusb_wrap.h"
17#include "frc971/queues/GyroAngle.q.h"
18
19#ifndef M_PI
20#define M_PI 3.14159265358979323846
21#endif
22
23using ::frc971::control_loops::drivetrain;
Daniel Petti3fe36542013-09-25 04:18:24 +000024using ::frc971::control_loops::shooter;
Daniel Petti3fe36542013-09-25 04:18:24 +000025using ::frc971::sensors::gyro;
26
Daniel Pettibedbf8d2013-09-26 01:29:15 +000027namespace bot3 {
Daniel Petti3fe36542013-09-25 04:18:24 +000028namespace {
29
30inline double drivetrain_translate(int32_t in) {
31 return static_cast<double>(in) / (256.0 /*cpr*/ * 4.0 /*quad*/) *
32 (19.0 / 50.0) /*output reduction*/ * (64.0 / 24.0) /*encoder gears*/ *
33 (3.5 /*wheel diameter*/ * 2.54 / 100.0 * M_PI);
34}
35
Daniel Pettibedbf8d2013-09-26 01:29:15 +000036// TODO(daniel): This might have to change if I find out that the gear ratios are different.
Daniel Petti3fe36542013-09-25 04:18:24 +000037inline double shooter_translate(int32_t in) {
38 return static_cast<double>(in) / (32.0 /*cpr*/ * 4.0 /*quad*/) *
39 (15.0 / 34.0) /*gears*/ * (2 * M_PI);
40}
41
Daniel Petti3fe36542013-09-25 04:18:24 +000042} // namespace
43
44class GyroBoardReader {
45 public:
46 GyroBoardReader()
47 : top_rise_count_(0),
48 last_top_rise_count_(0),
49 top_fall_count_(0),
50 last_top_fall_count_(0),
51 bottom_rise_count_(0),
52 last_bottom_rise_count_(0),
53 bottom_fall_delay_count_(0),
54 last_bottom_fall_delay_count_(0),
55 bottom_fall_count_(0),
Daniel Pettibedbf8d2013-09-26 01:29:15 +000056 last_bottom_fall_count_(0) {
Daniel Petti3fe36542013-09-25 04:18:24 +000057 }
58
59 void Run() {
60 LibUSB libusb;
61
62 dev_handle_ = ::std::unique_ptr<LibUSBDeviceHandle>(
63 libusb.FindDeviceWithVIDPID(kVid, kPid));
64 if (!dev_handle_) {
65 LOG(ERROR, "couldn't find device. exiting\n");
66 exit(1);
67 }
68
69 uint8_t data[64];
70 GyroBoardData *real_data;
71 static_assert(sizeof(*real_data) <= sizeof(data), "it doesn't fit");
72
73 uint8_t *data_pointer = data;
74 memcpy(&real_data, &data_pointer, sizeof(data_pointer));
75 while (true) {
76 if (false) {
77 // Theoretically need -3ms of offset. Using a slightly larger one to avoid
78 // missing the first control loop in the worst case.
79 ::aos::time::PhasedLoop10MS(
80 ::aos::time::Time::InSeconds(-0.0031).ToUSec());
81 LOG(DEBUG, "starting now\n");
82
83 // Read 2 to make sure that we get fresh data.
84 if (!ReadPacket(data, sizeof(data))) continue;
85 //LOG(DEBUG, "in between\n");
86 if (!ReadPacket(data, sizeof(data))) continue;
87 } else {
88 if (!ReadPacket(data, sizeof(data))) continue;
89
90 ProcessData(real_data);
91 }
92 }
93 }
94
95 private:
96 static const unsigned char kEndpoint = 0x81;
97 // in ms
98 // 0 is unlimited
99 static const unsigned int kReadTimeout = 1000;
100
101 // vendor ID
102 static const int32_t kVid = 0x1424;
103 // product ID
104 static const int32_t kPid = 0xd243;
105
106 // Returns whether it read a good packet.
107 bool ReadPacket(uint8_t *data, size_t data_size) {
108 int read_bytes;
109 int r = dev_handle_->interrupt_transfer(
110 kEndpoint, data, data_size, &read_bytes, kReadTimeout);
111
112 if (r != 0) {
113 if (r == LIBUSB_ERROR_TIMEOUT) {
114 LOG(ERROR, "read timed out\n");
115 return false;
116 }
117 LOG(FATAL, "libusb gave error %d\n", r);
118 }
119
120 if (read_bytes < static_cast<ssize_t>(sizeof(GyroBoardData))) {
121 LOG(ERROR, "read %d bytes instead of at least %zd\n",
122 read_bytes, sizeof(GyroBoardData));
123 return false;
124 }
125
126 return true;
127 }
128
129 void UpdateWrappingCounter(
130 uint8_t current, uint8_t *last, int32_t *counter) {
131 if (*last > current) {
132 *counter += 0x100;
133 }
134 *counter = (*counter & 0xffffff00) | current;
135 *last = current;
136 }
137
138 void ProcessData(GyroBoardData *data) {
139 data->NetworkToHost();
140 LOG(DEBUG, "processing a packet\n");
141 static ::aos::time::Time last_time = ::aos::time::Time::Now();
142 if ((last_time - ::aos::time::Time::Now()) >
143 ::aos::time::Time::InMS(0.00205)) {
144 LOG(INFO, "missed one\n");
145 }
146
147 gyro.MakeWithBuilder()
148 .angle(data->gyro_angle / 16.0 / 1000.0 / 180.0 * M_PI)
149 .Send();
150
151 UpdateWrappingCounter(data->top_rise_count,
152 &last_top_rise_count_, &top_rise_count_);
153 UpdateWrappingCounter(data->top_fall_count,
154 &last_top_fall_count_, &top_fall_count_);
155 UpdateWrappingCounter(data->bottom_rise_count,
156 &last_bottom_rise_count_, &bottom_rise_count_);
157 UpdateWrappingCounter(data->bottom_fall_delay_count,
158 &last_bottom_fall_delay_count_, &bottom_fall_delay_count_);
159 UpdateWrappingCounter(data->bottom_fall_count,
160 &last_bottom_fall_count_, &bottom_fall_count_);
Daniel Petti3fe36542013-09-25 04:18:24 +0000161
162 drivetrain.position.MakeWithBuilder()
163 .right_encoder(drivetrain_translate(data->right_drive))
164 .left_encoder(-drivetrain_translate(data->left_drive))
165 .Send();
166
Daniel Petti3fe36542013-09-25 04:18:24 +0000167 shooter.position.MakeWithBuilder()
168 .position(shooter_translate(data->shooter))
169 .Send();
Daniel Petti3fe36542013-09-25 04:18:24 +0000170 }
171
172 ::std::unique_ptr<LibUSBDeviceHandle> dev_handle_;
173
174 int32_t top_rise_count_;
175 uint8_t last_top_rise_count_;
176 int32_t top_fall_count_;
177 uint8_t last_top_fall_count_;
178 int32_t bottom_rise_count_;
179 uint8_t last_bottom_rise_count_;
180 int32_t bottom_fall_delay_count_;
181 uint8_t last_bottom_fall_delay_count_;
182 int32_t bottom_fall_count_;
183 uint8_t last_bottom_fall_count_;
Daniel Petti3fe36542013-09-25 04:18:24 +0000184};
185
Daniel Pettibedbf8d2013-09-26 01:29:15 +0000186} // namespace bot3
Daniel Petti3fe36542013-09-25 04:18:24 +0000187
188int main() {
189 ::aos::Init();
Daniel Pettibedbf8d2013-09-26 01:29:15 +0000190 ::bot3::GyroBoardReader reader;
Daniel Petti3fe36542013-09-25 04:18:24 +0000191 reader.Run();
192 ::aos::Cleanup();
193 return 0;
194}