Design Philosophy & Architecture
Modular Architecture: Core and Conduit
Project Iris is deliberately split into two primary modules – IrisCore and IrisConduit – each with a well-defined role. This separation of concerns follows a classic modular design philosophy: **IrisCore** handles data transport and connectivity (the "back-end"), while **IrisConduit** handles the user-facing integration in Unreal (the "front-end"). By decoupling these layers, each can evolve or be optimized independently. For example, the underlying DDS transport could be upgraded (say to a new version of Fast DDS or even an alternate DDS implementation) without requiring changes to how developers use the plugin via Conduit. Likewise, new convenience features or UI in IrisConduit won’t interfere with the stability of the core messaging layer.
This design mirrors the division between network protocol and application logic. IrisCore is like the network stack – highly optimized for throughput and reliability – and IrisConduit is akin to the application layer that provides context and usability. The benefit to our users is clarity: when diagnosing an issue or extending functionality, it’s clear whether it’s a transport-level concern or an interface-level concern.
Data Flow and Architecture Overview
Here’s a high-level view of how data flows through Project Iris:
- Unreal Engine Actors/Components: Your game entities (cameras, sensors, robots) produce or consume data. For instance, a camera captures an image, or a robot actor needs a velocity command.
- IrisConduit Components/APIs: Attached to those actors are IrisConduit components (e.g., Publisher/Subscriber). They take the actor data (the camera image) and hand it to IrisCore as a ROS 2 message, or receive a ROS 2 message (velocity command) and apply it to the actor. This is the bridging step where game logic meets ROS 2 message structures.
- IrisCore Transport Layer: IrisCore receives messages from Conduit and uses Fast DDS to publish them to the ROS 2 network, or receives DDS messages from ROS 2 and passes them up to Conduit. It manages the DDS session, including discovery of ROS 2 nodes, reading/writing from network buffers, and queueing data. Importantly, IrisCore operates asynchronously – often on separate threads – to ensure smooth real-time performance.
- ROS 2 Nodes: On the ROS 2 side, standard ROS 2 nodes (in simulations or running on robots) subscribe or publish as usual. To them, Project Iris appears simply as another ROS 2 participant (because it is one, by virtue of using DDS). A ROS 2 node might subscribe to the camera topic and get images from Unreal, or publish a command topic that the Unreal side subscribes to.
The above pipeline is fully distributed and decentralized – thanks to DDS, there is no central server bottleneck. Unreal and ROS 2 communicate peer-to-peer. This design choice means no single point of failure and reduces latency since messages don’t have to hop through intermediate brokers. It’s inherently scalable: you can have multiple Unreal instances, numerous ROS 2 nodes, all discovering each other and exchanging data as needed.
Performance and Threading
To achieve real-time performance, Project Iris leverages multi-threaded design. IrisCore runs the DDS communications possibly in a separate thread (or threads) from the Unreal game thread. This way, heavy networking activity – like pumping through a 60 FPS video feed or a 100k-point LIDAR scan – won’t stall your rendering or physics. We carefully synchronize data at the Conduit boundary: for example, when an image frame is ready to send, IrisConduit will safely transfer it to IrisCore’s thread for sending. Conversely, incoming data from IrisCore is buffered and handed to the game thread in a thread-safe manner (often via queued events or Unreal’s task graph) to update game objects. The end result is a smooth simulation even under high data load.
Quality of Service (QoS) settings also play a role in performance tuning at the design level. By default, Project Iris uses ROS 2’s default QoS for each message type, which are chosen to balance performance and reliability. Developers can adjust these if needed (e.g., switching a topic to best-effort to reduce networking overhead, or increasing the history depth for a critical topic to ensure no data is missed). The architecture ensures that such QoS policies propagate correctly through IrisCore to the DDS layer:contentReference[oaicite:22]{index=22}.
Design Inspirations
We drew inspiration from both modern software engineering practices and a bit of mythology. The idea of Iris as the messenger goddess – carrying information (in her case, messages of the gods) at the speed of wind and across the arc of a rainbow – nicely metaphorizes what we aimed for: **swift, reliable, and illuminating communication**. Just as Iris’s rainbow connects heaven and earth, Project Iris connects simulation and reality, via a spectrum of data (“light”) converted into meaningful information. This framing guided our emphasis on reliability and clarity in the design. In practical terms, it meant rigorously using proven standards (DDS) for the messenger role, and creating clear interfaces (Conduit) for those sending and receiving the messages.
Moreover, our internal development philosophy was to prioritize technical accuracy over flashy gimmicks. You will not find artificial limitations or fake benchmarks in our materials – any performance claim we make is backed by real data or the known capabilities of the underlying DDS system:contentReference[oaicite:23]{index=23}. We believe that by building on solid engineering (and citing those foundations), Project Iris earns the trust of developers who depend on it for mission-critical simulation work.