Low-Level C++ SDK  v1.2.0
Loading...
Searching...
No Matches
Low-Level C++ SDK

Welcome to the Weart Low-Level C++ SDK documentation.

The SDK allows to connect to the Weart middleware and perform various actions with the TouchDIVER devices:

  • Start and Stop the middleware operations
  • Calibrate the device
  • Receive tracking data from the devices
  • Send haptic effects to the devices

Architecture

C++ SDK Architecture

Setup

The minimum setup to use the weart SDK consists of:

  • A PC with the Middleware installed
  • A TouchDIVER device
  • A C++ project using the Low-Level SDK

The SDK can be downloaded as a zip file containing all the necessary files. To use it in your C++ project, unzip it and move the files in a folder inside your project. Then, add the folder with the sdk files to the project's include path, and the .cpp files to your project's sources. In Visual Studio, this can be done by including the sdk directory into the project (Right Click on Solution -> Add -> Existing Directory).

To start using the SDK in your project, start the Middleware application and connect a TouchDIVER device to it. Then, create a header file and Include the following headers:

Finally, create the WeArtClient and start the communication with the middleware:

// Instantiate SDK client object
WeArtClient* weArtClient = new WeArtClient("127.0.0.1", WeArtConstants::DEFAULT_TCP_PORT);
// Run communication thread
weArtClient->Run();
Weart client, used to connect to the Weart middleware, perform operations and receive messages.
Definition: WeArtClient.h:19
void Run()
Starts and runs the network connection thread.
Definition: WeArtClient.cpp:42
const PCSTR DEFAULT_TCP_PORT
Definition: WeArtCommon.h:190
Note
The network thread created by the Run method will stop once the connection is closed. To keep the connection open, call the method again upon disconnection or error (they can be notified with WeArtClient::AddConnectionStatusCallback and WeArtClient::AddErrorCallback).

Features

Start/Stop Client

Once connected to the middleware, it's still not possible to receive tracking data and send haptic commands to the devices. In order to do so, it's important to start the middleware with the proper command.

To start the middleware operations, call the Start() method.

weArtClient->Start();
void Start(TrackingType trackType=TrackingType::WEART_HAND)
Send a start command to the middleware.
Definition: WeArtClient.cpp:221

To stop the middleware, call the Stop() method.

weArtClient->Stop();
void Stop()
Send a stop command to the middleware.
Definition: WeArtClient.cpp:226

Devices calibration

After starting the communication with the middleware, it's now possible to calibrate the TouchDIVER devices. The calibration allows to set the initial offsets of each thimble relative to the control unit position, in order to improve the finger tracking output.

First, create the calibration tracking object and add it to the client. The WeArtTrackingCalibration object allows to listen for calibration messages from the middleware, and get notified when the calibration process ends.

// Create calibration tracker and add to client
weArtClient->AddMessageListener(calibration);
void AddMessageListener(WeArtMessageListener *listener)
Adds a message listener object to the client, allowing it to receive messages.
Definition: WeArtClient.cpp:337
Calibration status/result observer.
Definition: WeArtTrackingCalibration.h:7

Then, start the calibration procedure. This will allow the middleware to calibrate the hand sensor offsets based on the current setup (thimbles and control device position, hand inclination, personal differences in the fingers etc..).

weArtClient->StartCalibration();
void StartCalibration()
Starts the device calibration procedure.
Definition: WeArtClient.cpp:249

It’s possible to get the calibration status and result from the tracker object itself, or through callbacks (in the form of std::function).

// Get hand, status and result from tracking object
HandSide hand = calibration->getCurrentHand();
CalibrationStatus status = calibration->getStatus();
bool result = calibration->getResult();
// Be notified by callbacks when the calibration status changes
calibration->AddStatusCallback([](HandSide hand, CalibrationStatus status) {
...
});
// Be notified by callbacks when a calibration result is available
calibration->AddResultCallback([](HandSide hand, bool result) {
... insert code here
});
CalibrationStatus
Definition: WeArtCommon.h:55
HandSide
Definition: WeArtCommon.h:17
void AddStatusCallback(std::function< void(HandSide, CalibrationStatus)> callback)
Adds a callback for calibration status update.
Definition: WeArtTrackingCalibration.cpp:6
void AddResultCallback(std::function< void(HandSide, bool)> callback)
Adds a callback for calibration result.
Definition: WeArtTrackingCalibration.cpp:10
CalibrationStatus getStatus()
Definition: WeArtTrackingCalibration.h:15
HandSide getCurrentHand()
Definition: WeArtTrackingCalibration.h:11
bool getResult()
Definition: WeArtTrackingCalibration.h:19

Haptic feedback

The TouchDIVER allows to perform haptic feedback on the user's finger through its thimbles. Every thimble can apply a certain amount of pressure, temperature and vibration based on the processed object and texture.

Haptic Object

A WeArtHapticObject is the basic object used to apply haptic feedback. To create one, use the following code:

