My App
extreme3dpro_driver

Architecture

Threading model, data flow, and class internals for extreme3dpro_driver

Architecture

Extreme3DProDriver is a single rclcpp::Node that separates hardware I/O from publishing using two concurrent execution contexts.

Data Flow

Threading Model

Read Thread

Runs continuously in the background with the device opened in O_NONBLOCK mode:

  • js_event available → update axes_[] or buttons_[], set fresh_ = true
  • No data (EAGAIN) → sleep 1 ms to avoid busy-waiting
  • Read error → set running_ = false and exit

The JS_EVENT_INIT flag is stripped so initialisation events don't incorrectly mark data as fresh.

Timer Callback

Fires at publish_rate Hz on the main thread:

  1. Skip if !fresh_ && !autorepeat_
  2. publish_joy() — copy axes/buttons with deadzone applied
  3. publish_twist() — non-zero only when deadman held
  4. Publish deadman state
  5. Clear fresh_

Shared state (axes_, buttons_, fresh_) is accessed from both threads. Safe in practice at ≤200 Hz publish rates, but a future improvement could wrap access in a std::mutex.

Lifecycle

If open_device() fails, the node calls rclcpp::shutdown() immediately rather than spinning with no hardware.

Axis Normalisation

Raw int16_t from the kernel → float in [−1.0, +1.0]:

float centre = (max_val + min_val) / 2.0f;
float range  = (max_val - min_val) / 2.0f;
return std::clamp((raw - centre) / range, -1.0f, 1.0f);

Class Overview

On this page