Hi everyone! I’m new to Unreal Engine and working on a hardware project using the ESP32 with a BNO085 IMU sensor. I’m trying to get full 9-DOF motion tracking in Unreal Engine via UDP communication.
What I Have Working:
- I’m already sending rotation data (3DOF) from the BNO085 via quaternion, using an ESP32 and UDP over Wi-Fi.
- The data is being received in Unreal Engine 5 using Blueprints.
- The actor in UE5 rotates correctly based on that data (roll, pitch, yaw).
What I’m Struggling With:
-
I now want to add translation (position) data: X, Y, Z — to get full 9DOF tracking.
-
I don’t want the translation in quaternion — just as a vector (in millimeters).
-
I’m confused about:
- How to get the position data (x, y, z) from the BNO085 and send it via UDP along with quaternion.
- How to modify my Blueprint in Unreal Engine to apply both rotation and translation.
My Setup:
- ESP32 with BNO085 connected via I2C.
- Sending quaternion rotation as comma-separated strings via UDP every 100ms.
- Here’s the current C++ (Arduino) code I’m using for rotation:
include <WiFi.h>
include <WiFiUdp.h>
include <Wire.h>
include <Adafruit_BNO08x.h>
include <sh2_SensorValue.h>
include <math.h>
// Wi-Fi Config
const char* ssid = “test”;
const char* password = “12345678”;
const char* udpAddress = “*******7”; // PC IP
const int udpPort = 4210;
WiFiUDP udp;
Adafruit_BNO08x bno085;
sh2_SensorValue_t sensorValue;
// Wi-Fi Connect Function
void connectToWiFi() {
Serial.print(“Connecting to Wi-Fi”);
WiFi.begin(ssid, password);
int retries = 0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(“.”);
retries++;
if (retries > 20) {
Serial.println(“ WiFi Failed!”);
return;
}
}
Serial.println(“”);
Serial.print(" Connected! IP: ");
Serial.println(WiFi.localIP());
}
// Quaternion to Euler (Yaw-Pitch-Roll) Conversion
void quaternionToEuler(float qx, float qy, float qz, float qw, float& roll, float& pitch, float& yaw) {
roll = atan2(2.0f * (qw * qx + qy * qz), 1.0f - 2.0f * (qx * qx + qy * qy));
pitch = asin(2.0f * (qw * qy - qz * qx));
yaw = atan2(2.0f * (qw * qz + qx * qy), 1.0f - 2.0f * (qy * qy + qz * qz));
}
// Euler (with flipped yaw) back to Quaternion
void eulerToQuaternion(float roll, float pitch, float yaw, float& qx, float& qy, float& qz, float& qw) {
float cy = cos(yaw * 0.5);
float sy = sin(yaw * 0.5);
float cp = cos(pitch * 0.5);
float sp = sin(pitch * 0.5);
float cr = cos(roll * 0.5);
float sr = sin(roll * 0.5);
qw = cr * cp * cy + sr * sp * sy;
qx = sr * cp * cy - cr * sp * sy;
qy = cr * sp * cy + sr * cp * sy;
qz = cr * cp * sy - sr * sp * cy;
}
void setup() {
Serial.begin(115200);
delay(1000);
connectToWiFi();
Wire.begin();
if (!bno085.begin_I2C()) {
Serial.println(“ Failed to find BNO085”);
while (1) delay(10);
}
Serial.println(“ BNO085 found!”);
bno085.enableReport(SH2_ROTATION_VECTOR);
delay(100);
}
void loop() {
if (bno085.wasReset()) {
Serial.println(“ BNO085 was reset. Re-enabling report.”);
bno085.enableReport(SH2_ROTATION_VECTOR);
}
if (bno085.getSensorEvent(&sensorValue) && sensorValue.sensorId == SH2_ROTATION_VECTOR) {
float qw = sensorValue.un.rotationVector.real;
float qx = sensorValue.un.rotationVector.i;
float qy = sensorValue.un.rotationVector.j;
float qz = sensorValue.un.rotationVector.k;
// Convert to Euler
float roll, pitch, yaw;
quaternionToEuler(qx, qy, qz, qw, roll, pitch, yaw);
// Invert Yaw
yaw *= -1.0f;
// Convert back to Quaternion
float qx_new, qy_new, qz_new, qw_new;
eulerToQuaternion(roll, pitch, yaw, qx_new, qy_new, qz_new, qw_new);
// Format Output
String output = String(qx_new, 5) + "," +
String(qy_new, 5) + "," +
String(qz_new, 5) + "," +
String(qw_new, 5) + ",";
// Send over UDP
udp.beginPacket(udpAddress, udpPort);
udp.print(output);
udp.endPacket();
// Print to Serial
Serial.println(output);
}
delay(100);
}
My Questions:
- How can I enable translation (position) data from BNO085 using Arduino?
- What’s the best way to format and send both rotation and translation together via UDP?
- How should I update my UE5 Blueprints to use both
SetActorRotation
andSetActorLocation
based on the incoming UDP string? - Is the RVR Stabilized Accelerometer report the right way to get position?
Goal:
A UE5 actor that both rotates and moves according to real-world IMU motion (full 9DOF), all controlled via UDP from ESP32.
Any help, code examples, or pointers would mean a lot.
Thank you!