Spaces:
Running
Running
| import React from "react"; | |
| import { useNavigate } from "react-router-dom"; | |
| import VisualizerPanel from "@/components/control/VisualizerPanel"; | |
| import { useToast } from "@/hooks/use-toast"; | |
| import DirectFollowerControlPanel from "@/components/control/DirectFollowerControlPanel"; | |
| import UrdfViewer from "@/components/UrdfViewer"; | |
| import UrdfProcessorInitializer from "@/components/UrdfProcessorInitializer"; | |
| import Logo from "@/components/Logo"; | |
| const DirectFollowerPage = () => { | |
| const navigate = useNavigate(); | |
| const { toast } = useToast(); | |
| const handleGoBack = async () => { | |
| try { | |
| // Stop the direct follower control process before navigating back | |
| console.log("🛑 Stopping direct follower control..."); | |
| const response = await fetch("http://localhost:8000/stop-direct-follower", { | |
| method: "POST", | |
| }); | |
| if (response.ok) { | |
| const result = await response.json(); | |
| console.log("✅ Direct follower control stopped:", result.message); | |
| toast({ | |
| title: "Direct Follower Control Stopped", | |
| description: | |
| result.message || | |
| "Direct follower control has been stopped successfully.", | |
| }); | |
| } else { | |
| const errorText = await response.text(); | |
| console.warn( | |
| "⚠️ Failed to stop direct follower control:", | |
| response.status, | |
| errorText | |
| ); | |
| toast({ | |
| title: "Warning", | |
| description: `Failed to stop direct follower control properly. Status: ${response.status}`, | |
| variant: "destructive", | |
| }); | |
| } | |
| } catch (error) { | |
| console.error("❌ Error stopping direct follower control:", error); | |
| toast({ | |
| title: "Error", | |
| description: "Failed to communicate with the robot server.", | |
| variant: "destructive", | |
| }); | |
| } finally { | |
| // Navigate back regardless of the result | |
| navigate("/"); | |
| } | |
| }; | |
| return ( | |
| <div className="min-h-screen bg-black flex items-center justify-center p-2 sm:p-4"> | |
| <div className="w-full h-[95vh] flex flex-col lg:flex-row gap-4"> | |
| {/* Left: Visualizer */} | |
| <div className="flex-1 flex flex-col"> | |
| <div className="bg-gray-900 rounded-lg p-4 flex-1 flex flex-col"> | |
| <div className="flex items-center gap-4 mb-4"> | |
| <button | |
| onClick={handleGoBack} | |
| className="text-gray-400 hover:text-white hover:bg-gray-800 p-2 rounded transition-colors" | |
| aria-label="Go Back" | |
| > | |
| <svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"> | |
| <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" /> | |
| </svg> | |
| </button> | |
| {/* Only the logo, no "LiveLab" or blue L avatar */} | |
| <Logo iconOnly /> | |
| <div className="w-px h-6 bg-gray-700" /> | |
| <h2 className="text-xl font-medium text-gray-200">Direct Follower Control</h2> | |
| </div> | |
| {/* Visualization area */} | |
| <div className="flex-1 bg-black rounded border border-gray-800 min-h-[50vh]"> | |
| <div className="w-full h-full flex items-center justify-center"> | |
| <div className="w-full h-full"> | |
| {/* Urdf Viewer only */} | |
| <VisualizerOnlyUrdf /> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| {/* Right: Control Panel */} | |
| <div className="lg:w-[400px] flex-shrink-0 flex flex-col"> | |
| <DirectFollowerControlPanel /> | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| // Helper component to render just the URDF viewer | |
| const VisualizerOnlyUrdf: React.FC = () => { | |
| // Important: Keep this separate from panels with cameras! | |
| return ( | |
| <div className="w-full h-full"> | |
| {/* Use the same URDF viewer as in Teleoperation */} | |
| <React.Suspense fallback={<div className="text-gray-400 p-12 text-center">Loading robot model...</div>}> | |
| <UrdfVisualizerWithProcessor /> | |
| </React.Suspense> | |
| </div> | |
| ); | |
| }; | |
| const UrdfVisualizerWithProcessor: React.FC = () => ( | |
| <> | |
| <UrdfProcessorInitializer /> | |
| <UrdfViewer /> | |
| </> | |
| ); | |
| export default DirectFollowerPage; | |