GR-Sensor
1. Overviewβ
GR-Sensor is the sensor-data subscription layer. The runtime service grsensor reads orientation, angular velocity, and linear acceleration from the body IMU, and converts touch-controller UDP data into DDS touch state. This page documents the currently available IMU and touch topic contracts.
π§ For lidar and camera streaming data, interfaces are under construction
| Element | Value |
|---|---|
| Domain ID | 123 |
| Hardware access | Runtime needs root to access device files |
| Current support | IMU data acquisition, body touch state |
| Topics | Imu_state, body_sensor_state |
2. DDS Interfaceβ
2.1 Topicsβ
IMUβ
| Topic | Message Type | Description |
|---|---|---|
Imu_state | fourier_msgs_pod/msg/Imu | Body IMU, default topic |
Touchβ
| Topic | Message Type | Description |
|---|---|---|
body_sensor_state | fourier_msgs/msg/SensorState | Body touch state; non-zero bitmask means touched |
2.2 IDL Definitionsβ
Imuβ
// fourier_msgs_pod/msg/Imu β body IMU
struct Imu {
HeaderPod header;
TracePointList trace_points;
Quaternion orientation; // x, y, z, w
double orientation_covariance[9];
Vector3 angular_velocity; // rad/s
double angular_velocity_covariance[9];
Vector3 linear_acceleration; // m/s^2
double linear_acceleration_covariance[9];
Vector3 bias_vector; // robot yaw-direction bias vector
};
SensorState (Touch)β
In body_sensor_state, sensor_name is "touch" and sensor_state[0].arg_int[0] is the 16-bit touch bitmask. If you only need to know whether anything is touched, check whether this value is non-zero.
struct BaseDataType {
sequence<int32> arg_int;
sequence<double> arg_double;
sequence<string> arg_string;
};
struct SensorState {
Header header;
string sensor_name; // "touch"
sequence<BaseDataType> sensor_state;
};
3. Basic Examplesβ
3.1 Python β Subscribe to IMUβ
import time
from fourierdds_py import DDSInterface, SubscriberQosProfile
import fourier_msgs_pod.msg.ImuPod as ImuPod
dds = DDSInterface(domain_id=123)
def on_imu(msg):
q = msg.orientation()
w = msg.angular_velocity()
a = msg.linear_acceleration()
b = msg.bias_vector()
print(
"[imu]\n"
f" orientation xyzw: [{q.x():.6f}, {q.y():.6f}, {q.z():.6f}, {q.w():.6f}]\n"
f" angular_velocity rad/s: [{w.x():.6f}, {w.y():.6f}, {w.z():.6f}]\n"
f" linear_acceleration m/s^2: [{a.x():.6f}, {a.y():.6f}, {a.z():.6f}]\n"
f" bias_vector: [{b.x():.6f}, {b.y():.6f}, {b.z():.6f}]"
)
dds.create_subscription(
ImuPod.ImuPubSubType,
"Imu_state",
on_imu,
qos_profile=SubscriberQosProfile.default(),
)
while True:
time.sleep(0.1)
3.2 Python β Subscribe to Touch Stateβ
import time
from fourierdds_py import DDSInterface, SubscriberQosProfile
import fourier_msgs.msg.SensorState as SensorState
dds = DDSInterface(domain_id=123)
def on_touch(msg):
states = msg.sensor_state()
if states.size() == 0:
return
values = states[0].arg_int()
if values.size() == 0:
return
if values[0] != 0:
print("[touch] touched")
dds.create_subscription(
SensorState.SensorStatePubSubType,
"body_sensor_state",
on_touch,
qos_profile=SubscriberQosProfile.default(),
)
while True:
time.sleep(0.1)
3.3 C++ β Subscribe to IMUβ
#include <ImuPod/ImuPodPubSubTypes.hpp>
#include "fourier_dds/dds_node.hpp"
#include "fourier_dds/dds_subscription.hpp"
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
int main() {
auto node = std::make_shared<fourier_dds::DdsNode>(123);
auto sub = std::make_shared<
fourier_dds::DdsSubscription<fourier_msgs_pod::msg::ImuPubSubType>>(
node,
"Imu_state",
[](const fourier_msgs_pod::msg::Imu& msg) {
std::cout << "[imu]\n"
<< " orientation xyzw: ["
<< msg.orientation().x() << ", "
<< msg.orientation().y() << ", "
<< msg.orientation().z() << ", "
<< msg.orientation().w() << "]\n"
<< " angular_velocity rad/s: ["
<< msg.angular_velocity().x() << ", "
<< msg.angular_velocity().y() << ", "
<< msg.angular_velocity().z() << "]\n"
<< " linear_acceleration m/s^2: ["
<< msg.linear_acceleration().x() << ", "
<< msg.linear_acceleration().y() << ", "
<< msg.linear_acceleration().z() << "]\n"
<< " bias_vector: ["
<< msg.bias_vector().x() << ", "
<< msg.bias_vector().y() << ", "
<< msg.bias_vector().z() << "]\n";
});
while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
Build example:
g++ -std=c++17 imu_sub.cpp -o imu_sub \
-I/opt/fftai/include/fourier_dds \
-I/opt/fftai/fourier_dds_msgs/include/fourier_dds_msgs \
-L/opt/fftai/fourier_dds_msgs/lib \
-Wl,-rpath,/opt/fftai/fourier_dds_msgs/lib \
-lImuPod \
-lfastdds \
-lfastcdr \
-pthread
Run example:
sudo env "PYTHONPATH=$PYTHONPATH" "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" ./imu_sub
3.4 C++ β Subscribe to Touch Stateβ
#include <SensorState/SensorStatePubSubTypes.hpp>
#include "fourier_dds/dds_node.hpp"
#include "fourier_dds/dds_subscription.hpp"
#include <chrono>
#include <iostream>
#include <memory>
#include <thread>
int main() {
auto node = std::make_shared<fourier_dds::DdsNode>(123);
auto sub = std::make_shared<
fourier_dds::DdsSubscription<fourier_msgs::msg::SensorStatePubSubType>>(
node,
"body_sensor_state",
[](const fourier_msgs::msg::SensorState& msg) {
if (msg.sensor_state().empty() || msg.sensor_state()[0].arg_int().empty()) {
return;
}
if (msg.sensor_state()[0].arg_int()[0] != 0) {
std::cout << "[touch] touched\n";
}
});
while (true) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
Build example:
g++ -std=c++17 touch_sub.cpp -o touch_sub \
-I/opt/fftai/include/fourier_dds \
-I/opt/fftai/fourier_dds_msgs/include/fourier_dds_msgs \
-L/opt/fftai/fourier_dds_msgs/lib \
-Wl,-rpath,/opt/fftai/fourier_dds_msgs/lib \
-lSensorState \
-lfastdds \
-lfastcdr \
-pthread
Run example:
sudo env "PYTHONPATH=$PYTHONPATH" "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" ./touch_sub
4. Troubleshooting & Remindersβ
Local Subscriber Permissionsβ
grsensor usually runs as root. Run local subscriber examples as root too. Python subscriber scripts need PYTHONPATH and LD_LIBRARY_PATH preserved; otherwise DDS may match but deliver no callback.
sudo env "PYTHONPATH=$PYTHONPATH" "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" python3 -u touch.py
For non-login SSH commands, load the login environment first:
bash -lc 'cd ~/sensor_test && sudo env PYTHONPATH="$PYTHONPATH" LD_LIBRARY_PATH="$LD_LIBRARY_PATH" python3 -u touch.py'
No IMU Dataβ
Confirm that grsensor is running, then check that the subscriber uses domain 123, topic Imu_state, and the matching message type.
No Touch Stateβ
Confirm that CommNodeUdpTouch and CommNodeDdsSensorState are enabled. The touch device sends UDP packets to grsensor:50001; after receiving them, grsensor publishes DDS topic body_sensor_state.
Topic and Message Type Must Matchβ
Imu_state maps to fourier_msgs_pod/msg/Imu; body_sensor_state maps to fourier_msgs/msg/SensorState. If the topic name and message type do not match, DDS discovery may succeed while the callback receives no valid data.
Domain IDβ
All grsensor topics live on domain 123. If you change the domain on one side, change it on the other.