RFDT Solver and WiTwin Simulator are undergoing internal testing as we prepare for public release. The functions are limited. Sign up to receive updates.

Component System

Understanding and using standard and custom components

How Components Work#

Component-Based Architecture#

In WiTwin, every object's data and functionality is defined by a collection of components. Each component encapsulates specific features and behaviors.

Transform Component

Transform is a special component that every Object has by default and cannot be removed. It defines the object's position, rotation, and scale in 3D space.

When you create objects using different methods, they automatically come with different default components based on their functionality.

Adding & Removing Components#

Via UI

  1. Select an object in the Viewport or Hierarchy panel
  2. In the Properties panel, click Add Component
  3. To remove a component, right-click on the component header and select Remove (Transform cannot be removed)

Via Python Code

from witwin import Scene
 
scene = Scene()
obj = scene.create_object("MyObject")
 
# Add components
obj.add_component("Mesh", mesh_type="Cube")
obj.add_component("Material")
obj.add_component("Radar")
 
# Remove a component (except Transform)
obj.remove_component("Radar")
 
# Check if object has a component
material = obj.get_component("Material")
if material:
    material.color = [1.0, 0.0, 0.0, 1.0]  # Red

Standard Components#

Transform Component#

Controls object position, rotation, and scale. Automatically added to all objects.

# Access transform directly from object
obj.transform.position = [10.0, 5.0, 0.0]
obj.transform.rotation = [0.0, 90.0, 0.0]  # Degrees
obj.transform.scale = [2.0, 1.0, 1.0]
FieldTypeDescription
positionVector3World position [x, y, z]
rotationVector3Euler angles (degrees)
scaleVector3Scale factors

Material Component#

Defines visual and electromagnetic properties.

obj.add_component("Material")
material = obj.get_component("Material")
 
# Visual properties
material.color = [1.0, 0.5, 0.0, 1.0]  # RGBA
material.metalness = 0.8
material.roughness = 0.2
material.emissive = [0.0, 0.0, 0.0]
material.emissive_intensity = 0.0
 
# Electromagnetic properties
material.permittivity = 2.5    # Relative permittivity (εr)
material.conductivity = 0.0    # Conductivity (S/m)

Mesh Component#

Defines 3D geometry for the object.

# Add mesh with type
obj.add_component("Mesh", mesh_type="Cube")
 
# Available mesh types:
# - Cube, Sphere, Cylinder, Plane, Cone, Torus
# - Custom (for imported models)
 
mesh = obj.get_component("Mesh")
print(f"Vertices: {mesh.vertex_count}")
print(f"Faces: {mesh.face_count}")

Radar Component#

Configures FMCW radar parameters.

obj.add_component("Radar")
radar = obj.get_component("Radar")
 
# Basic parameters
radar.frequency = 77e9      # 77 GHz
radar.bandwidth = 4e9       # 4 GHz
radar.num_tx = 3            # Transmitters
radar.num_rx = 4            # Receivers
radar.fov = 120.0           # Field of view (degrees)
radar.max_range = 100.0     # Maximum range (meters)

Transmitter & Receiver#

from witwin import Scene
 
scene = Scene()
 
# Create transmitter
tx = scene.create_object("TX")
tx.add_component("Transmitter")
transmitter = tx.get_component("Transmitter")
transmitter.frequency = 28e9   # 28 GHz
transmitter.power = 20.0       # dBm
transmitter.antenna_gain = 5.0 # dBi
 
# Create receiver
rx = scene.create_object("RX")
rx.transform.position = [10, 0, 0]
rx.add_component("Receiver")
receiver = rx.get_component("Receiver")
receiver.sensitivity = -90.0   # dBm
receiver.noise_figure = 3.0    # dB

Creating Custom Components#

Extend WiTwin with custom components for your specific needs. Define custom fields and button events that automatically generate UI elements in the Properties panel.

Example: Ball Component with Events#

from witwin.components import (
    Component, component, button,
    float_field, bool_field, color_field
)
from witwin import Console, Results
 
@component(name="Ball")
class BallComponent(Component):
    """A bouncing ball with physics properties."""
 
    # Fields - automatically rendered in Properties panel
    radius = float_field(
        1.0,
        min=0.1,
        max=10.0,
        step=0.1,
        description="Ball radius in meters"
    )
    mass = float_field(
        1.0,
        min=0.1,
        max=100.0,
        description="Ball mass in kilograms"
    )
    color = color_field(
        [1.0, 0.0, 0.0, 1.0],  # Red RGBA
        description="Ball color"
    )
    bounce_height = float_field(
        0.0,
        readonly=True,
        description="Current bounce height"
    )
    is_bouncing = bool_field(
        False,
        description="Is the ball currently bouncing"
    )
 
    # Button events - automatically rendered as buttons
    @button(display_name="Start Bounce")
    def start_bounce(self):
        """Start the ball bouncing."""
        self.is_bouncing = True
        Console.log(f"Ball started bouncing!")
        Console.log(f"Radius: {self.radius}m, Mass: {self.mass}kg")
        return "Bounce started"
 
    @button(display_name="Stop Bounce")
    def stop_bounce(self):
        """Stop the ball bouncing."""
        self.is_bouncing = False
        self.bounce_height = 0.0
        Console.log("Ball stopped bouncing.")
        return "Bounce stopped"
 
    @button(display_name="Calculate Energy")
    def calculate_energy(self):
        """Calculate and display kinetic energy."""
        if self.is_bouncing:
            g = 9.81  # gravity
            energy = self.mass * g * self.bounce_height
            Console.log(f"Current Energy: {energy:.2f} Joules")
 
            # Output to Results panel
            Results.bar(["Energy"], [energy], title="Ball Energy")
            Results.commit(message="Energy Calculation")
            return f"Energy: {energy:.2f} J"
        return "Ball not bouncing"

Using the Custom Component#

from witwin import Scene
 
scene = Scene()
 
# Create object with custom component
ball = scene.create_object("MyBall")
ball.add_component("Mesh", mesh_type="Sphere")
ball.add_component("Ball")
 
# Access custom component
ball_comp = ball.get_component("Ball")
ball_comp.mass = 2.5
ball_comp.color = [0.0, 1.0, 0.0, 1.0]  # Green

How It Works#

Automatic UI Generation

When you define fields with field decorators (float_field, bool_field, etc.), the frontend automatically creates appropriate input widgets (sliders, text inputs, color pickers, checkboxes) in the Properties panel.

Button Events

Methods decorated with @button are rendered as clickable buttons in the UI. When a user clicks a button, the corresponding Python method executes.

Output Options

Component code can communicate results through the Studio APIs:

  • Console.log() - Print messages to the Console panel
  • Results.plot/bar/scatter/imshow/table() - Create visualizations
  • Results.commit() - Send plots to the Results panel
  • Notifications.info/success/warning/error() - Show toast notifications

Field Types Reference#

FieldUsage
float_field(default, min, max, step)Numeric slider
int_field(default, min, max)Integer input
bool_field(default)Checkbox
string_field(default, options)Text or dropdown
vector2_field(default)2D vector
vector3_field(default)3D vector
vector4_field(default)4D vector
color_field(default)Color picker (RGBA)
image_field()Image display
plot_field()Inline plot

Next Steps#