recorderlegend1 commited on
Commit
e418c5a
·
verified ·
1 Parent(s): e1447c9

Upload folder using huggingface_hub

Browse files
Files changed (46) hide show
  1. .DS_Store +0 -0
  2. .gitignore +1 -0
  3. Data_Collection_Scripts/README.md +3 -0
  4. Data_Collection_Scripts/arduino_master.ino +130 -0
  5. Data_Collection_Scripts/arduino_slave.ino +118 -0
  6. Data_Collection_Scripts/left.py +56 -0
  7. Data_Collection_Scripts/requirements.txt +1 -0
  8. Data_Collection_Scripts/right.py +57 -0
  9. Data_Collection_Scripts/run_legs.py +24 -0
  10. NewAccelMaster/NewAccelMaster.ino +90 -0
  11. NewAccelerometer/NewAccelerometer.ino +70 -0
  12. README.md +1 -0
  13. SimpleAccelMaster/SimpleAccelMaster.ino +78 -0
  14. SimpleAccelerometer/SimpleAccelerometer.ino +74 -0
  15. data/.DS_Store +0 -0
  16. data/processed/.DS_Store +0 -0
  17. data/processed/striding/data.pt +3 -0
  18. data/processed/striding/features.csv +0 -0
  19. data/processed/striding/labels.csv +0 -0
  20. data/processed/walking/data.pt +3 -0
  21. data/processed/walking/features.csv +0 -0
  22. data/processed/walking/labels.csv +0 -0
  23. data/unprocessed/StraightWalking/COM10.log +0 -0
  24. data/unprocessed/StraightWalking/COM3.log +0 -0
  25. data/unprocessed/StraightWalking/COM4.log +0 -0
  26. data/unprocessed/StraightWalking/COM5.log +0 -0
  27. data/unprocessed/SwerveWalking/COM10.log +0 -0
  28. data/unprocessed/SwerveWalking/COM3.log +0 -0
  29. data/unprocessed/SwerveWalking/COM4.log +0 -0
  30. data/unprocessed/SwerveWalking/COM5.log +0 -0
  31. data/unprocessed/WideStride/COM10.log +0 -0
  32. data/unprocessed/WideStride/COM3.log +0 -0
  33. data/unprocessed/WideStride/COM4.log +0 -0
  34. data/unprocessed/WideStride/COM5.log +0 -0
  35. data/unprocessed/striding/back.txt +0 -0
  36. data/unprocessed/striding/front.txt +0 -0
  37. data/unprocessed/walking/back.txt +0 -0
  38. data/unprocessed/walking/front.txt +0 -0
  39. model/.DS_Store +0 -0
  40. model/lstm/__pycache__/model.cpython-310.pyc +0 -0
  41. model/lstm/model.py +32 -0
  42. model/preprocess/preprocess.py +65 -0
  43. model/preprocess/run.sh +2 -0
  44. model/train/test.py +6 -0
  45. model/train/train.py +76 -0
  46. sensor_calibration_data +38 -0
.DS_Store ADDED
Binary file (6.15 kB). View file
 
