mirror of
https://github.com/soconnor0919/hristudio.git
synced 2026-03-23 19:27:51 -04:00
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:
@@ -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}
|
||||
|
||||
Reference in New Issue
Block a user