Skip to main content

Programmatic device import

This page aims to support the device simulation workflow by showing how to import geometry that can be used to import devices into Treble.

See Mesh optimization for background on meshing and quality metrics and look at the Tutorials for specific workflows, such as exporting from Rhino, Solidworks, Autocad.

Treble SDK programatic import methods currently allow to import NURBS from Rhinoceros, as well as already meshed objects.

The geometry to be imported should be drawn in meters in one of these file formats:

  • .3dm (NURBS or 3D mesh)
  • .obj (3D mesh)
  • .dxf (3D mesh aka 3DFACE)

Basic examples​

The following examples explain how to import a mannequin geometry saved as a .3dm. You can find the geometry in the zipped folder of examples at the bottom of the page.

Create device geometry definition​

Use the following code to check the quality of a device geometry prior to running a free field simulation. The default check runs with simplification threshold of 0.005 m, and a volumetric benchmark at 8000 Hz upper frequency. For this mannequin, the volumetric mesh efficiency is 29.82%.

from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm")
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()

To stop an in-progress geometry check, call cancel():

device_geometry_check.cancel()
Example of mesh info for a device mesh
Example of mesh info for a device mesh

Add model​

With create_device_geometry_definition you can check geometry quality, but you still need to add the model to the project to save it for later, meaning that if you run a new geometry check without creating a new reference, you'll lose the previous one. Once you're satisfied with the check results, add the model to the project:

project = tsdk.get_or_create_project("checking_devices")

model_name = "SimpleMannequin"
model = project.get_model_by_name(model_name)
if model is None:
model = project.add_model(model_name, device_geometry_check)

Advanced examples​

Simplification threshold​

You can pass simplification_threshold as an argument to remove some detail above the specified threshold. The simplification threshold is set to 0.001 by default and if set to None, it defaults to 1/5 of the remesh size (if provided) or of the automatically calculated remesh size otherwise.

In this example, the mesh quality is increased to 37.71% and the QA tab shows that there are a certain amount of short edges that could be improved in the source geometry.

from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
settings=DeviceGeometryCheckSettings(simplification_threshold=0.01),
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()
Simplification Threshold
Simplification Threshold Plot

By setting simplification_threshold to 0.025 m, the mesh quality is increased to 46.15% but the membrane layer is deformed. The cleaning should only be used to target some isolated cases (e.g. setting it to 0.002 to tackle few small edges); if there is a lot of meaningful edges around that size, then the cleaning will distort the geometry more than remeshing (which is more context aware and attempts to preserve the curves).

from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
settings=DeviceGeometryCheckSettings(simplification_threshold=0.025),
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()
Excessive Simplification

Remesh size​

For cases like this you should use remesh_size, which will try to make more uniform the size of the triangles, preserving as much as possible the source geometry. Here you have an example of the result for remeshing with 1cm size. This generates many small triangles and the mesh quality drops to 10.93%.


from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
settings=DeviceGeometryCheckSettings(remesh_size=0.01),
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()

A fair rule of thumb is to have the simplification threshold set to 1/5 of the remesh size (if any remesh size is provided). This can be done automatically by setting simplification_threshold to None when using remesh_size. The outcome will be simplification_threshold=0.002, with the remaining short edge removed. The mesh quality then raises to 23.93%.


from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
settings=DeviceGeometryCheckSettings(remesh_size=0.01, simplification_threshold=None),
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()

You set the parameter to 0.05 the mesh quality for the default benchmark will increase to 46.54%. If you set simplification_threshold to None it will pick up automatically the best value for the selected remesh_size.

from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
#simplification_threshold set to None becomes 0.01m as 1/5 of remesh_size
settings=DeviceGeometryCheckSettings(remesh_size=0.05, simplification_threshold=None),
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()
Remesh Size

Benchmark threshold​

You can change the upper frequency of the benchmark and observe the results on mesh efficiency. For this case, the quality drops again to 17.08% because there are a good amount of edges whose lengths are shorter than the minimum relevant edge length for the benchmark's transition frequency.

from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings, DeviceGeometryBenchmark,
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
settings=DeviceGeometryCheckSettings(remesh_size=0.05),
benchmarks=[DeviceGeometryBenchmark(transition_frequency=4000)]
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()
Remesh Size Transition Frequency

As we have learnt earlier, set the simplification_threshold to None to improve the mesh quality and get rid of short edges. Now the mesh quality for the benchmark at 4000 Hz is 28.36%.

from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings, DeviceGeometryBenchmark,
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
settings=DeviceGeometryCheckSettings(remesh_size=0.05, simplification_threshold=None),
benchmarks=[DeviceGeometryBenchmark(transition_frequency=4000)]
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()
Simplification None

Other benchmarks​

You can specify benchmarks with different transition frequencies and types as a list. In this example the mannequin is too big to fit comortably in the DRTF Sphere.

