# Experiment Designer ## Overview The Experiment Designer is a core feature of HRIStudio that enables researchers to create and configure robot experiments using a visual, flow-based interface. It supports drag-and-drop functionality, real-time updates, and integration with the plugin system. ## Architecture ### Core Components ```typescript interface ExperimentDesignerProps { className?: string; defaultSteps?: Step[]; onChange?: (steps: Step[]) => void; readOnly?: boolean; } export function ExperimentDesigner({ className, defaultSteps = [], onChange, readOnly = false, }: ExperimentDesignerProps) { // Implementation } ``` ### Data Types ```typescript export type ActionType = | "move" // Robot movement | "speak" // Robot speech | "wait" // Wait for a duration | "input" // Wait for user input | "gesture" // Robot gesture | "record" // Start/stop recording | "condition" // Conditional branching | "loop"; // Repeat actions export interface Action { id: string; type: ActionType; parameters: Record; order: number; } export interface Step { id: string; title: string; description?: string; actions: Action[]; order: number; } export interface Experiment { id: number; studyId: number; title: string; description?: string; version: number; status: "draft" | "active" | "archived"; steps: Step[]; createdAt: Date; updatedAt: Date; } ``` ## Visual Components ### Action Node ```typescript interface ActionNodeData { type: string; parameters: Record; onChange?: (parameters: Record) => void; } export const ActionNode = memo(({ data, selected }: NodeProps) => { const [configOpen, setConfigOpen] = useState(false); const [isHovered, setIsHovered] = useState(false); const actionConfig = AVAILABLE_ACTIONS.find((a) => a.type === data.type); return (
{actionConfig?.icon}
{actionConfig?.title}
{actionConfig?.description}
); }); ``` ### Flow Edge ```typescript export function FlowEdge({ id, sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, style = {}, markerEnd, }: EdgeProps) { const [edgePath] = getBezierPath({ sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, }); return ( <> ); } ``` ## Action Configuration ### Available Actions ```typescript export const AVAILABLE_ACTIONS: ActionConfig[] = [ { type: "move", title: "Move Robot", description: "Move the robot to a specific position", icon: , defaultParameters: { position: { x: 0, y: 0, z: 0 }, speed: 1, easing: "linear", }, }, { type: "speak", title: "Robot Speech", description: "Make the robot say something", icon: , defaultParameters: { text: "", speed: 1, pitch: 1, volume: 1, }, }, // Additional actions... ]; ``` ### Parameter Configuration Dialog ```typescript interface ActionConfigDialogProps { open: boolean; onOpenChange: (open: boolean) => void; type: ActionType; parameters: Record; onSubmit: (parameters: Record) => void; } export function ActionConfigDialog({ open, onOpenChange, type, parameters, onSubmit, }: ActionConfigDialogProps) { const actionConfig = AVAILABLE_ACTIONS.find(a => a.type === type); return ( Configure {actionConfig?.title} {actionConfig?.description}
{/* Parameter fields */}
); } ``` ## Database Schema ```typescript export const experiments = createTable("experiment", { id: integer("id").primaryKey().notNull().generatedAlwaysAsIdentity(), studyId: integer("study_id") .notNull() .references(() => studies.id, { onDelete: "cascade" }), title: varchar("title", { length: 256 }).notNull(), description: text("description"), version: integer("version").notNull().default(1), status: experimentStatusEnum("status").notNull().default("draft"), steps: jsonb("steps").$type().default([]), createdById: varchar("created_by", { length: 255 }) .notNull() .references(() => users.id), createdAt: timestamp("created_at").defaultNow().notNull(), updatedAt: timestamp("updated_at").defaultNow().notNull(), }); ``` ## Integration with Plugin System ### Action Transformation ```typescript interface ActionTransform { type: "direct" | "transform"; transformFn?: string; map?: Record; } function transformActionParameters( parameters: Record, transform: ActionTransform ): unknown { if (transform.type === "direct") { return parameters; } const transformFn = getTransformFunction(transform.transformFn!); return transformFn(parameters); } ``` ### Plugin Action Integration ```typescript function getAvailableActions(plugin: RobotPlugin): ActionConfig[] { return plugin.actions.map(action => ({ type: action.type, title: action.title, description: action.description, icon: getActionIcon(action.type), defaultParameters: getDefaultParameters(action.parameters), transform: action.ros2?.payloadMapping, })); } ``` ## User Interface Features ### Drag and Drop ```typescript function onDragStart(event: DragEvent, nodeType: string) { event.dataTransfer.setData("application/reactflow", nodeType); event.dataTransfer.effectAllowed = "move"; } function onDrop(event: DragEvent) { event.preventDefault(); const type = event.dataTransfer.getData("application/reactflow"); const position = project({ x: event.clientX, y: event.clientY, }); const newNode = { id: getId(), type, position, data: { label: `${type} node` }, }; setNodes((nds) => nds.concat(newNode)); } ``` ### Step Organization ```typescript function reorderSteps(steps: Step[], sourceIndex: number, targetIndex: number): Step[] { const result = Array.from(steps); const [removed] = result.splice(sourceIndex, 1); result.splice(targetIndex, 0, removed); return result.map((step, index) => ({ ...step, order: index, })); } ``` ## Best Practices 1. **Performance:** - Use React.memo for expensive components - Implement virtualization for large flows - Optimize drag and drop operations 2. **User Experience:** - Provide clear visual feedback - Implement undo/redo functionality - Show validation errors inline 3. **Data Management:** - Validate experiment data - Implement auto-save - Version control experiments 4. **Error Handling:** - Validate action parameters - Handle plugin loading errors - Provide clear error messages ## Future Enhancements 1. **Advanced Flow Control:** - Conditional branching - Parallel execution - Loop constructs 2. **Visual Improvements:** - Custom node themes - Animation preview - Mini-map navigation 3. **Collaboration:** - Real-time collaboration - Comment system - Version history 4. **Analysis Tools:** - Flow validation - Performance analysis - Debug tools