Spaces:
Running
Running
Aditya Shankar
feat: added dataset recording; hf uploader, s3 uploader; runpod trainer (#6)
4384839
unverified
"use client"; | |
import { NonIndexedLeRobotDatasetRow } from "@lerobot/web"; | |
import { TeleoperatorJointGraph } from "./teleoperator-joint-graph"; | |
interface TeleoperatorFramesViewProps { | |
frames: NonIndexedLeRobotDatasetRow[]; | |
} | |
export function TeleoperatorFramesView({ frames }: TeleoperatorFramesViewProps) { | |
// Joint names in the order they appear in the arrays | |
const jointNames = [ | |
"shoulder_pan", | |
"shoulder_lift", | |
"elbow_flex", | |
"wrist_flex", | |
"wrist_roll", | |
"gripper" | |
]; | |
// Helper function to format an object as a column of key-value pairs with joint names | |
const formatArrayAsColumn = (obj: Record<number, number>): string => { | |
return Object.entries(obj) | |
.map(([key, value]) => { | |
// Convert numeric key to joint name if possible | |
const index = parseInt(key); | |
const jointName = !isNaN(index) && index < jointNames.length ? jointNames[index] : key; | |
return `${jointName}: ${value}`; | |
}) | |
.join('\n'); | |
}; | |
return ( | |
<div className="ml-8 mr-4 mb-2"> | |
{/* Joint visualization graph */} | |
<TeleoperatorJointGraph frames={frames} /> | |
{/* Frames container with horizontal scroll */} | |
<div className="bg-gray-800/50 rounded-md overflow-hidden"> | |
<div className="overflow-x-auto"> | |
{/* Frames header */} | |
<table className="w-full min-w-max table-fixed"> | |
<thead> | |
<tr className="text-xs font-medium bg-gray-800/80 text-gray-300"> | |
<th className="w-16 px-2 py-1 text-left">Frame</th> | |
<th className="w-64 px-2 py-1 text-left">Timestamp</th> | |
<th className="w-[300px] px-2 py-1 text-left">Action</th> | |
<th className="w-[500px] px-2 py-1 text-left">State</th> | |
</tr> | |
</thead> | |
{/* Frame rows */} | |
<tbody className="max-h-60 overflow-y-auto"> | |
{frames.map((frame: NonIndexedLeRobotDatasetRow, frameIndex: number) => ( | |
<tr key={frameIndex} className="text-xs border-t border-gray-700/50"> | |
<td className="w-16 px-2 py-1 font-mono whitespace-nowrap">{frameIndex}</td> | |
<td className="w-64 px-2 py-1 font-mono whitespace-nowrap"> | |
{frame.timestamp} | |
</td> | |
<td className="w-[200px] px-2 py-1 font-mono whitespace-pre-wrap align-top"> | |
{Object.keys(frame.action).length > 0 ? | |
formatArrayAsColumn(frame.action) : | |
'-'} | |
</td> | |
<td className="w-[300px] px-2 py-1 font-mono whitespace-pre-wrap align-top"> | |
{Object.keys(frame["observation.state"]).length > 0 ? | |
formatArrayAsColumn(frame["observation.state"]) : | |
'-'} | |
</td> | |
</tr> | |
))} | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</div> | |
); | |
} | |