// create haptic object to manage actuation on Right hand and Index Thimble
hapticObject = new WeArtHapticObject(weArtClient);
hapticObject->handSideFlag = HandSide::Right;
hapticObject->actuationPointFlag = ActuationPoint::Index;
A haptic object class, representing one or multiple thimbles and hand with which the user interacts.
Definition: WeArtHapticObject.h:21

The values handSideFlag and actuationPointFlag accept multiple values. The next example presents a single haptic object that, when applied a WeArtEffect, will affect both hands and all fingers.

hapticObject->handSideFlag = HandSide::Right | HandSide::Left;
hapticObject->actuationPointFlag = ActuationPoint::Index | ActuationPoint::Middle | ActuationPoint::Thumb;

Create Effect

The SDK contains a basic TouchEffect class to apply effects to the haptic device. The TouchEffect class contains the effects without any processing. For different use cases (e.g. values not directly set, but computed from other parameters), create a different effect class by implementing the WeArtEffect interface.

Create the object on which the temperature, force and texture values will be applied:

Basic object to apply effects.
Definition: WeArtEffect.h:29
Force value to be applied to an effect.
Definition: WeArtForce.h:10
Temperature value to be applied to an effect.
Definition: WeArtTemperature.h:5
Temperature value to be applied to an effect.
Definition: WeArtTexture.h:9

Add or Update Effect

It's possible to add a new effect to an haptic object, or to update an existing one.

In the example below, the effect created in the previous section is updated with a new temperature, force and texture. It is then added to the haptic object if not already present, otherwise the haptic object is updated in order to send the new effect parameters to the middleware and then to the device.

// define temperature
temperature.active = true;
temperature.value(0.7f);
// define force
force.active = true;
force.value(0.8f);
// define TextileMeshMedium Texture
texture.active = true;
texture.textureType(TextureType::TextileMeshMedium);
texture.textureVelocity(0.5f);
// set properties to effect
touchEffect->Set(temperature, force, texture);
// add effect to thimble or update
if (hapticObject->activeEffects.size() <= 0)
hapticObject->AddEffect(touchEffect);
else
hapticObject->UpdateEffects();
bool Set(WeArtTemperature temp, WeArtForce force, WeArtTexture texture)
Set the effect parameters.
Definition: WeArtEffect.cpp:3
float value() const
Force value getter.
Definition: WeArtForce.h:27
bool active
Definition: WeArtForce.h:23
float value() const
Temperature value getter.
Definition: WeArtTemperature.h:21
bool active
Definition: WeArtTemperature.h:17
float textureVelocity() const
Gets the texture velocity.
Definition: WeArtTexture.h:36
TextureType textureType() const
Texture type getter.
Definition: WeArtTexture.h:48
bool active
Definition: WeArtTexture.h:32
Note
When multiple effects are added to a WeArtHapticObject, which effect is applied depends on the order in which the effects are added. In particular, for each value (temperature, force, texture) only the latest active one will be applied.

Remove Effect

If an effect is not needed anymore, it can be removed from the haptic object with the WeArtHapticObject::RemoveEffect method.

hapticObject->RemoveEffect(touchEffect);

Tracking

After starting the middleware and performing the device calibration, it's possible to receive tracking data related to the TouchDIVER thimbles.

To read these values, create and set a thimble tracker object for monitoring the closure/abduction value of a given finger:

WeArtThimbleTrackingObject* thumbThimbleTracking = new WeArtThimbleTrackingObject(HandSide::Right, ActuationPoint::Thumb);
weArtClient->AddThimbleTracking(thumbThimbleTracking);
void AddThimbleTracking(WeArtThimbleTrackingObject *trackingObjects)
Adds a thimble tracking object to the client, allowing it to receive messages.
Definition: WeArtClient.cpp:373
Object used to track a single thimble object and its closure value.
Definition: WeArtThimbleTrackingObject.h:12

Once this object is added to the client, it will start receiving the tracking values. To access the closure and abduction values, simply use the getters provided by the thimble tracking object.

The closure value ranges from 0 (opened) to 1 (closed).

