EduArt Sensor Ring Library 3.0.0
Loading...
Searching...
No Matches
Examples

The Sensor Ring library includes both C++ examples and Python examples that show how to use it in custom projects.

⚠️ Interface: All examples register both a SocketCAN and an USBtingo interface by default. The SensorRingFactory auto-discovery will use whichever interface is available on your system. Depending on your setup, you may need to adjust the interface names (e.g. the SocketCAN device name or the USBtingo device index) in the respective example source file. Note that SocketCAN is only available on Linux.

1. C++ Examples C++

The library is written in C++ and it is recommended to use the C++ interface of the library for performance reasons.

The following examples show how to use the Sensor Ring library in your own C++ project:

Measurement Rate Examples

The first two examples are functionally identical — they all use the SensorRingFactory for auto-discovery and display the current ToF and thermal measurement rate on the command line. They differ only in the programming pattern used to receive measurements:

  • Using Lambdas (function-based): Subscribes to device groups and state changes using lambda callbacks directly on the MeasurementManager
  • Using Proxy Class (object-oriented): Wraps the subscription logic in a custom proxy class that binds its member functions as callbacks via std::bind

Visualization and Action Examples

  • Depth Map Example: Prints a colored 8×8 depth map of the first connected ToF sensor on the command line
  • Thermal Map Example: Prints a 32×32 false-color thermal image from the first connected HTPA32 sensor on the command line
  • Extra Action Example: Demonstrates how to use enqueueExtraAction() to control WS2812b LEDs with a smooth color cycling animation

⚠️ To use the depth_map or thermal_map C++ examples on Windows you might first need to enable UTF-8 support for your current terminal session with this command:
$OutputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding.

2. Python Examples Python

ℹ️ The library can be built with -DSENSORRING_BUILD_PYTHON_BINDINGS=ON option to generate python bindings.

⚠️ To use the sensorring python package you have to append the location of the package to your PYTHONPATH environment variable.

⚠️ It is strongly recommended to copy measurements to NumPy arrays before manipulating them in Python. This is shown in the depth_map_matplotlib example using point_cloud.copyTo().

  • Linux

    export PYTHONPATH=$PYTHONPATH:/usr/local/lib/python3/dist-packages
  • Windows

    $env:PYTHONPATH = "${env:PYTHONPATH};C:\Program Files\EduArt Robotik GmbH\Sensor Ring\bindings\python3"
    $env:EDU_SENSORRING_DIR = "C:\Program Files\EduArt Robotik GmbH\Sensor Ring\"
    Alternatively you can use the Windows Edit the System Environment Variables tool to add the python package location to the environment variable PYTHONPATH.

The following examples show how to use the Sensor Ring library in your own Python project.

Measurement Rate Examples

The first two examples are functionally identical — they all use the SensorRingFactory for auto-discovery and display the current ToF and thermal measurement rate on the command line. They differ only in the programming pattern used to receive measurements:

  • Using Lambdas (function-based): Subscribes to device groups and state changes using Python callbacks directly on the MeasurementManager
  • Using Proxy Class (object-oriented): Wraps the subscription logic in a custom proxy class that binds its member methods as callbacks

Depth Map Examples

Thermal Map Examples

Action Examples

  • Extra Action Example: Demonstrates how to use enqueueExtraAction() to control WS2812b LEDs with a smooth color cycling animation

The depth_map_terminal example

The depth_map_matplotlib example.

Below is a minimal example that shows how to set up the SensorRing and receive measurements in Python using the function-based subscription API:

import time
import eduart.sensorring as sensorring
def main():
params = sensorring.ManagerParams()
# Set up the communication interface
interface = sensorring.ComInterfaceID()
interface.type = sensorring.InterfaceType_UsbTingo
interface.name = "0"
try:
# Subscribe to the log messages
log_sub = sensorring.Logger.getInstance().subscribe(
lambda verbosity, msg:
print(f"[{sensorring.LogVerbosityToString(verbosity)}] {msg}")
if verbosity > sensorring.LogVerbosity_Debug else None
)
# Create the SensorRing via auto-discovery
factory = sensorring.SensorRingFactory()
factory.addInterface(interface)
sensor_ring = factory.build(sensorring.ValidationMode_Relaxed)
if sensor_ring is None:
print("Failed to create SensorRing. Exiting.")
return
# Create the MeasurementManager with the SensorRing
manager = sensorring.MeasurementManager(params, sensor_ring)
# Subscribe to the state changes
state_sub = manager.subscribeToStateChanges(
lambda state: print(f"[State] State changed to: {sensorring.ManagerStateToString(state)}")
)
# Subscribe to the ToF and Thermal device groups
tof_sub = manager.subscribeToDeviceGroup(
sensorring.DeviceType_VL53L8CX,
lambda group: None # Process ToF measurements here
)
thermal_sub = manager.subscribeToDeviceGroup(
sensorring.DeviceType_HTPA32,
lambda group: None # Process thermal measurements here
)
# Start the measurements
manager.startMeasuring()
while manager.isMeasuring():
# Do something useful here ...
time.sleep(1)
# Cancel subscriptions and stop (optional - destruction also cancels)
state_sub.cancel()
tof_sub.cancel()
thermal_sub.cancel()
log_sub.cancel()
manager.stopMeasuring()
except Exception as e:
print(f"Caught: {e}")
if __name__ == "__main__":
main()

3. Logger Subscription

All examples subscribe to the Logger before creating the SensorRingFactory or any other library object. This is intentional: the factory and the manager emit log messages during construction, enumeration and initialization. A logger subscription that is set up after these objects are created will miss those early messages.

Because the subscription must exist before any class instance it could be embedded in, a simple lambda (C++) or function (Python) is the best choice. A class-based approach (binding a member function) would require the logger-owning object to be fully constructed first, making it impossible to capture the very first messages.

// C++ — subscribe at the top of the try block, before any other library call
auto log_sub = logger::Logger::getInstance()->subscribe(
[](const logger::LogVerbosity verbosity, const std::string& msg) {
if (verbosity > logger::LogVerbosity::Debug)
std::cout << "[" << verbosity << "] " << msg << std::endl;
});
# Python — same pattern
log_sub = sensorring.Logger.getInstance().subscribe(
lambda verbosity, msg:
print(f"[{sensorring.LogVerbosityToString(verbosity)}] {msg}")
if verbosity > sensorring.LogVerbosity_Debug else None
)
Read Previous Read Next
Software Wrappers