from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings, DeviceGeometryBenchmark, DeviceGeometryBenchmarkModelType
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
settings=DeviceGeometryCheckSettings(remesh_size=0.05, simplification_threshold=None),
benchmarks=[
DeviceGeometryBenchmark(transition_frequency=4000),
DeviceGeometryBenchmark(transition_frequency=8000, model_type=DeviceGeometryBenchmarkModelType.DRTF_SPHERE),
DeviceGeometryBenchmark(transition_frequency=2000, model_type=DeviceGeometryBenchmarkModelType.SHOEBOX_ROOM)]
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()
Other Benchmarks

Specify source layer​

Use the settings source_layers to provide a list of layers that are intended to be used as boundary velocity layers later in the lifecycle of this device. An additional verification step is run after the simplification to ensure that none of the faces in the source layers have been modified or ignored (if they were internal to the object and not exposed to the outside, for instance). Setting the source layer with a source_layers argument locks the shape of the layer.

from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/MannequinHatsSimplified.3dm"),
source_layers= ["Membrane"],

)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()
Ignore Extra Faces

Microphone placement​

The following rules apply:

  • Device orientation

Orient the device on the X axis so that azimuthal rotations correspond to rotation in degrees. Center it on the axis as close as possible to the origin. Positive rotations are counterclockwise from the X axis.

  • Microphone centering

Center the device at the origin (or as close as possible) to keep it within the required spherical radius — see Device Simulation for details.

Center both the model and microphones around the X axis — the meshing tools work best with symmetric placement.

Manipulate geometry​

If you need to move or rotate the device model before the simulation, you can transform it into a geometry component using a transform and GeometryComponentGenerator.create_component_from_model. The original mannequin was already correctly facing the X axis, so we won´t rotate it. If you wished to do so, this is the code example.

from treble_tsdk.geometry.generator import GeometryComponentGenerator

translation = treble.Vector3d(0, 0, 0)
rotation = treble.Rotation(90, 0, 0)
transform = treble.Transform3d(translation, rotation)

rotated_mannequin = GeometryComponentGenerator.create_component_from_model(
model,
component_name="rotated_mann",
transform=transform,
)
rotated_mannequin.plot()

This mannequin is rotated. You would then use rotated_mannequin instead of model in the following example.

Mannequin rotated 90 degrees

Ignore extra faces​

Use this setting to include the external faces that are excluded by the picking step. These faces can be the ones that are not part of the manifold part of the device, such as open surfaces 'dangling' from the device or parts floating outside of it.


from treble_tsdk.core.device_geometry_obj import DeviceGeometryCheckSettings, DeviceGeometryBenchmark, DeviceGeometryBenchmarkModelType
from pathlib import Path

device_geometry_check = tsdk.source_receiver_device_library.create_device_geometry_definition(
Path("examples/SimpleMannequinGlasses.3dm"),
settings=DeviceGeometryCheckSettings(simplification_threshold=0.001, ignore_extra_faces=False),
)
device_geometry_check.as_live_device_geometry_status()
device_geometry_check.plot()

Local mesh sizing​

When a dg or hybrid simulation definition is added to a project (project.add_simulation()), the SDK creates a tetrahedral volumetric mesh. LocalMeshSizing controls how individual layers are meshed within that volumetric mesh. Pass a list of LocalMeshSizing objects to the local_mesh_sizing parameter of SimulationDefinition or FreeFieldSimulationDefinition. Changing local sizing requires updating and re-adding the simulation definition.

from treble_tsdk.core.model_obj import LocalMeshSizing
from treble_tsdk.core.simulation import MesherSettings
import numpy as np

local_sizing = []
element_size = 8e-3 # Max. element size for boundary velocity element (device mic)
element_area = (
np.sqrt(3) / 4
) * element_size**2 # Max. element area estimation based on element size

local_sizing.append(
LocalMeshSizing(
layer_name="Layer 0",
mesh_sizing_m=element_size,
keep_exterior_edges=False, # Has to be false to have a quality mesh
)
)

sim_def = treble.free_field.FreeFieldSimulationDefinition( # Creates the simulation definition
name=freefield_simulation_name,
free_field_model=ff_m_dev,
frequency=frequency,
receiver_sphere_radius=1,
source_input="Layer 0",
simulation_purpose=treble.free_field.FreeFieldSimulationPurpose.device,
mesher_settings=MesherSettings(simplify_mesh=True),
local_mesh_sizing=local_sizing,
)
sim_def.plot()

ff_sim = project.add_simulation(
sim_def
) # Adds the simulation definition to the project

simulation_mesh_collection = ff_sim.get_mesh_info()
simulation_mesh_collection.as_table()
source_mesh = simulation_mesh_collection.source_mesh_infos_by_label["source_0"]
source_mesh.plot()

Check out:

  • the tutorial on geometry sizing to learn how to size layers differently on a device.
  • the tutorial on lousdpeaker membrane sizing to learn how to size a membrane on a speaker with boundary velocity source in a room simulation.

If you encounter persistent meshing problems, contact Support.