Logic Gates & Composed Events¶
In the previous recipes, we triggered actions based on single, isolated conditions – “If Mapper Fails” or “If Person Detected”. But real-world autonomy is rarely that simple. A robot shouldn’t stop every time it sees an obstacle – maybe only if it’s moving fast. It shouldn’t return home just because the battery is low – maybe only after finishing its current task.
In this recipe, we use logic operators to compose multiple conditions into smarter, more robust event triggers.
Logic Operators¶
EMOS lets you compose complex triggers using standard Python bitwise operators. This turns your Event definitions into a high-level logic circuit.
Logic |
Operator |
Description |
Use Case |
|---|---|---|---|
AND |
|
All conditions must be True |
Speed > 0 AND Obstacle Close |
OR |
|
At least one condition is True |
Lidar Blocked OR Bumper Hit |
NOT |
|
Inverts the condition |
Target Seen AND NOT Low Battery |
Intelligence Example: Conditional Cognition¶
We can apply the same logic to the intelligence layer. Consider the Event-Driven Cognition recipe where a Vision detector triggers a VLM. What if we only want the VLM to run when the robot has sufficient battery?
from agents.ros import Topic, Event
# Detection output from the Vision component
detections = Topic(name="/detections", msg_type="Detections")
# Battery level topic
battery = Topic(name="/battery_state", msg_type="Float32")
# Condition A: Person detected (with debounce)
person_detected = detections.msg.labels.contains_any(["person"])
# Condition B: Battery above 20%
battery_ok = battery.msg.data > 20.0
# Composed Event: person detected AND battery sufficient
event_describe_person = Event(
event_condition=(person_detected & battery_ok),
on_change=True,
keep_event_delay=5
)
The VLM only wakes up when both conditions are met – saving compute when the battery is low.
OR Logic: Redundant Sensors¶
The | operator is useful for sensor redundancy. If either the front lidar detects a close obstacle or the bumper is pressed, trigger an emergency stop:
from kompass.ros import Topic, Event
lidar = Topic(name="/scan_front", msg_type="Float32")
bumper = Topic(name="/bumper", msg_type="Bool")
is_lidar_blocked = lidar.msg.data < 0.2
is_bumper_pressed = bumper.msg.data == True
event_any_collision = Event(
event_condition=(is_lidar_blocked | is_bumper_pressed),
on_change=True
)
NOT Logic: Exclusion¶
The ~ operator inverts a condition. Use it to exclude scenarios:
from kompass.ros import Topic, Event
# Only track the target if the robot is NOT in manual override mode
manual_mode = Topic(name="/manual_override", msg_type="Bool")
target_seen = detections.msg.labels.contains_any(["person"])
event_auto_track = Event(
event_condition=(target_seen & ~manual_mode.msg.data),
on_change=True
)
Event Configuration Reference¶
All composed events support these parameters:
Parameter |
Description |
Default |
|---|---|---|
|
Trigger only when the condition transitions to True (edge-triggered) |
|
|
Fire only once during the system’s lifetime |
|
|
Minimum seconds between consecutive triggers (debounce) |
|
See also
For the full list of event types and configuration options, see the Events & Actions reference.