.gitignore ADDED
@@ -0,0 +1 @@
 
 
1
+ .idea/
Data_Collection_Scripts/README.md ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ Each leg requires one Arduino to be flashed as master, and one as slave.
2
+
3
+ The master Arduino should be connected to the Jetson.
Data_Collection_Scripts/arduino_master.ino ADDED
@@ -0,0 +1,130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <Wire.h>
2
+ extern TwoWire Wire1; // Declare Wire1 for secondary I²C bus
3
+ #include <SPI.h>
4
+ #include <Adafruit_LSM6DSOX.h>
5
+
6
+ #define CS_PIN 10 // Chip select pin for SPI
7
+
8
+ #define BUFFER_SIZE 48 // 12 floats * 4 bytes per float
9
+
10
+ // Sensor instances and addresses
11
+ Adafruit_LSM6DSOX sensor1;
12
+ uint8_t sensor1_addr = 0x6A; // Sensor 1 I2C address
13
+ Adafruit_LSM6DSOX sensor2;
14
+ uint8_t sensor2_addr = 0x6B; // Sensor 2 I2C address
15
+
16
+ // Arrays to hold sensor data
17
+ float masterData[12]; // Master's sensor data
18
+ float slaveData[12]; // Slave's sensor data
19
+
20
+ uint8_t slaveStorage[BUFFER_SIZE]; // Buffer to hold incoming data from slave
21
+
22
+ // Buffer to hold combined data for I2C transmission
23
+ #define TOTAL_DATA_SIZE 96 // 24 floats * 4 bytes per float
24
+ uint8_t i2cData[TOTAL_DATA_SIZE]; // Holds both masterData and slaveData
25
+
26
+ // Variables for I2C chunked transmission
27
+ volatile uint8_t requestedChunk = 0; // Chunk index requested by the master
28
+ #define CHUNK_SIZE 32 // Number of bytes per I2C chunk
29
+ #define TOTAL_CHUNKS ((TOTAL_DATA_SIZE + CHUNK_SIZE - 1) / CHUNK_SIZE) // Total number of chunks
30
+
31
+ void setup()
32
+ {
33
+ Serial.begin(115200); // Initialize Serial for debugging
34
+
35
+ // Initialize SPI communication
36
+ pinMode(CS_PIN, OUTPUT);
37
+ digitalWrite(CS_PIN, HIGH); // Deselect the slave
38
+ SPI.begin();
39
+ SPI.beginTransaction(SPISettings(21000000, MSBFIRST, SPI_MODE0));
40
+
41
+ // Initialize sensors on default I2C bus (Wire)
42
+ Wire.begin(); // Initialize default I2C bus as master
43
+ while (!sensor1.begin_I2C(sensor1_addr, &Wire))
44
+ {
45
+ Serial.println("Failed to initialize sensor1!");
46
+ delay(10);
47
+ }
48
+
49
+ while (!sensor2.begin_I2C(sensor2_addr, &Wire))
50
+ {
51
+ Serial.println("Failed to initialize sensor2!");
52
+ delay(10);
53
+ }
54
+
55
+ sensor1.setAccelDataRate(LSM6DS_RATE_416_HZ);
56
+ sensor2.setAccelDataRate(LSM6DS_RATE_416_HZ);
57
+
58
+ // Initialize I2C as a slave on the secondary I2C bus (Wire1)
59
+ Wire1.begin(0x08); // Join the I2C bus with address #8
60
+ Wire1.onReceive(receiveEvent); // Register the receive event handler
61
+ Wire1.onRequest(requestEvent); // Register the request event handler
62
+ }
63
+
64
+ void loop()
65
+ {
66
+ // Read master's sensor data
67
+ updateMasterSensorData();
68
+
69
+ // Transfer data byte by byte (sending dummy data)
70
+ digitalWrite(CS_PIN, LOW); // Select the slave
71
+ for (size_t i = 0; i < BUFFER_SIZE; i++)
72
+ {
73
+ slaveStorage[i] = SPI.transfer(0x00); // Send dummy byte and receive data
74
+ }
75
+ digitalWrite(CS_PIN, HIGH); // Deselect the slave
76
+
77
+ // Reconstruct floats received from slave
78
+ memcpy(slaveData, slaveStorage, sizeof(slaveData));
79
+
80
+ // Prepare data for I2C transmission
81
+
82
+ Serial.println(slaveData[0]);
83
+ prepareI2CData();
84
+ }
85
+
86
+ // Function to read master's sensor data
87
+ void updateMasterSensorData()
88
+ {
89
+
90
+ // Read sensor1 data
91
+ sensor1.readAcceleration(masterData[0], masterData[1], masterData[2]);
92
+ sensor1.readGyroscope(masterData[3], masterData[4], masterData[5]);
93
+
94
+ // Read sensor2 data
95
+ sensor2.readAcceleration(masterData[6], masterData[7], masterData[8]);
96
+ sensor2.readGyroscope(masterData[9], masterData[10], masterData[11]);
97
+ }
98
+
99
+ // Function to prepare data for I2C transmission
100
+ void prepareI2CData()
101
+ {
102
+ // Combine masterData and slaveData into i2cData buffer
103
+ memcpy(i2cData, masterData, sizeof(masterData)); // Copy masterData
104
+ memcpy(i2cData + sizeof(masterData), slaveData, sizeof(slaveData)); // Copy slaveData
105
+ }
106
+
107
+ // I2C receive event handler
108
+ void receiveEvent(int numBytes)
109
+ {
110
+ if (numBytes >= 1)
111
+ {
112
+ requestedChunk = Wire1.read(); // Read the requested chunk index
113
+ // Read additional bytes if needed (not in this case)
114
+ }
115
+ }
116
+
117
+ // I2C request event handler
118
+ void requestEvent()
119
+ {
120
+ // Send data in chunks of CHUNK_SIZE bytes based on requestedChunk
121
+ uint16_t offset = requestedChunk * CHUNK_SIZE;
122
+ uint8_t bytesToSend = CHUNK_SIZE;
123
+
124
+ if (offset + CHUNK_SIZE > TOTAL_DATA_SIZE)
125
+ {
126
+ bytesToSend = TOTAL_DATA_SIZE - offset;
127
+ }
128
+
129
+ Wire1.write(i2cData + offset, bytesToSend);
130
+ }
Data_Collection_Scripts/arduino_slave.ino ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <SPI.h>
2
+ #include <Adafruit_LSM6DSOX.h>
3
+ #include <stdint.h>
4
+
5
+ #define BUFFER_SIZE 48 // 12 floats * 4 bytes per float
6
+ #define SS_PIN 10
7
+
8
+ // Sensor instances and addresses
9
+ Adafruit_LSM6DSOX sensor1;
10
+ uint8_t sensor1_addr = 0x6A;
11
+ Adafruit_LSM6DSOX sensor2;
12
+ uint8_t sensor2_addr = 0x6B;
13
+
14
+ // Variables to hold sensor data
15
+ float sensorData[12]; // Array to hold sensor data
16
+
17
+ volatile uint8_t pos = 0;
18
+ volatile bool dataReady = false;
19
+ volatile bool transferComplete = false;
20
+
21
+ uint8_t sendStorage[BUFFER_SIZE]; // Buffer to store bytes to send to master
22
+
23
+ // SPI interrupt number for the SAM3X8E chip:
24
+ #define SPI0_INTERRUPT_NUMBER (IRQn_Type)24
25
+
26
+ void setup() {
27
+ Serial.begin(115200);
28
+ slaveBegin(SS_PIN); // Initialize SPI as slave on pin 10
29
+ }
30
+
31
+ void loop() {
32
+ if (transferComplete) {
33
+ transferComplete = false; // Reset flag
34
+
35
+ // Update sensor data
36
+ updateSensorData();
37
+
38
+ // Prepare data to send in next SPI transaction
39
+ memcpy(sendStorage, sensorData, sizeof(sensorData));
40
+
41
+
42
+ // Serial.println(sensorData[11]);
43
+ // Preload TDR with the first byte to send
44
+ REG_SPI0_TDR = sendStorage[0];
45
+ pos = 1; // Reset position for next transfer
46
+ }
47
+ }
48
+
49
+ void slaveBegin(uint8_t _pin) {
50
+ // Setup the SPI Interrupt registers
51
+ NVIC_ClearPendingIRQ(SPI0_INTERRUPT_NUMBER);
52
+ NVIC_EnableIRQ(SPI0_INTERRUPT_NUMBER);
53
+
54
+ // Initialize the SPI device with Arduino default values
55
+ SPI.begin(_pin);
56
+ REG_SPI0_CR = SPI_CR_SWRST; // Reset SPI
57
+
58
+ // Setup interrupt
59
+ REG_SPI0_IDR = SPI_IDR_TDRE | SPI_IDR_MODF | SPI_IDR_OVRES |
60
+ SPI_IDR_NSSR | SPI_IDR_TXEMPTY | SPI_IDR_UNDES;
61
+ REG_SPI0_IER = SPI_IER_RDRF;
62
+
63
+ // Setup the SPI registers
64
+ REG_SPI0_CR = SPI_CR_SPIEN; // Enable SPI
65
+ REG_SPI0_MR = SPI_MR_MODFDIS; // Slave and no modefault
66
+ REG_SPI0_CSR = SPI_MODE0; // DLYBCT=0, DLYBS=0, SCBR=0, 8-bit transfer
67
+
68
+ // Initialize sensors
69
+ while (!sensor1.begin_I2C(sensor1_addr)) {
70
+ Serial.println("Failed to initialize sensor1!");
71
+ delay(10);
72
+ }
73
+
74
+ while (!sensor2.begin_I2C(sensor2_addr)) {
75
+ Serial.println("Failed to initialize sensor2!");
76
+ delay(10);
77
+ }
78
+
79
+ sensor1.setAccelDataRate(LSM6DS_RATE_416_HZ);
80
+ sensor2.setAccelDataRate(LSM6DS_RATE_416_HZ);
81
+
82
+ // Update sensor data for the first transfer
83
+ updateSensorData();
84
+ memcpy(sendStorage, sensorData, sizeof(sensorData));
85
+
86
+ // Preload TDR with the first byte to send
87
+ REG_SPI0_TDR = sendStorage[0];
88
+ pos = 1; // Start position at 1 since first byte is already loaded
89
+ }
90
+
91
+ void updateSensorData() {
92
+ // Read sensor1 data
93
+ sensor1.readAcceleration(sensorData[0], sensorData[1], sensorData[2]);
94
+ sensor1.readGyroscope(sensorData[3], sensorData[4], sensorData[5]);
95
+
96
+ // Read sensor2 data
97
+ sensor2.readAcceleration(sensorData[6], sensorData[7], sensorData[8]);
98
+ sensor2.readGyroscope(sensorData[9], sensorData[10], sensorData[11]);
99
+ }
100
+
101
+ void SPI0_Handler(void) {
102
+ uint32_t status = REG_SPI0_SR;
103
+
104
+ // Check if data has been received
105
+ if (status & SPI_SR_RDRF) {
106
+ // Read byte from SPI data register
107
+ uint8_t received_byte = REG_SPI0_RDR & 0xFF;
108
+
109
+ // Load next byte to transmit
110
+ if (pos < BUFFER_SIZE) {
111
+ REG_SPI0_TDR = sendStorage[pos++];
112
+ } else {
113
+ // All bytes have been sent
114
+ transferComplete = true;
115
+ pos = 0; // Reset position for the next transfer
116
+ }
117
+ }
118
+ }
Data_Collection_Scripts/left.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from smbus2 import SMBus
2
+ import time
3
+ import struct
4
+
5
+ I2C_BUS_NUMBER = 1
6
+
7
+ # I2C address of the Arduino
8
+ ARDUINO_I2C_ADDRESS = 0x08
9
+
10
+ # Total number of bytes to read (24 floats * 4 bytes per float)
11
+ TOTAL_BYTES = 96
12
+
13
+ # Maximum bytes per I2C transaction (due to limitations)
14
+ CHUNK_SIZE = 32
15
+
16
+ OUTPUT_FILE = "left_data.txt"
17
+
18
+
19
+ def read_i2c_data(bus, addr, total_bytes, chunk_size):
20
+ data = []
21
+ chunks = (total_bytes + chunk_size - 1) // chunk_size
22
+ for chunk_index in range(chunks):
23
+ # Use read_i2c_block_data which sends a command byte before reading data
24
+ to_read = min(chunk_size, total_bytes - (chunk_index * chunk_size))
25
+ chunk_data = bus.read_i2c_block_data(addr, chunk_index, to_read)
26
+ data.extend(chunk_data)
27
+ return data
28
+
29
+
30
+
31
+ with SMBus(I2C_BUS_NUMBER) as bus, open(OUTPUT_FILE,'w') as f: # Use the correct I2C bus number
32
+ while True:
33
+ try:
34
+ # Read data in chunks
35
+ data = read_i2c_data(bus, ARDUINO_I2C_ADDRESS, TOTAL_BYTES, CHUNK_SIZE)
36
+
37
+ # Convert byte data to floats
38
+ floats = []
39
+ for i in range(0, TOTAL_BYTES, 4):
40
+ # Combine 4 bytes into a float
41
+ float_bytes = bytes(data[i:i+4])
42
+ value = struct.unpack('<f', float_bytes)[0] # '<f' for little-endian float
43
+ floats.append(value)
44
+
45
+ # Split into master and slave data
46
+ masterData = floats[:12]
47
+ slaveData = floats[12:]
48
+
49
+ # Print the data
50
+ f.write(f"{time.time()}\nM: {masterData}\nS:{slaveData}")
51
+ # print(f"{time.time()}\nM: {masterData}\nS:{slaveData}")
52
+
53
+ except Exception as e:
54
+ f.write(f"Error: {e}")
55
+ # print((f"Error: {e}"))
56
+
Data_Collection_Scripts/requirements.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ smbus2==0.5.0
Data_Collection_Scripts/right.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from smbus2 import SMBus
2
+ import time
3
+ import struct
4
+
5
+
6
+ I2C_BUS_NUMBER = 7
7
+
8
+ # I2C address of the Arduino
9
+ ARDUINO_I2C_ADDRESS = 0x08
10
+
11
+ # Total number of bytes to read (24 floats * 4 bytes per float)
12
+ TOTAL_BYTES = 96
13
+
14
+ # Maximum bytes per I2C transaction (due to limitations)
15
+ CHUNK_SIZE = 32
16
+
17
+ OUTPUT_FILE = "right_data.txt"
18
+
19
+
20
+ def read_i2c_data(bus, addr, total_bytes, chunk_size):
21
+ data = []
22
+ chunks = (total_bytes + chunk_size - 1) // chunk_size
23
+ for chunk_index in range(chunks):
24
+ # Use read_i2c_block_data which sends a command byte before reading data
25
+ to_read = min(chunk_size, total_bytes - (chunk_index * chunk_size))
26
+ chunk_data = bus.read_i2c_block_data(addr, chunk_index, to_read)
27
+ data.extend(chunk_data)
28
+ return data
29
+
30
+
31
+
32
+ with SMBus(I2C_BUS_NUMBER) as bus, open(OUTPUT_FILE,'w') as f: # Use the correct I2C bus number
33
+ while True:
34
+ try:
35
+ # Read data in chunks
36
+ data = read_i2c_data(bus, ARDUINO_I2C_ADDRESS, TOTAL_BYTES, CHUNK_SIZE)
37
+
38
+ # Convert byte data to floats
39
+ floats = []
40
+ for i in range(0, TOTAL_BYTES, 4):
41
+ # Combine 4 bytes into a float
42
+ float_bytes = bytes(data[i:i+4])
43
+ value = struct.unpack('<f', float_bytes)[0] # '<f' for little-endian float
44
+ floats.append(value)
45
+
46
+ # Split into master and slave data
47
+ masterData = floats[:12]
48
+ slaveData = floats[12:]
49
+
50
+ # Print the data
51
+ f.write(f"{time.time()}\nM: {masterData}\nS:{slaveData}")
52
+ # print(f"{time.time()}\nM: {masterData}\nS:{slaveData}")
53
+
54
+ except Exception as e:
55
+ f.write(f"Error: {e}")
56
+ # print((f"Error: {e}"))
57
+
Data_Collection_Scripts/run_legs.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """"
2
+ This file just runs both leg collections at once.
3
+ The 3 second delay between scripts is because we experienced some I2C errors when trying to
4
+ instantaneously access both I2C busses on the Jetson.
5
+ """
6
+
7
+ import subprocess
8
+ import time
9
+
10
+ DELAY_SECONDS = 3
11
+
12
+ right = 'right.py'
13
+ left = 'left.py'
14
+
15
+ print(f"Running {right}")
16
+ subprocess.run(["python",right])
17
+
18
+ print(f"Waiting {DELAY_SECONDS} seconds...")
19
+ time.sleep(DELAY_SECONDS)
20
+
21
+ print(f"Running {left}")
22
+ subprocess.run(["python",left])
23
+
24
+ print("Run complete.")
NewAccelMaster/NewAccelMaster.ino ADDED
@@ -0,0 +1,90 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Arduino LSM6DSOX - Simple Accelerometer
3
+
4
+ This example reads the acceleration values from the LSM6DSOX
5
+ sensor and continuously prints them to the Serial Monitor
6
+ or Serial Plotter.
7
+
8
+ The circuit:
9
+ - Arduino Nano RP2040 Connect
10
+
11
+ created 10 May 2021
12
+ by Arturo Guadalupi
13
+
14
+ This example code is in the public domain.
15
+ */
16
+
17
+ #include <Adafruit_LSM6DSOX.h>
18
+ #include <string>
19
+ #include <TimeLib.h>
20
+ Adafruit_LSM6DSOX sensor1;
21
+ uint8_t sensor1_addr = 0x6A;
22
+ Adafruit_LSM6DSOX sensor2;
23
+ uint8_t sensor2_addr = 0x6B;
24
+ String comma = ",";
25
+ String colon = ":";
26
+ float ax1, ay1, az1, ax2, gx1, gy1, gz1, ay2, az2, gx2, gy2, gz2;
27
+ uint32_t count;
28
+
29
+ void setup() {
30
+ pinMode(2, OUTPUT);
31
+ pinMode(3, OUTPUT);
32
+ pinMode(4, OUTPUT);
33
+
34
+ Serial.begin(115200);
35
+ while (!Serial);
36
+
37
+ while (!sensor1.begin_I2C(sensor1_addr)) {
38
+ Serial.println("Failed to initialize 0x6A!");
39
+ delay(10);
40
+ }
41
+
42
+ sensor1.setAccelDataRate(LSM6DS_RATE_6_66K_HZ);
43
+ Serial.print("Accelerometer sample rate = ");
44
+ Serial.print(sensor1.accelerationSampleRate());
45
+ Serial.println(" Hz");
46
+ Serial.println();
47
+ Serial.println("Acceleration in g's");
48
+ Serial.println("X\tY\tZ");
49
+
50
+ while (!sensor2.begin_I2C(sensor2_addr)) {
51
+ Serial.println("Failed to initialize 0x6B!");
52
+ delay(10);
53
+ }
54
+ sensor2.setAccelDataRate(LSM6DS_RATE_6_66K_HZ);
55
+
56
+ count = 0;
57
+
58
+ while(!Serial.available()); // Wait for serial input
59
+
60
+ digitalWrite(2, HIGH);
61
+ digitalWrite(2, LOW);
62
+
63
+ digitalWrite(3, HIGH); // Send signal pulse to others to sync counts
64
+ digitalWrite(3, LOW);
65
+
66
+ digitalWrite(4, HIGH);
67
+ digitalWrite(4, LOW);
68
+
69
+ }
70
+
71
+ void loop() {
72
+
73
+ digitalWrite(2, HIGH);
74
+ digitalWrite(2, LOW);
75
+
76
+ digitalWrite(3, HIGH); // Send signal pulse to others to process
77
+ digitalWrite(3, LOW);
78
+
79
+ digitalWrite(4, HIGH);
80
+ digitalWrite(4, LOW);
81
+
82
+ sensor1.readAcceleration(ax1, ay1, az1);
83
+ sensor1.readGyroscope(gx1, gy1, gz1);
84
+ sensor2.readAcceleration(ax2, ay2, az2); // Read in sensor data
85
+ sensor2.readGyroscope(gx2, gy2, gz2);
86
+
87
+ Serial.print(count++ + colon + ax1 + comma + ay1 + comma + az1 + comma + ax2 + comma + ay2 + comma + az2 + comma);
88
+ Serial.println(gx1 + comma + gy1 + comma + gz1 + comma + gx2 + comma + gy2 + comma + gz2);
89
+
90
+ }
NewAccelerometer/NewAccelerometer.ino ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Arduino LSM6DSOX - Simple Accelerometer
3
+
4
+ This example reads the acceleration values from the LSM6DSOX
5
+ sensor and continuously prints them to the Serial Monitor
6
+ or Serial Plotter.
7
+
8
+ The circuit:
9
+ - Arduino Nano RP2040 Connect
10
+
11
+ created 10 May 2021
12
+ by Arturo Guadalupi
13
+
14
+ This example code is in the public domain.
15
+ */
16
+
17
+ #include <Adafruit_LSM6DSOX.h>
18
+ #include <string>
19
+ #include <TimeLib.h>
20
+ Adafruit_LSM6DSOX sensor1;
21
+ uint8_t sensor1_addr = 0x6A;
22
+ Adafruit_LSM6DSOX sensor2;
23
+ uint8_t sensor2_addr = 0x6B;
24
+ String comma = ",";
25
+ String colon = ":";
26
+ float ax1, ay1, az1, ax2, gx1, gy1, gz1, ay2, az2, gx2, gy2, gz2;
27
+ uint32_t count;
28
+
29
+ void setup() {
30
+ pinMode(2, INPUT);
31
+
32
+ Serial.begin(115200);
33
+ while (!Serial);
34
+
35
+ while (!sensor1.begin_I2C(sensor1_addr)) {
36
+ Serial.println("Failed to initialize 0x6A!");
37
+ delay(10);
38
+ }
39
+
40
+ sensor1.setAccelDataRate(LSM6DS_RATE_6_66K_HZ);
41
+ Serial.print("Accelerometer sample rate = ");
42
+ Serial.print(sensor1.accelerationSampleRate());
43
+ Serial.println(" Hz");
44
+ Serial.println();
45
+ Serial.println("Acceleration in g's");
46
+ Serial.println("X\tY\tZ");
47
+
48
+ while (!sensor2.begin_I2C(sensor2_addr)) {
49
+ Serial.println("Failed to initialize 0x6B!");
50
+ delay(10);
51
+ }
52
+ sensor2.setAccelDataRate(LSM6DS_RATE_6_66K_HZ);
53
+
54
+ while(!digitalRead(2)); // Wait for signal to start
55
+ count = 0;
56
+ }
57
+
58
+ void loop() {
59
+
60
+ while(!digitalRead(2)); // Wait for signal to proceed
61
+
62
+ sensor1.readAcceleration(ax1, ay1, az1);
63
+ sensor1.readGyroscope(gx1, gy1, gz1);
64
+ sensor2.readAcceleration(ax2, ay2, az2); // Read in sensor data
65
+ sensor2.readGyroscope(gx2, gy2, gz2);
66
+
67
+ Serial.print(count++ + colon + ax1 + comma + ay1 + comma + az1 + comma + gx1 + comma + gy1 + comma + gz1);
68
+ Serial.println(ax2 + comma + ay2 + comma + az2 + comma + gx2 + comma + gy2 + comma + gz2);
69
+
70
+ }
README.md ADDED
@@ -0,0 +1 @@
 
 
1
+ #starx
SimpleAccelMaster/SimpleAccelMaster.ino ADDED
@@ -0,0 +1,78 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Arduino LSM6DSOX - Simple Accelerometer
3
+
4
+ This example reads the acceleration values from the LSM6DSOX
5
+ sensor and continuously prints them to the Serial Monitor
6
+ or Serial Plotter.
7
+
8
+ The circuit:
9
+ - Arduino Nano RP2040 Connect
10
+
11
+ created 10 May 2021
12
+ by Arturo Guadalupi
13
+
14
+ This example code is in the public domain.
15
+ */
16
+
17
+ #include <Adafruit_LSM6DSOX.h>
18
+ #include <string>
19
+ #include <TimeLib.h>
20
+ Adafruit_LSM6DSOX sensor1;
21
+ uint8_t sensor1_addr = 0x6A;
22
+ Adafruit_LSM6DSOX sensor2;
23
+ uint8_t sensor2_addr = 0x6B;
24
+ String comma = ",";
25
+ float ax1, ay1, az1, ax2, gx1, gy1, gz1, ay2, az2, gx2, gy2, gz2;
26
+ uint32_t time_start;
27
+
28
+ void setup() {
29
+ pinMode(2, OUTPUT);
30
+ pinMode(3, OUTPUT);
31
+ pinMode(4, OUTPUT);
32
+
33
+ Serial.begin(115200);
34
+ while (!Serial);
35
+
36
+ while (!sensor1.begin_I2C(sensor1_addr)) {
37
+ Serial.println("Failed to initialize 0x6A!");
38
+ delay(10);
39
+ }
40
+
41
+ sensor1.setAccelDataRate(LSM6DS_RATE_416_HZ);
42
+ Serial.print("Accelerometer sample rate = ");
43
+ Serial.print(sensor1.accelerationSampleRate());
44
+ Serial.println(" Hz");
45
+ Serial.println();
46
+ Serial.println("Acceleration in g's");
47
+ Serial.println("X\tY\tZ");
48
+
49
+ while (!sensor2.begin_I2C(sensor2_addr)) {
50
+ Serial.println("Failed to initialize 0x6B!");
51
+ delay(10);
52
+ }
53
+ sensor2.setAccelDataRate(LSM6DS_RATE_416_HZ);
54
+
55
+ digitalWrite(2, HIGH);
56
+ digitalWrite(3, HIGH);
57
+ digitalWrite(4, HIGH);
58
+
59
+ time_start = millis();
60
+ }
61
+
62
+ void loop() {
63
+ if (sensor1.accelerationAvailable())
64
+ sensor1.readAcceleration(ax1, ay1, az1);
65
+
66
+ if (sensor1.gyroscopeAvailable())
67
+ sensor1.readGyroscope(gx1, gy1, gz1);
68
+
69
+ if (sensor2.accelerationAvailable())
70
+ sensor2.readAcceleration(ax2, ay2, az2);
71
+
72
+ if (sensor2.gyroscopeAvailable())
73
+ sensor2.readGyroscope(gx2, gy2, gz2);
74
+
75
+ Serial.print((millis() - time_start) + comma + ax1 + comma + ay1 + comma + az1 + comma + ax2 + comma + ay2 + comma + az2 + comma);
76
+ Serial.println(gx1 + comma + gy1 + comma + gz1 + comma + gx2 + comma + gy2 + comma + gz2);
77
+
78
+ }
SimpleAccelerometer/SimpleAccelerometer.ino ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Arduino LSM6DSOX - Simple Accelerometer
3
+
4
+ This example reads the acceleration values from the LSM6DSOX
5
+ sensor and continuously prints them to the Serial Monitor
6
+ or Serial Plotter.
7
+
8
+ The circuit:
9
+ - Arduino Nano RP2040 Connect
10
+
11
+ created 10 May 2021
12
+ by Arturo Guadalupi
13
+
14
+ This example code is in the public domain.
15
+ */
16
+
17
+ #include <Adafruit_LSM6DSOX.h>
18
+ #include <string>
19
+ #include <TimeLib.h>
20
+ Adafruit_LSM6DSOX sensor1;
21
+ uint8_t sensor1_addr = 0x6A;
22
+ Adafruit_LSM6DSOX sensor2;
23
+ uint8_t sensor2_addr = 0x6B;
24
+ String comma = ",";
25
+ float ax1, ay1, az1, ax2, gx1, gy1, gz1, ay2, az2, gx2, gy2, gz2;
26
+ uint32_t time_start;
27
+
28
+ void setup() {
29
+ pinMode(2, INPUT);
30
+
31
+ Serial.begin(115200);
32
+ while (!Serial);
33
+
34
+ while (!sensor1.begin_I2C(sensor1_addr)) {
35
+ Serial.println("Failed to initialize 0x6A!");
36
+ delay(10);
37
+ }
38
+
39
+ sensor1.setAccelDataRate(LSM6DS_RATE_416_HZ);
40
+ Serial.print("Accelerometer sample rate = ");
41
+ Serial.print(sensor1.accelerationSampleRate());
42
+ Serial.println(" Hz");
43
+ Serial.println();
44
+ Serial.println("Acceleration in g's");
45
+ Serial.println("X\tY\tZ");
46
+
47
+ while (!sensor2.begin_I2C(sensor2_addr)) {
48
+ Serial.println("Failed to initialize 0x6B!");
49
+ delay(10);
50
+ }
51
+ sensor2.setAccelDataRate(LSM6DS_RATE_416_HZ);
52
+
53
+ while(!digitalRead(2));
54
+
55
+ time_start = millis();
56
+ }
57
+
58
+ void loop() {
59
+
60
+ if (sensor1.accelerationAvailable())
61
+ sensor1.readAcceleration(ax1, ay1, az1);
62
+
63
+ if (sensor1.gyroscopeAvailable())
64
+ sensor1.readGyroscope(gx1, gy1, gz1);
65
+
66
+ if (sensor2.accelerationAvailable())
67
+ sensor2.readAcceleration(ax2, ay2, az2);
68
+
69
+ if (sensor2.gyroscopeAvailable())
70
+ sensor2.readGyroscope(gx2, gy2, gz2);
71
+
72
+ Serial.print((millis() - time_start) + comma + ax1 + comma + ay1 + comma + az1 + comma + gx1 + comma + gy1 + comma + gz1);
73
+ Serial.println(ax2 + comma + ay2 + comma + az2 + comma + gx2 + comma + gy2 + comma + gz2);
74
+ }
data/.DS_Store ADDED
Binary file (6.15 kB). View file
 
