Skip to main content

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

ElementValue
Domain ID123
Hardware accessRuntime needs root to access device files
Current supportIMU data acquisition, body touch state
TopicsImu_state, body_sensor_state

2. DDS Interface​

2.1 Topics​

IMU​

TopicMessage TypeDescription
Imu_statefourier_msgs_pod/msg/ImuBody IMU, default topic

Touch​

TopicMessage TypeDescription
body_sensor_statefourier_msgs/msg/SensorStateBody touch state; non-zero bitmask means touched

2.2 IDL Definitions​

Imu​

Idl
// 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.

Idl
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​

Python
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​

Python
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​

C++
#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:

Bash
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:

Bash
sudo env "PYTHONPATH=$PYTHONPATH" "LD_LIBRARY_PATH=$LD_LIBRARY_PATH" ./imu_sub

3.4 C++ β€” Subscribe to Touch State​

C++
#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:

Bash
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:

Bash
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.

Bash
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
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.