Matlab Toolbox serving as an interface client to interact with the Unreal Engine implementation of SonoTraceUE.
- Demonstration video: https://www.youtube.com/watch?v=_Z39IlmT22E
- Paper Preprint: https://arxiv.org/abs/2602.19652
We kindly ask to cite our paper if you find this repository useful:
@article{jansen2026sonotraceue,
title={Hardware-Accelerated Geometrical Simulation of Biological and Engineered In-Air Ultrasonic Systems},
author={Jansen, Wouter and Steckel, Jan},
year={2026},
url={https://arxiv.org/abs/2602.19652},
doi={10.48550/arXiv.2602.19652},
}
Find the latest release on Github or the MathWorks File Exchange for the toolbox. You can also clone or download this repository and use it from source.
- Unreal Engine with SonoTraceUE Plugin v3.1.0 or higher.
- Instrument Control Toolbox
- Phased Array System Toolbox
- Signal Processing Toolbox
- Computer Vision Toolbox
- Lidar Toolbox
- Navigation Toolbox
- Radar Toolbox
- Robotics System Toolbox
- ROS Toolbox
- Satellite Communications Toolbox
- Sensor Fusion and Tracking Toolbox
An example is available, to quickly open this file after installing the toolbox, run the following command or find it manually in the examples folder.
sonotraceue.openExampleThis example works best with the Default level of the SonoTraceUE sample project.
All functions in this Toolbox exist within the sonotraceue namespace. For calling these functions you therefore have to add the namespace name to the beginning.
output = sonotraceue.functionName(...)
Important: This MATLAB client uses a right-handed coordinate system with meters as the unit of measurement, which follows MATLAB's convention. This is very different from Unreal Engine's coordinate system.
MATLAB/Client Coordinate System:
- Right-handed coordinate system
- X: Forward
- Y: Right
- Z: Up
- Units: Meters
Unreal Engine Coordinate System:
- Left-handed Z-up coordinate system
- Units: Centimeters
The toolbox automatically handles coordinate transformations between these two systems. When you send data to or receive data from the SonoTraceUE plugin, the conversions are performed transparently using the matlabTFormToUnreal() and unrealToMatlabTForm() helper functions.
The UnrealPlugin has the option to generate sub output results for each component (specular, diffraction, direct path). If it is enabled there (including in the interface settings!) than the interface will also receive the data seperately for each sub output. This allows it to be seperately plotted as pointclouds and also have the impulse responses generated seperately (with optional merging).
The main interface class that establishes and manages the TCP connection to the SonoTraceUE plugin.
Constructor:
interface = sonotraceue.Interface(serverIP, serverPort, logLevel) Parameters:
serverIP(string, optional): IP address of the server. Default:'localhost'serverPort(int, optional): Port number. Default:9098logLevel(string, optional): Logging level ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL')
Example:
% Connect to local SonoTraceUE instance
interface = sonotraceue.Interface('localhost', 9098, 'INFO'); Receives simulation settings from the Unreal Engine plugin. This includes all emitter/receiver configurations, simulation parameters, object settings, frequencies, and emitter signals.
settings = interface.receiveSettings() Returns:
settings: Asonotraceue.Settingsobject containing all simulation configuration
The Settings object contains properties such as:
- Emitter and receiver positions
- Simulation parameters (frequency range, sample rate, speed of sound)
- Ray tracing settings (number of rays, maximum bounces, ray distance)
- Component calculation flags (specular, diffraction, direct path)
- Sensor limits (azimuth and elevation angles)
- Object acoustic properties
For preparing the impulse response synthesis and the signal generation, this function should be run once retrieving the initial settings to further prepare the interface for generating the final output if so desired.
settings = settings.prepareIRandSignalGeneration(numberOfSamplesIRFilter, enablePatternSum, iRFilterGaussAlpha, numberOfIRSamples, ...
approximateIRCutDB, enableApproximateIR, useBaseKernels)Parameters:
numberOfSamplesIRFilter: Defines the length (in samples) of the short kernel used to represent a single reflection event. A higher value provides higher frequency resolution for the pulse shape but increases computation time. It determines the size of the FFT/IFFT windows used to create the base kernels. Common value are 256.enablePatternSum:iRFilterGaussAlpha: The Alpha parameter for the Gaussian window function (gausswin) applied to the frequency kernels.numberOfIRSamples: The total length of the final output impulse response vector (in samples).approximateIRCutDB: The dynamic range threshold (in decibels) used for culling weak reflections whenenableApproximateIRis active. Rays with a signal strength below this threshold (relative to the strongest ray) are skipped. Ex. : Setting this to -60 or -80 dB preserves accuracy; setting it to -20 dB is faster but loses detail.enableApproximateIR: Toggle the Culling optimization. If enabled, it calculates the energy of rays first and discards those belowapproximateIRCutDBbefore synthesis.useBaseKernels: Toggle the base kernel optimization. Uses pre-computed time-domain pulses and matrix multiplication. This should in most cases be enabled!
Triggers a new acoustic measurement in the Unreal Engine simulation.
success = interface.triggerMeasurement()
success = interface.triggerMeasurement(overrideEmitterSignalIndexes) Parameters:
overrideEmitterSignalIndexes(array, optional): Array of emitter signal indexes to override the default configuration
Returns:
success: Boolean indicating whether the trigger was successful
Example:
% Trigger with default settings
triggered = interface.triggerMeasurement();
% Trigger with specific emitter signal indexes
triggered = interface.triggerMeasurement([0, 1, 0, 1]); Sets the emitter signal index for a specific emitter.
success = interface.SetCurrentEmitterSignalIndexForSpecificEmitter(emitterIndex, emitterSignalIndex) Parameters:
Sets the emitter signal indexes for all emitters at once.
success = interface.SetCurrentEmitterSignalIndexes(emitterSignalIndexes) Parameters:
emitterSignalIndexes: Array of signal indexes for all emitters
Retrieves the current emitter signal index for a specific emitter.
index = interface.GetCurrentEmitterSignalIndexForSpecificEmitter(emitterIndex)Retrieves the current emitter signal indexes for all emitters.
indexes = interface.GetCurrentEmitterSignalIndexes() Sets a new relative transform for the sensor (relative to its owner/parent).
success = interface.setNewSensorRelativeTransform(tform) Parameters:
Sets a new world transform for the sensor in absolute coordinates.
success = interface.setNewSensorWorldTransform(tform)
success = interface.setNewSensorWorldTransform(tform, teleport) Parameters:
tform: 4x4 homogeneous transformation matrix (MATLAB convention)teleport(bool, optional): If true, instantly teleports; if false, performs smooth movement. Default:false
Sets a new world transform for the sensor's owner/parent actor.
success = interface.setNewSensorOwnerWorldTransform(tform)
success = interface.setNewSensorOwnerWorldTransform(tform, teleport) Parameters:
tform: 4x4 homogeneous transformation matrix (MATLAB convention)teleport(bool, optional): If true, instantly teleports; if false, performs smooth movement. Default:false
Updates the positions of specific emitters.
success = interface.setNewEmitterPositions(emitterIndexes, newEmitterPositions, relativeTransform, reApplyOffset) Parameters:
emitterIndexes: Array of emitter indexes to updateNewEmitterPositions: 3×N matrix of positions in meters (MATLAB convention)relativeTransform(bool): If true, positions are relative to sensor framereApplyOffset(bool): If true, applies the configured emitter offset
Updates the positions of specific receivers.
success = interface.setNewReceiverPositions(receiverIndexes, newReceiverPositions, relativeTransform, reApplyOffset) Parameters:
receiverIndexes: Array of receiver indexes to updateNewReceiverPositions: 3×N matrix of positions in meters (MATLAB convention)relativeTransform(bool): If true, positions are relative to sensor framereApplyOffset(bool): If true, applies the configured receiver offset
Sends a generic data message to the Unreal Engine plugin. This allows custom data exchange between MATLAB and UE.
success = interface.SendDataMessage(dataMessage) Parameters:
dataMessage: Asonotraceue.DataMessageobject
DataMessage Constructor:
msg = sonotraceue.DataMessage(type, order, strings, integers, floats) Parameters:
type(int): Custom message type identifierorder(array): Array specifying data order (0=string, 1=integer, 2=float)strings(cell array): Cell array of stringsintegers(array): Array of integer valuesfloats(array): Array of float values
Example:
% Create a data message with mixed types
msg = sonotraceue.DataMessage(1, [0, 1, 2], {'hello'}, [42], [3.14]);
success = interface.SendDataMessage(msg); Receives data from the Unreal Engine plugin. This can be measurement data or custom data messages.
[data, type] = interface.receiveData() Returns:
data: Either aMeasurementobject (type=1) orDataMessageobject (type=2)type: Integer indicating data type:1: Measurement data2: Data message0: End of connection-1: No active interface-2: Unknown message
Contains all data from a single acoustic measurement, including ray-traced points, impulse responses, and sensor poses.
Key Properties:
index: Measurement index numbertimestamp: Measurement timestampemitterTForms: 4×4×N array of emitter transformsreceiverTForms: 4×4×M array of receiver transformssensorTForm: 4×4 sensor world transformreflectedPoints: Struct Array of ray-traced point structures, explained belowdirectPathLOS: Line-of-sight results for direct pathimpulseResponses: Generated impulse responses (emitters × receivers × samples)receiverSignals: Generated receiver signals (receivers × samples)specularSubOutput: Specular reflection component resultsdiffractionSubOutput: Diffraction component resultsdirectPathSubOutput: Direct path component resultsmaximumStrength: Maximum reflection strength value across all pointsmaximumCurvature: Maximum surface curvature encounteredmaximumTotalDistance: Maximum total acoustic path distance (in meters)emitterSignalIndexes: Array of signal indexes used by each emitter for this measurementsensorToOwnerTForm: 4×4 transform from sensor to its owner/parent actorownerTForm: 4×4 owner/parent actor world transformnumberOfFrequencies: Number of frequency components used in simulationnumberOfEmitters: Number of emitters in the sensor arraynumberOfReceivers: Number of receivers in the sensor arraysampleRate: Sample rate used for signal generation (Hz)pointsInSensorFrame: Boolean indicating if reflected points are in sensor frame (true) or world frame (false)
The reflectedPoints struct array of the Measurement class holds the important data on all the reflected simulation points. This table explains all the fields of this array.
| Field | Type | Description |
|---|---|---|
location |
[3×1 double] |
3D position of point |
reflectionDirection |
[3×1 double] |
Direction of acoustic reflection |
label |
string |
Object label (from component name) |
index |
int32 |
Sequential point index |
summedStrength |
float |
Total strength across all frequencies |
strengths |
[Em × Rx × Freq float] |
Strength values per emitter, receiver, and frequency |
totalDistance |
float |
Total acoustic path length |
totalDistancesFromEmitters |
[Em × 1 float] |
Path length per emitter |
totalDistanceToReceivers |
[Em × Rx float] |
Path length from this point to each receiver, per emitter |
distanceToSensor |
float |
Direct distance to sensor |
objectTypeIndex |
int32 |
Index into ObjectSettings array |
isHit |
logical |
true if ray hit geometry |
isLastHit |
logical |
true if final bounce in ray path |
curvatureMagnitude |
float |
Surface curvature at hit point |
isSpecular |
logical |
true if from specular component |
isDiffraction |
logical |
true if from diffraction component |
isDirectPath |
logical |
true if from direct path component |
rayIndex |
int32 |
The original index of the raytracing resulting in this point |
bounceIndex |
int32 |
The bounce index of the multi-path reflections of the rays |
emitterDirectivities |
[Em × 1 float] |
The calculated source directivity for each emitter to the first reflection |
Em = Number of Emitters, Rx = Number of Receivers, Freq = Number of Frequencies
Make sure to first run Settings.prepareIRandSignalGeneration() once in order to prepare the two next two functions.
Synthesizes impulse responses from the reflected points data.
measurement = measurement.synthetizeIRFromPoints(settings) Generates receiver signals by convolving impulse responses with emitter signals.
measurement = measurement.receiverSignalGenerationFromIR(settings)
Visualizes measurement data including sensor poses, reflected points, direct path results, impulse responses, and receiver signals.
measurement.updatePlot(plotSensor, plotReflectedPoints, plotDirectPath, plotIR, plotSignals, dbCutoff, plotLimitAroundSensor)Parameters:
plotSensor(logical): If true, plots sensor, owner, emitter, and receiver poses in 3D world frameplotReflectedPoints(logical): If true, plots reflected points colored by normalized reflection strengthplotDirectPath(logical): If true, plots direct path line-of-sight results, showing which receivers have LOS to emittersplotIR(logical): If true, plots impulse responses for all receivers in subplotsplotSignals(logical): If true, plots receiver signal spectrograms in subplotsdbCutoff(float): Dynamic range threshold in dB for reflected points color mapping (e.g., 60 or 80)plotLimitAroundSensor(logical): If true, limits plot axes to ±plotAxisLimitaround sensor position
There are also additional functions for generating impulse responses for suboutputs seperately as well as override functions, please check the source code for using those.
Converts Unreal Engine position and rotation to a MATLAB transformation matrix.
tform = sonotraceue.unrealToMatlabTForm(position, rotation)Converts a MATLAB transformation matrix to Unreal Engine position and rotation.
[locationCentimeters, rotationQuat] = sonotraceue.matlabTFormToUnreal(tform) Here's a typical workflow for using the SonoTraceUE MATLAB client:
% 1. Establish connection
interface = sonotraceue.Interface('localhost', 9099, 'INFO');
% 2. Receive initial settings and configure and prepare the post processing steps
settings = interface.receiveSettings();
useBaseKernels = true;
numberOfSamplesIRFilter = 256;
iRFilterGaussAlpha = 5;
numberOfIRSamples = 18000;
approximateIRCutDB = -90;
enableApproximateIR = false;
enablePatternSum = true;
settings = settings.prepareIRandSignalGeneration(numberOfSamplesIRFilter, enablePatternSum,...
iRFilterGaussAlpha, numberOfIRSamples, ...
approximateIRCutDB, enableApproximateIR, useBaseKernels)
% 3. (Optional) Update sensor position
tform = eye(4);
tform(1:3, 4) = [1.0; 0.5; 0.2]; % X, Y, Z in meters
interface.setNewSensorWorldTransform(tform, true);
% 4. Trigger measurement
triggered = interface.triggerMeasurement();
% 5. Receive measurement data
[measurement, dataType] = interface.receiveData();
% 6. Process measurement
if dataType == 1
% Synthesize impulse responses
measurement = measurement.synthetizeIRFromPoints(settings);
% Generate receiver signals
measurement = measurement.receiverSignalGenerationFromIR(settings);
% Access results
signals = measurement.receiverSignals;
end- Logger For MATLAB by Ismet Handžić
- Progress bar by HyunGwang Cho
This project is released under the CC-BY-NC-SA-4.0 license.