data/processed/.DS_Store ADDED
Binary file (6.15 kB). View file
 
data/processed/striding/data.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c52b74a822f57953dbc97ca68a8f697a7fd756cd8da944b1977b0bb138474a73
3
+ size 2337121286
data/processed/striding/features.csv ADDED
The diff for this file is too large to render. See raw diff
 
data/processed/striding/labels.csv ADDED
The diff for this file is too large to render. See raw diff
 
data/processed/walking/data.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:2a738719e7697a42803ddf3efd0481a3d23f81b11fe2aa9c41b7ab3868d028b6
3
+ size 2337121286
data/processed/walking/features.csv ADDED
The diff for this file is too large to render. See raw diff
 
data/processed/walking/labels.csv ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/StraightWalking/COM10.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/StraightWalking/COM3.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/StraightWalking/COM4.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/StraightWalking/COM5.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/SwerveWalking/COM10.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/SwerveWalking/COM3.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/SwerveWalking/COM4.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/SwerveWalking/COM5.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/WideStride/COM10.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/WideStride/COM3.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/WideStride/COM4.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/WideStride/COM5.log ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/striding/back.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/striding/front.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/walking/back.txt ADDED
The diff for this file is too large to render. See raw diff
 
data/unprocessed/walking/front.txt ADDED
The diff for this file is too large to render. See raw diff
 
