import React from "react"; import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from "recharts"; import { NonIndexedLeRobotDatasetRow } from "@lerobot/web"; interface TeleoperatorJointGraphProps { frames: NonIndexedLeRobotDatasetRow[]; } export function TeleoperatorJointGraph({ frames }: TeleoperatorJointGraphProps) { // Skip rendering if no frames if (!frames || frames.length === 0) { return null; } // Use hardcoded joint names that match the LeRobot dataset format const jointNames = [ "shoulder_pan", "shoulder_lift", "elbow_flex", "wrist_flex", "wrist_roll", "gripper" ]; // Generate a color palette for the joints const colors = [ "#8884d8", "#82ca9d", "#ffc658", "#ff8042", "#0088fe", "#00C49F", "#FFBB28", "#FF8042", "#a4de6c", "#d0ed57" ]; // Prepare data for the chart - handling arrays const chartData = frames.map((frame, index) => { // Create base data point with index const dataPoint: any = { name: index, timestamp: frame.timestamp }; // Add action values (assuming action is an array) if (Array.isArray(frame.action)) { // Map each array index to the corresponding joint name jointNames.forEach((jointName, i) => { if (i < frame.action.length) { dataPoint[`action_${jointName}`] = frame.action[i]; } }); } // Add observation state values (assuming observation.state is an array) if (Array.isArray(frame["observation.state"])) { // Map each array index to the corresponding joint name jointNames.forEach((jointName, i) => { if (i < frame["observation.state"].length) { dataPoint[`state_${jointName}`] = frame["observation.state"][i]; } }); } return dataPoint; }); // Create lines for each joint const linesToRender = jointNames.flatMap(jointName => [ { key: `action_${jointName}`, dataKey: `action_${jointName}`, name: `Action: ${jointName}`, isDotted: true }, { key: `state_${jointName}`, dataKey: `state_${jointName}`, name: `State: ${jointName}`, isDotted: false } ]); return (