feat: Complete NAO6 robot integration with HRIStudio platform

MAJOR INTEGRATION COMPLETE:

🤖 Robot Communication System:
- RobotCommunicationService for WebSocket ROS bridge integration
- Template-based message generation from plugin definitions
- Real-time action execution with error handling and reconnection

🔧 Trial Execution Engine:
- Updated TrialExecutionEngine to execute real robot actions
- Plugin-based action discovery and parameter validation
- Complete event logging for robot actions during trials

🎮 Wizard Interface Integration:
- RobotActionsPanel component for live robot control
- Plugin-based action discovery with categorized interface
- Real-time parameter forms auto-generated from schemas
- Emergency controls and safety features

📊 Database Integration:
- Enhanced plugin system with NAO6 definitions
- Robot action logging to trial events
- Study-scoped plugin installations

🔌 API Enhancement:
- executeRobotAction endpoint in trials router
- Parameter validation against plugin schemas
- Complete error handling and success tracking

 Production Ready Features:
- Parameter validation prevents invalid commands
- Emergency stop controls in wizard interface
- Connection management with auto-reconnect
- Complete audit trail of robot actions

TESTING READY:
- Seed script creates NAO6 experiment with robot actions
- Complete wizard interface for manual robot control
- Works with or without physical robot hardware

Ready for HRI research with live NAO6 robots!
This commit is contained in:
2025-10-17 11:35:36 -04:00
parent c206f86047
commit 7072ee487b
7 changed files with 1531 additions and 35 deletions

View File

@@ -68,7 +68,7 @@ export function WizardInterface({
// Persistent tab states to prevent resets from parent re-renders
const [controlPanelTab, setControlPanelTab] = useState<
"control" | "step" | "actions"
"control" | "step" | "actions" | "robot"
>("control");
const [executionPanelTab, setExecutionPanelTab] = useState<
"current" | "timeline" | "events"
@@ -86,6 +86,20 @@ export function WizardInterface({
},
);
// Robot action execution mutation
const executeRobotActionMutation = api.trials.executeRobotAction.useMutation({
onSuccess: (result) => {
toast.success("Robot action executed successfully", {
description: `Completed in ${result.duration}ms`,
});
},
onError: (error) => {
toast.error("Failed to execute robot action", {
description: error.message,
});
},
});
// Map database step types to component step types
const mapStepType = (dbType: string) => {
switch (dbType) {
@@ -304,6 +318,23 @@ export function WizardInterface({
}
};
const handleExecuteRobotAction = async (
pluginName: string,
actionId: string,
parameters: Record<string, unknown>,
) => {
try {
await executeRobotActionMutation.mutateAsync({
trialId: trial.id,
pluginName,
actionId,
parameters,
});
} catch (error) {
console.error("Failed to execute robot action:", error);
}
};
return (
<div className="flex h-full flex-col">
{/* Compact Status Bar */}
@@ -370,6 +401,8 @@ export function WizardInterface({
onCompleteTrial={handleCompleteTrial}
onAbortTrial={handleAbortTrial}
onExecuteAction={handleExecuteAction}
onExecuteRobotAction={handleExecuteRobotAction}
studyId={trial.experiment.studyId}
_isConnected={true}
activeTab={controlPanelTab}
onTabChange={setControlPanelTab}