model/.DS_Store ADDED
Binary file (6.15 kB). View file
 
model/lstm/__pycache__/model.cpython-310.pyc ADDED
Binary file (1.13 kB). View file
 
model/lstm/model.py ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+ import torch.nn as nn
3
+
4
+ class STARM(nn.Module):
5
+ def __init__(self, num_classes, input_size, hidden_size, num_layers):
6
+ super().__init__()
7
+ self.num_classes = num_classes # Output size
8
+ self.num_layers = num_layers # Number of recurrent layers in the LSTM
9
+ self.input_size = input_size # Input size
10
+ self.hidden_size = hidden_size # Neurons in each LSTM layer
11
+
12
+ # LSTM model
13
+ self.lstm = nn.LSTM(input_size=input_size, hidden_size=hidden_size,
14
+ num_layers=num_layers, batch_first=True, dropout=0)
15
+
16
+ self.fc_1 = nn.Linear(hidden_size, 128) # Fully connected layer
17
+ self.fc_2 = nn.Linear(128, num_classes) # Fully connected last layer
18
+ self.relu = nn.ReLU() # ReLU activation
19
+
20
+ def forward(self, x):
21
+ # Initialize hidden and cell states
22
+ h_0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size, device=x.device)
23
+ c_0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size, device=x.device)
24
+
25
+ # Propagate input through LSTM
26
+ output, (hn, cn) = self.lstm(x) # Shape: (batch_size, seq_length, hidden_size)
27
+
28
+ # Apply fully connected layers and ReLU for each time step
29
+ out = self.fc_1(output) # Shape: (batch_size, seq_length, 128)
30
+ out = self.relu(out) # Apply ReLU
31
+ out = self.fc_2(out) # Shape: (batch_size, seq_length, num_classes)
32
+ return out
model/preprocess/preprocess.py ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+ import torch
4
+ import sys
5
+ import os
6
+ from sklearn.preprocessing import StandardScaler,MinMaxScaler
7
+ np.set_printoptions(suppress=True)
8
+
9
+ ss,mm = StandardScaler(), MinMaxScaler()
10
+ thigh = pd.read_csv(f"../../data/unprocessed/{sys.argv[1]}/front.txt",delimiter=',',usecols =[i for i in range(13) if i != 0])
11
+ shin = pd.read_csv(f"../../data/unprocessed/{sys.argv[1]}/back.txt",delimiter=',',usecols =[i for i in range(13) if i != 0])
12
+ thigh,shin = thigh.dropna(),shin.dropna()
13
+ delta = len(thigh) - len(shin)
14
+
15
+ thigh = thigh[delta:]
16
+ thigh.reset_index(inplace=True)
17
+ thigh,shin = thigh[:55000],shin[:55000]
18
+
19
+ for col in thigh.columns:
20
+ thigh.rename(columns={col:col+"_th"},inplace=True)
21
+ shin.rename(columns={col:col+"_sh"},inplace=True)
22
+
23
+
24
+ p_columns_th = [col for col in thigh.columns if col.startswith('p')]
25
+ s_columns_th = [col for col in thigh.columns if col.startswith('s')]
26
+ p_columns_sh = [col for col in shin.columns if col.startswith('p')]
27
+ s_columns_sh = [col for col in shin.columns if col.startswith('s')]
28
+
29
+
30
+
31
+ features = thigh[s_columns_th]
32
+ features = pd.concat([features,shin[s_columns_sh]],axis=1)
33
+
34
+ labels = thigh[p_columns_th]
35
+ labels = pd.concat([labels,shin[p_columns_sh]],axis=1)
36
+
37
+ features_scaled = pd.DataFrame(ss.fit_transform(features), columns=features.columns)
38
+ labels_scaled = pd.DataFrame(mm.fit_transform(labels), columns=labels.columns)
39
+
40
+ os.makedirs(f"../../data/processed/{sys.argv[1]}",exist_ok=True)
41
+ features.to_csv(f"../../data/processed/{sys.argv[1]}/features.csv")
42
+ labels.to_csv(f"../../data/processed/{sys.argv[1]}/labels.csv")
43
+
44
+ def preprocess_data(features_df, labels_df, lookback_window, predict_window, output_file):
45
+ lookback_window *= 150
46
+ predict_window *= 150
47
+
48
+ total_samples = len(features_df) - lookback_window - predict_window
49
+
50
+ x_data = torch.zeros((total_samples, lookback_window, features_df.shape[1]))
51
+ y_data = torch.zeros((total_samples, predict_window, labels_df.shape[1]))
52
+
53
+ for idx, i in enumerate(range(lookback_window, len(features_df) - predict_window)):
54
+ if idx % 1000 == 0:
55
+ print(f"Processing sample {idx}/{total_samples}...")
56
+
57
+ x_data[idx] = torch.tensor(features_df.iloc[i - lookback_window:i].values, dtype=torch.float32)
58
+ y_data[idx] = torch.tensor(labels_df.iloc[i:i + predict_window].values, dtype=torch.float32)
59
+
60
+ torch.save({"x": x_data, "y": y_data}, output_file)
61
+ print(f"Preprocessed data saved to {output_file}")
62
+
63
+ preprocess_data(features_scaled,labels_scaled,3,3,f"../../data/processed/{sys.argv[1]}/data.pt")
64
+
65
+
model/preprocess/run.sh ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ python preprocess.py striding
2
+ python preprocess.py walking
model/train/test.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ np.set_printoptions(suppress=True)
3
+ data = np.load('../../data/processed/striding/data.npz')
4
+ data_check = np.load('../../data/processed/striding/striding.npz')
5
+ y = data['y']
6
+ print(y[0])
model/train/train.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import torch
3
+ import sys, os
4
+ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
5
+ from tqdm import tqdm
6
+ from lstm.model import STARM
7
+ np.set_printoptions(suppress=True)
8
+ device = torch.device('cpu')
9
+ torch.cuda.empty_cache()
10
+
11
+
12
+ data = torch.load('../../data/processed/striding/data.pt')
13
+ train_split = int(.85*54100)
14
+ X = data['x']
15
+ y = data['y']
16
+
17
+ X_train = X[:train_split] #, X_test = X[:train_split], X[train_split:]
18
+ y_train = y[:train_split] #, y_test = y[:train_split], y[train_split:]
19
+
20
+ X_train = X_train.to(device)
21
+ # X_test = X_test.to(device)
22
+ y_train = y_train.to(device)
23
+ # y_test = y_test.to(device)
24
+
25
+
26
+ n_epoch = 1000
27
+ lr = 0.001
28
+ input_size = 12
29
+ hidden_size = 2
30
+ num_lstm = 1
31
+ num_classes = 12
32
+
33
+ lstm = STARM(
34
+ num_classes,
35
+ input_size,
36
+ hidden_size,
37
+ num_lstm
38
+ ).to(device)
39
+
40
+ loss_fn = torch.nn.MSELoss()
41
+ optimiser = torch.optim.Adam(lstm.parameters(), lr=lr)
42
+
43
+
44
+ def training_loop(n_epochs, lstm, optimiser, loss_fn, X_train, y_train, batch_size=541000):
45
+ dataset_size = X_train.size(0)
46
+ num_batches = (dataset_size + batch_size - 1) // batch_size # Number of batches
47
+
48
+ for epoch in range(n_epochs):
49
+ lstm.train()
50
+ epoch_loss = 0.0 # To accumulate loss for the epoch
51
+
52
+ # Progress bar for each epoch
53
+ with tqdm(total=num_batches, desc=f"Epoch {epoch + 1}/{n_epochs}", unit="batch") as pbar:
54
+ for i in range(0, dataset_size, batch_size):
55
+ # Get batch
56
+ X_batch = X_train[i:i + batch_size]
57
+ y_batch = y_train[i:i + batch_size]
58
+
59
+ # Forward pass
60
+ outputs = lstm(X_batch)
61
+ optimiser.zero_grad()
62
+
63
+ # Compute loss
64
+ loss = loss_fn(outputs, y_batch)
65
+ loss.backward()
66
+ optimiser.step()
67
+
68
+ # Update progress bar and accumulate epoch loss
69
+ epoch_loss += loss.item()
70
+ pbar.set_postfix({"loss": loss.item()})
71
+ pbar.update(1) # Increment progress bar by 1 batch
72
+
73
+ print(f"Epoch {epoch + 1} completed. Average loss: {epoch_loss / num_batches:.5f}")
74
+
75
+
76
+ training_loop(n_epochs=n_epoch,lstm=lstm,optimiser=optimiser,loss_fn=loss_fn,X_train=X_train,y_train=y_train)
sensor_calibration_data ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1
2
+ 0.0136, -0.008133, 0.0043
3
+
4
+ 2
5
+ 0.0049, 0.0006, -0.0086
6
+ 0.0006, 0.0037, -0.0122
7
+ 0.0055, 0.0012, -0.0098
8
+
9
+ 3
10
+ 0.0086, -0.0012, 0.0031
11
+ 0.0086, 0.0000, 0.0031
12
+ 0.0086, 0.0000, 0.0024
13
+
14
+ 4
15
+ 0.0000, -0.0031, 0.0061
16
+ 0.0000, -0.0037, 0.0061
17
+ 0.0000, -0.0037, 0.0061
18
+
19
+ 5
20
+ 0.0073, -0.0079, 0.0024
21
+ 0.0067, -0.0079, 0.0024
22
+ 0.0073, -0.0079, 0.0024
23
+
24
+ 7
25
+ -0.0012, -0.0049, -0.0159
26
+ -0.0012, -0.0049, -0.0147
27
+ -0.0012, -0.0049, -0.0153
28
+
29
+ 9
30
+ 0.0018, -0.0061, 0.0000
31
+ 0.0012, -0.0061, 0.0000
32
+ 0.0018, -0.0061, -0.0006
33
+
34
+ 10
35
+ 0.0086, -0.0079, -0.0006
36
+
37
+ 11
38
+ -0.0073, -0.0073, -0.0012