Upload folder using huggingface_hub
Browse files- .DS_Store +0 -0
- .gitignore +1 -0
- Data_Collection_Scripts/README.md +3 -0
- Data_Collection_Scripts/arduino_master.ino +130 -0
- Data_Collection_Scripts/arduino_slave.ino +118 -0
- Data_Collection_Scripts/left.py +56 -0
- Data_Collection_Scripts/requirements.txt +1 -0
- Data_Collection_Scripts/right.py +57 -0
- Data_Collection_Scripts/run_legs.py +24 -0
- NewAccelMaster/NewAccelMaster.ino +90 -0
- NewAccelerometer/NewAccelerometer.ino +70 -0
- README.md +1 -0
- SimpleAccelMaster/SimpleAccelMaster.ino +78 -0
- SimpleAccelerometer/SimpleAccelerometer.ino +74 -0
- data/.DS_Store +0 -0
- data/processed/.DS_Store +0 -0
- data/processed/striding/data.pt +3 -0
- data/processed/striding/features.csv +0 -0
- data/processed/striding/labels.csv +0 -0
- data/processed/walking/data.pt +3 -0
- data/processed/walking/features.csv +0 -0
- data/processed/walking/labels.csv +0 -0
- data/unprocessed/StraightWalking/COM10.log +0 -0
- data/unprocessed/StraightWalking/COM3.log +0 -0
- data/unprocessed/StraightWalking/COM4.log +0 -0
- data/unprocessed/StraightWalking/COM5.log +0 -0
- data/unprocessed/SwerveWalking/COM10.log +0 -0
- data/unprocessed/SwerveWalking/COM3.log +0 -0
- data/unprocessed/SwerveWalking/COM4.log +0 -0
- data/unprocessed/SwerveWalking/COM5.log +0 -0
- data/unprocessed/WideStride/COM10.log +0 -0
- data/unprocessed/WideStride/COM3.log +0 -0
- data/unprocessed/WideStride/COM4.log +0 -0
- data/unprocessed/WideStride/COM5.log +0 -0
- data/unprocessed/striding/back.txt +0 -0
- data/unprocessed/striding/front.txt +0 -0
- data/unprocessed/walking/back.txt +0 -0
- data/unprocessed/walking/front.txt +0 -0
- model/.DS_Store +0 -0
- model/lstm/__pycache__/model.cpython-310.pyc +0 -0
- model/lstm/model.py +32 -0
- model/preprocess/preprocess.py +65 -0
- model/preprocess/run.sh +2 -0
- model/train/test.py +6 -0
- model/train/train.py +76 -0
- 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
|