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 = 77e9Standard 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()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 # dBCreating 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] # GreenHow 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