Spaces:
Running
Running
| import { useState } from "react"; | |
| import { supabase } from "@/integrations/supabase/client"; | |
| import { UrdfData } from "@/lib/types"; | |
| import { toast } from "sonner"; | |
| export const useUrdfParser = () => { | |
| const [isLoading, setIsLoading] = useState(false); | |
| const [error, setError] = useState<string | null>(null); | |
| const [data, setData] = useState<UrdfData | null>(null); | |
| const parseUrdf = async (urdfContent: string) => { | |
| const requestId = `urdf-${Date.now()}`; // Generate unique ID for tracking this request | |
| console.log(`[${requestId}] π Urdf Parser: Starting parse request`); | |
| console.log( | |
| `[${requestId}] π Content preview:`, | |
| urdfContent?.substring(0, 100) + "..." | |
| ); | |
| // Check if the Urdf content is too large | |
| const MAX_SIZE = 4 * 1024 * 1024; // 4MB limit | |
| if (urdfContent.length > MAX_SIZE) { | |
| const errorMessage = `Urdf content too large (${( | |
| urdfContent.length / | |
| 1024 / | |
| 1024 | |
| ).toFixed(2)}MB). Maximum size is ${MAX_SIZE / 1024 / 1024}MB.`; | |
| console.error(`[${requestId}] β ${errorMessage}`); | |
| setError(errorMessage); | |
| toast.error("File too large", { | |
| description: errorMessage, | |
| duration: 5000, | |
| }); | |
| return null; | |
| } | |
| setIsLoading(true); | |
| setError(null); | |
| const startTime = performance.now(); | |
| try { | |
| // Make sure the urdfContent is a string | |
| if (typeof urdfContent !== "string") { | |
| throw new Error("Urdf content must be a string"); | |
| } | |
| console.log( | |
| `[${requestId}] π‘ Calling Supabase edge function "urdf-parser"...` | |
| ); | |
| const { data: rawResponse, error } = await supabase.functions.invoke( | |
| "urdf-parser", | |
| { | |
| body: { urdfContent }, | |
| } | |
| ); | |
| if (error) { | |
| console.error(`[${requestId}] β Supabase function error:`, error); | |
| // Handle different error cases | |
| if (error.message.includes("non-2xx status code")) { | |
| // Server error from edge function | |
| const serverErrorMsg = | |
| "The Urdf parser encountered a server error. It might be due to the complexity of your Urdf file or temporary server issues."; | |
| console.error(`[${requestId}] π₯ Server error in edge function`); | |
| // Check if we got fallback data despite the error | |
| if (rawResponse && rawResponse.fallback) { | |
| console.log(`[${requestId}] π Using fallback data from server`); | |
| toast.warning("Reduced Urdf Data", { | |
| description: | |
| "Limited information extracted from your Urdf file due to parsing limitations.", | |
| duration: 5000, | |
| }); | |
| // Use the fallback data | |
| setData(rawResponse.fallback); | |
| return rawResponse.fallback; | |
| } | |
| toast.error("Urdf Parser Error", { | |
| description: serverErrorMsg, | |
| duration: 5000, | |
| }); | |
| setError(serverErrorMsg); | |
| } else if (error.message.includes("timeout")) { | |
| // Timeout error | |
| const timeoutMsg = | |
| "The Urdf parser timed out. Your file might be too complex to process within the allowed time."; | |
| console.error(`[${requestId}] β±οΈ Edge function timed out`); | |
| toast.error("Processing Timeout", { | |
| description: timeoutMsg, | |
| duration: 5000, | |
| }); | |
| setError(timeoutMsg); | |
| } else { | |
| // Generic error | |
| setError(error.message); | |
| toast.error("Error Parsing Urdf", { | |
| description: error.message, | |
| duration: 5000, | |
| }); | |
| } | |
| throw error; | |
| } | |
| const endTime = performance.now(); | |
| console.log( | |
| `[${requestId}] β Edge function responded in ${( | |
| endTime - startTime | |
| ).toFixed(2)}ms` | |
| ); | |
| console.log( | |
| `[${requestId}] π Response data structure:`, | |
| Object.keys(rawResponse || {}) | |
| ); | |
| console.log(`[${requestId}] π¦ Full response:`, rawResponse); | |
| // Transform raw data into UrdfData format | |
| let transformedData: UrdfData | null = null; | |
| if (rawResponse && rawResponse.success && rawResponse.data) { | |
| const responseData = rawResponse.data; | |
| // Count joint types from raw joints array | |
| const jointTypes: { [key: string]: number } = { | |
| revolute: 0, | |
| prismatic: 0, | |
| continuous: 0, | |
| fixed: 0, | |
| other: 0, | |
| }; | |
| if (responseData.joints && Array.isArray(responseData.joints)) { | |
| responseData.joints.forEach((joint) => { | |
| const type = joint.type?.toLowerCase() || "other"; | |
| if (type in jointTypes) { | |
| jointTypes[type]++; | |
| } else { | |
| jointTypes.other++; | |
| } | |
| }); | |
| } | |
| // Transform links to expected format | |
| const transformedLinks = | |
| responseData.links?.map((link) => ({ | |
| name: link.name, | |
| mass: link.mass, | |
| })) || []; | |
| // Calculate total mass - either use the one from the response or sum up links | |
| const totalMass = | |
| responseData.total_mass || | |
| transformedLinks.reduce((sum, link) => sum + (link.mass || 0), 0); | |
| // Create the transformed data object | |
| transformedData = { | |
| name: responseData.name, | |
| description: | |
| "A detailed 3D model of a robotic system with articulated joints and components.", | |
| mass: totalMass, | |
| dofs: responseData.num_joints || responseData.joints?.length || 0, | |
| joints: { | |
| revolute: jointTypes.revolute, | |
| prismatic: jointTypes.prismatic, | |
| continuous: jointTypes.continuous, | |
| fixed: jointTypes.fixed, | |
| other: jointTypes.other, | |
| }, | |
| links: transformedLinks, | |
| // Default materials since we don't have this info from Urdf | |
| materials: [{ name: "Metal", percentage: 100 }], | |
| }; | |
| console.log(`[${requestId}] π Transformed data:`, transformedData); | |
| } | |
| setData(transformedData); | |
| return transformedData; | |
| } catch (err) { | |
| const errorMessage = | |
| err instanceof Error ? err.message : "Unknown error occurred"; | |
| const endTime = performance.now(); | |
| console.error( | |
| `[${requestId}] β Error parsing Urdf after ${( | |
| endTime - startTime | |
| ).toFixed(2)}ms:`, | |
| err | |
| ); | |
| console.error(`[${requestId}] π§© Error details:`, { | |
| message: errorMessage, | |
| type: err instanceof Error ? err.constructor.name : typeof err, | |
| stack: err instanceof Error ? err.stack : undefined, | |
| }); | |
| setError(errorMessage); | |
| return null; | |
| } finally { | |
| setIsLoading(false); | |
| console.log( | |
| `[${requestId}] π Urdf parsing request completed, isLoading set to false` | |
| ); | |
| } | |
| }; | |
| return { | |
| parseUrdf, | |
| data, | |
| isLoading, | |
| error, | |
| }; | |
| }; | |