-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathIndoorLoiter.ino
336 lines (282 loc) · 9.9 KB
/
IndoorLoiter.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
#include <Time.h>
#include <TimeLib.h>
#include <Pozyx.h>
#include <Pozyx_definitions.h>
/*//#include <mavlink.h>*/
#include "C:\Users\rmackay9\Documents\GitHub\ardupilot\Build.ArduCopter\libraries\GCS_MAVLink\include\mavlink\v2.0\common\mavlink.h"
#include <SoftwareSerial.h>
#include <Wire.h>
/*#include <Time.h> // download from https://github.com/PaulStoffregen/Time */
//#include "C:\Users\rmackay9\Documents\GitHub\Time\Time.h"
////////////////// Pozyx Prams //////////////////////////////
#define NUM_ANCHORS 4
// the network id of the anchors: change these to the network ids of your anchors.
uint16_t anchors[4] = { 0x601C, // (0,0)
0x6020, // x-axis
0x6057, // y-axis
0x605E};
// only required for manual anchor calibration.
// Please change this to the coordinates measured for the anchors
int32_t anchors_x[NUM_ANCHORS] = {0, 18600, 0, 18600}; // anchor x-coorindates in mm (horizontal)
int32_t anchors_y[NUM_ANCHORS] = {0, 0, 10000, 10000}; // anchor y-coordinates in mm (vertical)
int32_t heights[NUM_ANCHORS] = {1420, 0, 0, 1450}; // anchor z-coordinates in mm
////////////////// MAVLINK Prams //////////////////////////////
#define LATITUDE_BASE (36.324187 * 1.0e7)
#define LONGITUDE_BASE (138.639212 * 1.0e7)
uint8_t buf[MAVLINK_MSG_ID_GPS_INPUT_LEN];
int32_t latitude = 0;
int32_t longitude = 0;
// RX TX serial for flight controller ex) Pixhawk
// https://github.com/PaulStoffregen/AltSoftSerial
SoftwareSerial fcboardSerial(10, 11); // rx, tx
////////////////////////////////////////////////
void setup()
{
Serial.begin(115200);
fcboardSerial.begin(57600);
if (Pozyx.begin() == POZYX_FAILURE) {
Serial.println(("ERR: shield"));
delay(100);
abort();
}
Serial.println(("V1.0"));
// clear all previous devices in the device list
Pozyx.clearDevices();
//int status = Pozyx.doAnchorCalibration(POZYX_2_5D, 10, num_anchors, anchors, heights);
/*int status = Pozyx.doAnchorCalibration(POZYX_2D, 10, num_anchors, anchors, heights);
if (status != POZYX_SUCCESS) {
Serial.println(status);
Serial.println(("ERROR: calibration"));
Serial.println(("Reset required"));
delay(100);
abort();
}*/
// if the automatic anchor calibration is unsuccessful, try manually setting the anchor coordinates.
// fot this, you must update the arrays anchors_x, anchors_y and heights above
// comment out the doAnchorCalibration block and the if-statement above if you are using manual mode
SetAnchorsManual();
printCalibrationResult();
Serial.println(("Waiting.."));
delay(5000);
Serial.println(("Starting: "));
}
void loop()
{
coordinates_t position;
int status = Pozyx.doPositioning(&position, POZYX_2_5D, 1000);
//int status = Pozyx.doPositioning(&position);
if (status == POZYX_SUCCESS) {
// print out the result
printCoordinates(position);
// send GPS MAVLINK message
SendGPSMAVLinkMessage(position);
} else {
Serial.println("fail");
}
}
// function to print the coordinates to the serial monitor
void printCoordinates(coordinates_t coor)
{
Serial.print("x:");
Serial.print(coor.x);
print_tab();
Serial.print("y:");
Serial.print(coor.y);
print_tab();
Serial.print("z:");
Serial.print(coor.z);
print_tab();
Serial.print("lat:");
Serial.print(latitude);
print_tab();
Serial.print("lng:");
Serial.print(longitude);
print_tab();
Serial.println();
}
void print_comma()
{
Serial.print(",");
}
void print_tab()
{
Serial.print("\t");
}
#define LOCATION_SCALING_FACTOR_INV_MM 0.08983204953368922f
#define DEG_TO_RAD (M_PI / 180.0f)
float longitude_scale(uint32_t lat)
{
static int32_t last_lat = 0;
static float scale = 1.0;
if (labs(last_lat - lat) < 100000) {
// we are within 0.01 degrees (about 1km) of the
// previous latitude. We can avoid the cos() and return
// the same scale factor.
return scale;
}
scale = cosf(lat * 1.0e-7f * DEG_TO_RAD);
if (scale < 0.01f) {
scale = 0.01f;
}
if (scale > 1.0f) {
scale = 1.0f;
}
last_lat = lat;
return scale;
}
void location_offset(int32_t &lat, int32_t &lng, int32_t offset_north_mm, int32_t offset_east_mm)
{
int32_t dlat = offset_north_mm * LOCATION_SCALING_FACTOR_INV_MM;
int32_t dlng = (offset_east_mm * LOCATION_SCALING_FACTOR_INV_MM) / longitude_scale(lat);
lat += dlat;
lng += dlng;
}
// print out the anchor coordinates (also required for the processing sketch)
void printCalibrationResult()
{
uint8_t list_size;
int status;
status = Pozyx.getDeviceListSize(&list_size);
Serial.print("list: ");
Serial.println(status*list_size);
if (list_size == 0) {
Serial.println("Cal fail.");
Serial.println(Pozyx.getSystemError());
return;
}
uint16_t device_ids[list_size];
status &= Pozyx.getDeviceIds(device_ids,list_size);
Serial.println(("Cal:"));
Serial.print(("Anchors found: "));
Serial.println(list_size);
coordinates_t anchor_coor;
for (int i=0; i<list_size; i++) {
Serial.print("A0x");
Serial.print(device_ids[i], HEX);
print_comma();
status = Pozyx.getDeviceCoordinates(device_ids[i], &anchor_coor);
Serial.print(anchor_coor.x);
print_comma();
Serial.print(anchor_coor.y);
print_comma();
Serial.println(anchor_coor.z);
}
}
// function to manually set the anchor coordinates
void SetAnchorsManual()
{
int i=0;
for (i=0; i<NUM_ANCHORS; i++) {
device_coordinates_t anchor;
anchor.network_id = anchors[i];
anchor.flag = 0x1;
anchor.pos.x = anchors_x[i];
anchor.pos.y = anchors_y[i];
anchor.pos.z = heights[i];
Pozyx.addDevice(anchor);
}
}
// GPS MAVLink message using Pozyx potision
void SendGPSMAVLinkMessage(coordinates_t position)
{
// Initialize the required buffers
mavlink_message_t msg;
/**
* @brief Pack a gps_input message
* @param system_id ID of this system
* @param component_id ID of this component (e.g. 200 for IMU)
* @param msg The MAVLink message to compress the data into
*
* @param time_usec Timestamp (micros since boot or Unix epoch)
* @param gps_id ID of the GPS for multiple GPS inputs
* @param ignore_flags Flags indicating which fields to ignore (see GPS_INPUT_IGNORE_FLAGS enum). All other fields must be provided.
* @param time_week_ms GPS time (milliseconds from start of GPS week)
* @param time_week GPS week number
* @param fix_type 0-1: no fix, 2: 2D fix, 3: 3D fix. 4: 3D with DGPS. 5: 3D with RTK
* @param lat Latitude (WGS84), in degrees * 1E7
* @param lon Longitude (WGS84), in degrees * 1E7
* @param alt Altitude (AMSL, not WGS84), in m (positive for up)
* @param hdop GPS HDOP horizontal dilution of position in m
* @param vdop GPS VDOP vertical dilution of position in m
* @param vn GPS velocity in m/s in NORTH direction in earth-fixed NED frame
* @param ve GPS velocity in m/s in EAST direction in earth-fixed NED frame
* @param vd GPS velocity in m/s in DOWN direction in earth-fixed NED frame
* @param speed_accuracy GPS speed accuracy in m/s
* @param horiz_accuracy GPS horizontal accuracy in m
* @param vert_accuracy GPS vertical accuracy in m
* @param satellites_visible Number of satellites visible.
* @return length of the message in bytes (excluding serial stream start sign)
*/
uint16_t ignore_flags = GPS_INPUT_IGNORE_FLAG_VEL_HORIZ|
GPS_INPUT_IGNORE_FLAG_VEL_VERT|
GPS_INPUT_IGNORE_FLAG_SPEED_ACCURACY|
GPS_INPUT_IGNORE_FLAG_HORIZONTAL_ACCURACY|
GPS_INPUT_IGNORE_FLAG_VERTICAL_ACCURACY;
uint32_t time_week_ms = 0;
uint16_t time_week = 0;
make_gps_time(time_week_ms, time_week);
// adjust position
latitude = LATITUDE_BASE;
longitude = LONGITUDE_BASE;
location_offset(latitude, longitude, position.y, position.x);
uint16_t len = mavlink_msg_gps_input_pack(
1,
0,
&msg,
micros(), // time_usec,
0, // gps_id,
ignore_flags,
time_week_ms, // time_week_ms,
time_week, // time_week,
3, // fix_type,
latitude, // latitude,
longitude, // longitude,
10, // altitude,
1.0f, // hdop,
1.0f, // vdop,
0.0f, // vn
0.0f, // ve
0.0f, // vd
0.0f, // speed_accuracy
0.0f, // horiz_accuracy
0.0f, // vert_accuracy,
14 // satellites_visible
);
// Copy the message to send buffer
len = mavlink_msg_to_send_buffer(buf, &msg);
// Send message
fcboardSerial.write(buf, len);
}
// calculate GPS time
// based ardupilot/libraries/AP_GPS/GPS_Backend.cpp
void make_gps_time(uint32_t &time_week_ms, uint16_t &time_week)
{
uint8_t year, mon, day, hour, min, sec;
uint16_t msec;
time_t now_time = now();
year = ::year(now_time);
mon = ::month(now_time);
day = ::day(now_time);
uint32_t v = millis();
msec = v % 1000; v /= 1000;
sec = v % 100; v /= 100;
min = v % 100; v /= 100;
hour = v % 100; v /= 100;
int8_t rmon = mon - 2;
if (0 >= rmon) {
rmon += 12;
year -= 1;
}
// get time in seconds since unix epoch
uint32_t ret = (year/4) - 15 + 367*rmon/12 + day;
ret += year*365 + 10501;
ret = ret*24 + hour;
ret = ret*60 + min;
ret = ret*60 + sec;
// convert to time since GPS epoch
ret -= 272764785UL;
// get GPS week and time
time_week = ret / (7*86400UL);
time_week_ms = (ret % (7*86400UL)) * 1000;
time_week_ms += msec;
}