# IMU Accelerometer & Gyroscope

This example shows accelerometer and gyroscope at a combined/synchronized 400 Hz rate using the onboard IMU. Returns acceleration
[m/s^2] and angular velocity [rad/s].

## Demo

Example script output

```bash
~/examples/IMU$ python3 imu_gyroscope_accelerometer.py
Accelerometer timestamp: 27 days, 4:31:26.532170
Latency [ms]: 0:00:00.004806
Accelerometer [m/s^2]: x: -0.098162 y: -0.062249 z: -9.715671
Gyroscope timestamp: 27 days, 4:31:26.532170
Gyroscope [rad/s]: x: 0.002131 y: 0.019175 z: 0.001065
Accelerometer timestamp: 27 days, 4:31:26.534664
Latency [ms]: 0:00:00.006309
Accelerometer [m/s^2]: x: -0.064643 y: -0.119710 z: -9.758766
Gyroscope timestamp: 27 days, 4:31:26.534664
Gyroscope [rad/s]: x: 0.002131 y: 0.019175 z: 0.002131
```

This example requires the DepthAI v3 API, see [installation instructions](https://docs.luxonis.com/software-v3/depthai.md).

## Pipeline

### examples/imu_gyroscope_accelerometer.pipeline.json

```json
{"pipeline": {"connections": [{"node1Id": 0, "node1Output": "out", "node1OutputGroup": "", "node2Id": 1, "node2Input": "in", "node2InputGroup": ""}], "globalProperties": {"calibData": null, "cameraTuningBlobSize": null, "cameraTuningBlobUri": "", "leonCssFrequencyHz": 700000000.0, "leonMssFrequencyHz": 700000000.0, "pipelineName": null, "pipelineVersion": null, "sippBufferSize": 18432, "sippDmaBufferSize": 16384, "xlinkChunkSize": -1}, "nodes": [[1, {"alias": "", "id": 1, "ioInfo": [[["", "in"], {"blocking": true, "group": "", "id": 2, "name": "in", "queueSize": 3, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "XLinkOut", "parentId": -1, "properties": {"maxFpsLimit": -1.0, "metadataOnly": false, "streamName": "__x_0_out"}}], [0, {"alias": "", "id": 0, "ioInfo": [[["", "out"], {"blocking": false, "group": "", "id": 1, "name": "out", "queueSize": 8, "type": 0, "waitForMessage": false}], [["", "mockIn"], {"blocking": true, "group": "", "id": 0, "name": "mockIn", "queueSize": 3, "type": 3, "waitForMessage": false}]], "logLevel": 3, "name": "IMU", "parentId": -1, "properties": {"batchReportThreshold": 1, "enableFirmwareUpdate": false, "imuSensors": [{"changeSensitivity": 0, "reportRate": 480, "sensitivityEnabled": false, "sensitivityRelative": false, "sensorId": 20}, {"changeSensitivity": 0, "reportRate": 400, "sensitivityEnabled": false, "sensitivityRelative": false, "sensorId": 21}], "maxBatchReports": 10}}]]}}
```

## Source code

#### Python

```python
#!/usr/bin/env python3
import depthai as dai

def timeDeltaToMilliS(delta) -> float:
    return delta.total_seconds()*1000

# Create pipeline
with dai.Pipeline() as pipeline:
    # Define sources and outputs
    imu = pipeline.create(dai.node.IMU)

    # enable ACCELEROMETER_UNCALIBRATED at 500 hz rate
    imu.enableIMUSensor(dai.IMUSensor.ACCELEROMETER_UNCALIBRATED, 480)
    # enable GYROSCOPE_UNCALIBRATED at 400 hz rate
    imu.enableIMUSensor(dai.IMUSensor.GYROSCOPE_UNCALIBRATED, 400)
    # it's recommended to set both setBatchReportThreshold and setMaxBatchReports to 20 when integrating in a pipeline with a lot of input/output connections
    # above this threshold packets will be sent in batch of X, if the host is not blocked and USB bandwidth is available
    imu.setBatchReportThreshold(1)
    # maximum number of IMU packets in a batch, if it's reached device will block sending until host can receive it
    # if lower or equal to batchReportThreshold then the sending is always blocking on device
    # useful to reduce device's CPU load  and number of lost packets, if CPU load is high on device side due to multiple nodes
    imu.setMaxBatchReports(10)

    imuQueue = imu.out.createOutputQueue(maxSize=50, blocking=False)

    pipeline.start()
    baseTs = None
    while pipeline.isRunning():
        try:
            imuData = imuQueue.get()
        except KeyboardInterrupt:
            break
        assert isinstance(imuData, dai.IMUData)
        imuPackets = imuData.packets
        for imuPacket in imuPackets:
            acceleroValues = imuPacket.acceleroMeter
            gyroValues = imuPacket.gyroscope

            acceleroTs = acceleroValues.getTimestamp()
            gyroTs = gyroValues.getTimestamp()

            imuF = "{:.06f}"
            tsF  = "{:.03f}"

            print(f"Accelerometer timestamp: {acceleroTs}")
            print(f"Latency [ms]: {dai.Clock.now() - acceleroValues.getTimestamp()}")
            print(f"Accelerometer [m/s^2]: x: {imuF.format(acceleroValues.x)} y: {imuF.format(acceleroValues.y)} z: {imuF.format(acceleroValues.z)}")
            print(f"Gyroscope timestamp: {gyroTs}")
            print(f"Gyroscope [rad/s]: x: {imuF.format(gyroValues.x)} y: {imuF.format(gyroValues.y)} z: {imuF.format(gyroValues.z)} ")
            print()
```

#### C++

```cpp
#include <atomic>
#include <chrono>
#include <csignal>
#include <iomanip>
#include <iostream>
#include <memory>

#include "depthai/depthai.hpp"

std::atomic<bool> quitEvent(false);

void signalHandler(int) {
    quitEvent = true;
}

// Helper function to convert time delta to milliseconds
float timeDeltaToMilliS(const std::chrono::steady_clock::duration& delta) {
    return std::chrono::duration_cast<std::chrono::milliseconds>(delta).count();
}

int main() {
    signal(SIGTERM, signalHandler);
    signal(SIGINT, signalHandler);

    // Create pipeline
    dai::Pipeline pipeline;

    // Define sources and outputs
    auto imu = pipeline.create<dai::node::IMU>();

    // Enable ACCELEROMETER_UNCALIBRATED at 480 hz rate
    imu->enableIMUSensor(dai::IMUSensor::ACCELEROMETER_UNCALIBRATED, 480);
    // Enable GYROSCOPE_UNCALIBRATED at 400 hz rate
    imu->enableIMUSensor(dai::IMUSensor::GYROSCOPE_UNCALIBRATED, 400);

    // Set batch report threshold and max batch reports
    imu->setBatchReportThreshold(1);
    imu->setMaxBatchReports(10);

    // Create output queue
    auto imuQueue = imu->out.createOutputQueue(50, false);

    // Start pipeline
    pipeline.start();
    std::cout << "IMU pipeline started. Press Ctrl+C to stop." << std::endl;

    // Set up output formatting
    std::cout << std::fixed << std::setprecision(6);

    while(pipeline.isRunning() && !quitEvent) {
        auto imuData = imuQueue->get<dai::IMUData>();
        if(imuData == nullptr) continue;

        for(const auto& imuPacket : imuData->packets) {
            auto acceleroValues = imuPacket.acceleroMeter;
            auto gyroValues = imuPacket.gyroscope;

            auto acceleroTs = acceleroValues.getTimestamp();
            auto gyroTs = gyroValues.getTimestamp();

            // Print accelerometer data
            std::cout << "Accelerometer timestamp: " << acceleroTs.time_since_epoch().count() << std::endl;
            std::cout << "Latency [ms]: " << timeDeltaToMilliS(std::chrono::steady_clock::now() - acceleroValues.getTimestamp()) << std::endl;
            std::cout << "Accelerometer [m/s^2]: x: " << acceleroValues.x << " y: " << acceleroValues.y << " z: " << acceleroValues.z << std::endl;

            // Print gyroscope data
            std::cout << "Gyroscope timestamp: " << gyroTs.time_since_epoch().count() << std::endl;
            std::cout << "Gyroscope [rad/s]: x: " << gyroValues.x << " y: " << gyroValues.y << " z: " << gyroValues.z << std::endl;
        }
    }

    // Cleanup
    pipeline.stop();
    pipeline.wait();

    return 0;
}
```

### Need assistance?

Head over to [Discussion Forum](https://discuss.luxonis.com/) for technical support or any other questions you might have.
