Component System

Understanding and using standard and custom components

How Components Work

Component-Based Architecture

In PyRFDT, 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 (e.g., creating a cube vs. a radar), 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

# Add a component
obj.add_component("Radar")
obj.add_component("Material")

# Remove a component (except Transform)
obj.remove_component("Radar")

# Check if object has a component
if obj.has_component("Material"):
    material = obj["Material"]

# Access component
radar = obj["Radar"]
radar.frequency = 77e9

Standard Components

Transform Component

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

transform = obj["Transform"]

# Position (world space)
transform.position = [10.0, 5.0, 0.0]

# Rotation (Euler angles in radians)
transform.rotation = [0.0, 1.57, 0.0]  # 90° around Y-axis

# Scale
transform.scale = [2.0, 1.0, 1.0]

# Get 4x4 transformation matrix
matrix = transform.get_transformation_matrix()
position
Vector3 - World position
rotation
Vector3 - Euler angles (radians)
scale
Vector3 - Scale factors

Material Component

Defines visual and electromagnetic properties.

material = obj["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)

Radar Component

Configures FMCW radar parameters.

obj.add_component("Radar")
radar = obj["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

# Transmitter
tx = ObjectFactory.create_empty(position=[0, 0, 0], name="TX")
tx.add_component("Transmitter")
tx["Transmitter"].frequency = 28e9   # 28 GHz
tx["Transmitter"].power = 20.0        # dBm
tx["Transmitter"].antenna_gain = 5.0  # dBi

# Receiver
rx = ObjectFactory.create_empty(position=[10, 0, 0], name="RX")
rx.add_component("Receiver")
rx["Receiver"].sensitivity = -90.0    # dBm
rx["Receiver"].noise_figure = 3.0     # dB

Creating Custom Components

Extend PyRFDT with custom components for your specific needs. Define custom fields and event handlers that automatically generate UI elements in the Properties panel.

Example: Ball Component with Events

This example shows how to create a custom component with fields and button events. The frontend automatically renders input fields and buttons based on your component definition.

from rfdt.components import Component, component, field, button
from rfdt import server
import time

@component(name="Ball")
class BallComponent(Component):
    """A bouncing ball with physics properties."""

    # Fields - automatically rendered in Properties panel
    radius = field(
        1.0,
        min=0.1,
        max=10.0,
        step=0.1,
        description="Ball radius in meters"
    )
    mass = field(
        1.0,
        min=0.1,
        max=100.0,
        description="Ball mass in kilograms"
    )
    color = field(
        [1.0, 0.0, 0.0, 1.0],  # Red RGBA
        description="Ball color"
    )
    bounce_height = field(
        0.0,
        readonly=True,
        description="Current bounce height"
    )
    is_bouncing = field(
        False,
        description="Is the ball currently bouncing"
    )

    # Event handlers - automatically rendered as buttons
    @button(label="Start Bounce")
    def start_bounce(self):
        """Start the ball bouncing."""
        self.is_bouncing = True

        # Log to Console panel
        server.console.log(f"Ball {self.object.name} started bouncing!")
        server.console.log(f"Radius: {self.radius}m, Mass: {self.mass}kg")

    @button(label="Stop Bounce")
    def stop_bounce(self):
        """Stop the ball bouncing."""
        self.is_bouncing = False
        self.bounce_height = 0.0

        server.console.log(f"Ball {self.object.name} stopped bouncing.")

    @button(label="Calculate Energy")
    def calculate_energy(self):
        """Calculate and display kinetic energy."""
        if self.is_bouncing:
            # E = mgh (potential energy at bounce peak)
            g = 9.81  # gravity
            energy = self.mass * g * self.bounce_height

            server.console.log(f"Current Energy: {energy:.2f} Joules")

            # Output to Results panel
            categories = ["Energy"]
            values = [energy]
            server.results.bar(categories, values,
                             title="Ball Energy",
                             ylabel="Energy (Joules)")
            server.results.commit(message="Energy Calculation")

# Usage
ball = ObjectFactory.create_sphere(radius=1.0, name="MyBall")
ball.add_component("Ball")
ball["Ball"].mass = 2.5
ball["Ball"].color = [0.0, 1.0, 0.0, 1.0]  # Green

How It Works

1. Automatic UI Generation

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

2. 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.

3. Output Options

Component code can communicate results through the server object:

  • server.console.log() - Print messages to the Console panel
  • server.results.plot/bar/scatter/imshow/table() - Create visualizations
  • server.results.commit() - Send plots to the Results panel

Field Options Reference

  • min/max: Value bounds (creates slider UI for numeric types)
  • step: Increment step size for numeric inputs
  • description: Tooltip text shown in UI on hover
  • readonly: Make field read-only (display only, no editing)
  • @button(label="..."): Create a clickable button that executes the decorated method
  • • Auto UI widget selection based on field type and constraints

Continue Learning