The abduction value ranges from 0 (finger near the hand's central axis) to 1 (finger far from the hand central axis).

float closure = thumbThimbleTracking->GetClosure();
float abduction = thumbThimbleTracking->GetAbduction();
float GetClosure() const
Get last received thimble closure.
Definition: WeArtThimbleTrackingObject.h:21
float GetAbduction() const
Get last received thimble abduction.
Definition: WeArtThimbleTrackingObject.h:27
Note
The closure value is available for all thimbles, while the abduction value is available only for the thumb (other thimbles will have a value of 0).

Tracking Raw Sensors Data

It's possible to receive the raw data from the tracking sensors on each thimble (and the control unit), in addition to the tracking data. Each sensor has:

  • 3-axis accelerometer
  • 3-axis gyroscope
  • Time of Flight sensor

To read these values, create a WeArtTrackingRawData object and add it to the client.

WeArtTrackingRawData* trackingRawSensorData = new WeArtTrackingRawData(HandSide::Right, ActuationPoint::Index);
weArtClient->AddMessageListener(trackingRawSensorData);
Object used to track the raw sensors data for a single thimble.
Definition: WeArtTrackingRawData.h:13

Once this object is added to the client, it will listen for raw data messages. To start receiving raw data from the middleware, call the WeArtClient::StartRawData() method. To stop receiving raw data, call the WeArtClient::StopRawData() method.

To get the sensors data, get the latest sample (WeArtTrackingRawData::Sample) from the WeArtTrackingRawData object. The sample contains the accelerometer, gyroscope and time of flight data, in addition to the timestamp of its sampling (generated by the middleware and represented as milliseconds in unix epoch time).

WeArtTrackingRawData::Sample sample = trackingRawSensorData->GetLatestSample();
Sensor data sample.
Definition: WeArtTrackingRawData.h:22
Note
The Palm (control unit) doesn't contain a Time-Of-Flight sensor, so its value is always set to 0.

In addition to getting the latest sample by polling the tracking object, it's possible to add a callback called whenever a new sensor data sample is received from the TouchDIVER.

std::function<void(WeArtTrackingRawData::Sample)> callback = (WeArtTrackingRawData::Sample sample) => {
// process the sensor data sample
};
rawSensorData.AddSampleCallback(callback);

Analog Raw Sensors Data

It's possible to receive the raw data from the sensors on each thimble (and the control unit), instead of the tracking data when this function is activated on the Middleware. Each sensor has:

  • NTC - Negative Temperature Coefficient (raw data and converted degree)
  • FSR - force sensing resistor (raw adata and converted newton)

To read these values, create a WeArtAnalogSensorData object and add it to the client.

WeArtAnalogSensorData* anlogSensorData = new WeArtAnalogSensorData(HandSide::Right, ActuationPoint::Index);
weArtClient->AddMessageListener(rawSensorData);
Definition: WeArtAnalogSensorData.h:14

Once this object is added to the client, it will listen for raw data messages as soon the Middleware is on start.

To get the sensors data, get the latest sample (WeArtAnalogSensorData::Sample) from the AnalogSensorRawData object. The sample contains the accelerometer, gyroscope and time of flight data, in addition to the timestamp of its sampling (generated by the middleware and represented as milliseconds in unix epoch time).

WeArtAnalogSensorData::Sample sample = anlogSensorData->GetLatestSample();
Sensor data sample.
Definition: WeArtAnalogSensorData.h:22
Note
The Palm (control unit) doesn't contain a analog sensor, so its value is always set to 0.

Middleware and Devices status tracking

The SDK allows to track and receives updates about the middleware and the connected devices status.

In particular, the information is available through a MiddlewareStatusListener object, that must be added as listener to the client object:

mwListener = new MiddlewareStatusListener();
weArtClient->AddMessageListener(mwListener);
Listens and notifies about middleware status changes.
Definition: MiddlewareStatusListener.h:32

The MiddlewareListener tracks the messages from the middleware, saving and notifying about status changes. In particular, it's possible to register callbacks for the middleware and devices status.

The status callback will receive a struct with the MiddlewareStatusUpdate type, which includes:

  • Middleware version
  • Middleware status (MiddlewareStatus)
  • Status code and description
  • Whether actuations are enabled or not
  • List of the connected devices. For each device:
    • Mac Address
    • Assigned HandSide
    • Overall battery level
    • Status of each thimble (actuation point, connected or not, status code etc..)
std::function<void(MiddlewareStatusUpdate)> callback = [](MiddlewareStatusUpdate data) {
... access middleware status data ...
};
mwListener->AddStatusCallback(callback);
Middleware status fields.
Definition: MiddlewareStatusListener.h:8

The same information can be asked to the MiddlewareListener (in polling fashion) by calling the MiddlewareListener::lastStatus method.

Status Codes

The MiddlewareListener object allows to get the middleware status, which includes the latest status code sent by the middleware while performing its operations.

The current status codes (along with their description) are:

Status Code Description
0 OK Ok
100 START_GENERIC_ERROR Can't start generic error: Stopping
101 CONNECT_THIMBLE Unable to start, connect at least one thimble and retry
102 WRONG_THIMBLES Unable to start, connect the right thimbles matched to the bracelet and retry
103 BATTERY_TOO_LOW Battery is too low, cannot start
104 FIRMWARE_COMPATIBILITY Can't start while the devices are connected to the power supply
105 SET_IMU_SAMPLE_RATE_ERROR Error while setting IMU Sample Rate! Device Disconnected!
106 RUNNING_SENSOR_ON_MASK Inconsistency on Analog Sensors raw data! Please try again or Restart your device/s!
107 RUNNING_DEVICE_CHARGING Can't start while the devices are connected to the power supply
200 CONSECUTIVE_TRACKING_ERRORS Too many consecutive running sensor errors, stopping session
201 DONGLE_DISCONNECT_RUNNING BLE Dongle disconnected while running, stopping session
202 TD_DISCONNECT_RUNNING TouchDIVER disconnected while running, stopping session
203 DONGLE_CONNECTION_ERROR Error on Dongle during connection phase!
300 STOP_GENERIC_ERROR Generic error occurred while stopping session
Note
The description of each status code might change between different Middleware versions, use the status code to check instead of the description.