<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: liesliy</title>
    <description>The latest articles on DEV Community by liesliy (@liesliy).</description>
    <link>https://dev.to/liesliy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4057379%2F01a5a8ba-545c-4533-bd77-5f940e75f65c.png</url>
      <title>DEV Community: liesliy</title>
      <link>https://dev.to/liesliy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/liesliy"/>
    <language>en</language>
    <item>
      <title>Robot Training Data Is Messier Than You Think: Auditing 4,959 Episodes with an Open-Source Tool</title>
      <dc:creator>liesliy</dc:creator>
      <pubDate>Fri, 21 Aug 2026 08:48:10 +0000</pubDate>
      <link>https://dev.to/liesliy/robot-training-data-is-messier-than-you-think-auditing-4959-episodes-with-an-open-source-tool-20ke</link>
      <guid>https://dev.to/liesliy/robot-training-data-is-messier-than-you-think-auditing-4959-episodes-with-an-open-source-tool-20ke</guid>
      <description>&lt;p&gt;Robot learning is getting better very quickly.&lt;/p&gt;

&lt;p&gt;We now have better policy architectures, more capable simulation environments, standardized dataset formats such as LeRobot, and an increasing number of public robot manipulation datasets.&lt;/p&gt;

&lt;p&gt;But there is a basic question that is surprisingly difficult to answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How do we know whether a robot training dataset is actually usable?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A dataset can be perfectly readable and still be a poor training dataset.&lt;/p&gt;

&lt;p&gt;It can have valid Parquet files, correct schemas, and complete metadata while containing excessive idle motion, action discontinuities, sampling problems, distribution anomalies, or episodes that deserve human review.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;RDA (Robot Data Audit)&lt;/strong&gt; to explore this problem.&lt;/p&gt;

&lt;p&gt;I recently ran it across &lt;strong&gt;12 local robot datasets and 4,959 episodes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here is what I found.&lt;/p&gt;




&lt;h2&gt;
  
  
  "Can I Load It?" Is Not the Same as "Can I Train on It?"
&lt;/h2&gt;

&lt;p&gt;Robot datasets can contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;camera observations&lt;/li&gt;
&lt;li&gt;joint states&lt;/li&gt;
&lt;li&gt;actions&lt;/li&gt;
&lt;li&gt;timestamps&lt;/li&gt;
&lt;li&gt;task metadata&lt;/li&gt;
&lt;li&gt;robot configuration&lt;/li&gt;
&lt;li&gt;multiple sensor streams&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most data pipelines start with a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I load the dataset?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's necessary, but it isn't enough.&lt;/p&gt;

&lt;p&gt;I think robot data quality needs to be considered in several layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structural integrity&lt;/td&gt;
&lt;td&gt;Does the data actually exist and load correctly?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Schema &amp;amp; temporal integrity&lt;/td&gt;
&lt;td&gt;Are fields, values, and timestamps valid?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Behavioral quality&lt;/td&gt;
&lt;td&gt;Does the robot motion contain suspicious patterns?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Task relevance&lt;/td&gt;
&lt;td&gt;Are those patterns actually harmful for this task?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;RDA currently focuses primarily on the first three layers and produces structured evidence that can be used to investigate the fourth.&lt;/p&gt;

&lt;p&gt;This distinction matters.&lt;/p&gt;

&lt;p&gt;A statistical anomaly is not automatically a failed demonstration.&lt;/p&gt;

&lt;p&gt;And a dataset that passes structural validation is not automatically good training data.&lt;/p&gt;




&lt;h1&gt;
  
  
  What RDA Actually Measures
&lt;/h1&gt;

&lt;p&gt;RDA is an open-source, local-first auditing tool for LeRobot-format robot manipulation datasets.&lt;/p&gt;

&lt;p&gt;The core audit runs locally and does not require a GPU.&lt;/p&gt;

&lt;p&gt;The current version checks 13 metrics across three layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1 — Structural Integrity
&lt;/h3&gt;

&lt;p&gt;Deterministic checks include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing frames&lt;/li&gt;
&lt;li&gt;NaN / Inf values&lt;/li&gt;
&lt;li&gt;schema consistency&lt;/li&gt;
&lt;li&gt;timestamp validity&lt;/li&gt;
&lt;li&gt;joint limits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hard structural failures can result in an &lt;code&gt;EXCLUDE&lt;/code&gt; verdict.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 2 — Temporal &amp;amp; Motion Quality
&lt;/h3&gt;

&lt;p&gt;These checks look for statistical risk signals such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sensor synchronization&lt;/li&gt;
&lt;li&gt;sampling jitter&lt;/li&gt;
&lt;li&gt;velocity / acceleration anomalies&lt;/li&gt;
&lt;li&gt;action discontinuity&lt;/li&gt;
&lt;li&gt;temporal sufficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are generally signals for investigation rather than proof that an episode is unusable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 3 — Dataset Utility
&lt;/h3&gt;

&lt;p&gt;This includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;idle ratio&lt;/li&gt;
&lt;li&gt;distribution characteristics&lt;/li&gt;
&lt;li&gt;state-space coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These metrics are particularly contextual.&lt;/p&gt;

&lt;p&gt;For example, a high idle ratio may be perfectly reasonable for one task and problematic for another.&lt;/p&gt;




&lt;h1&gt;
  
  
  PASS, REVIEW, EXCLUDE — But Don't Confuse Them with Ground Truth
&lt;/h1&gt;

&lt;p&gt;One design decision became particularly important during development.&lt;/p&gt;

&lt;p&gt;RDA separates &lt;strong&gt;workflow verdicts&lt;/strong&gt; from &lt;strong&gt;evidence levels&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The workflow verdict is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;PASS&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;REVIEW&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EXCLUDE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The evidence level is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;HARD_FAIL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RISK_SIGNAL&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UNVERIFIABLE&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are deliberately different concepts.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;High action discontinuity → &lt;code&gt;RISK_SIGNAL&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;does &lt;strong&gt;not&lt;/strong&gt; mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The demonstration is corrupted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Likewise:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Missing frames → &lt;code&gt;HARD_FAIL&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;does not necessarily mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The entire upstream dataset is bad.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The purpose is to keep an audit tool from turning weak statistical evidence into overly confident labels.&lt;/p&gt;




&lt;h1&gt;
  
  
  4,959 Episodes: Almost Half Triggered a Review Signal
&lt;/h1&gt;

&lt;p&gt;I ran RDA across 12 local dataset copies.&lt;/p&gt;

&lt;p&gt;The overall result was:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Verdict&lt;/th&gt;
&lt;th&gt;Episodes&lt;/th&gt;
&lt;th&gt;Percentage&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PASS&lt;/td&gt;
&lt;td&gt;1,711&lt;/td&gt;
&lt;td&gt;34.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;REVIEW&lt;/td&gt;
&lt;td&gt;2,473&lt;/td&gt;
&lt;td&gt;49.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EXCLUDE&lt;/td&gt;
&lt;td&gt;775&lt;/td&gt;
&lt;td&gt;15.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These numbers are &lt;strong&gt;not&lt;/strong&gt; a confusion matrix.&lt;/p&gt;

&lt;p&gt;There was no independent human ground truth for this benchmark, so they cannot be used to claim precision or recall.&lt;/p&gt;

&lt;p&gt;The interesting observation is simply:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A large fraction of the tested episodes contained signals worth investigating before blindly feeding them into training.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That alone is useful.&lt;/p&gt;




&lt;h1&gt;
  
  
  Finding #1: Idle Data Is Everywhere
&lt;/h1&gt;

&lt;p&gt;The median idle ratio across the tested datasets ranged from:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;20.8% to 93.3%.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ten of the twelve datasets had median idle ratios above 65%.&lt;/p&gt;

&lt;p&gt;That raises a surprisingly important question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If a large fraction of your training data represents the robot doing very little, what exactly is the policy learning?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It might be useful temporal context.&lt;/p&gt;

&lt;p&gt;Or it might simply teach the model that doing nothing is common.&lt;/p&gt;

&lt;p&gt;The answer depends heavily on the task and model architecture.&lt;/p&gt;

&lt;p&gt;This led to our first optimization experiment.&lt;/p&gt;




&lt;h1&gt;
  
  
  Finding #2: The Same Robot Can Have Very Different Data Characteristics
&lt;/h1&gt;

&lt;p&gt;Two datasets from the same xArm platform showed a large difference.&lt;/p&gt;

&lt;h3&gt;
  
  
  xArm lift
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Median idle ratio: &lt;strong&gt;20.8%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;767 / 800 episodes received PASS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  xArm push
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Median idle ratio: &lt;strong&gt;83.3%&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;562 / 800 episodes received REVIEW&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Same robot platform.&lt;/p&gt;

&lt;p&gt;Different task.&lt;/p&gt;

&lt;p&gt;The important lesson is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Data quality is not completely independent of task structure.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A high idle ratio is not automatically a collection failure.&lt;/p&gt;

&lt;p&gt;It may simply reflect how the task is performed.&lt;/p&gt;

&lt;p&gt;That makes universal rules like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Delete every episode above 70% idle."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;dangerous.&lt;/p&gt;




&lt;h1&gt;
  
  
  Finding #3: Action Discontinuity May Reveal the Controller
&lt;/h1&gt;

&lt;p&gt;Another interesting pattern appeared in action discontinuity.&lt;/p&gt;

&lt;p&gt;Some datasets showed spikes in essentially every episode.&lt;/p&gt;

&lt;p&gt;Another xArm dataset had only a handful across 800 episodes.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simulated ALOHA datasets showed frequent spikes&lt;/li&gt;
&lt;li&gt;the SO-100 dataset also showed frequent spikes&lt;/li&gt;
&lt;li&gt;xArm lift had only 6 spike-containing episodes out of 800&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This suggests that some data-quality signals may tell us as much about the &lt;strong&gt;collection or control stack&lt;/strong&gt; as about the demonstrations themselves.&lt;/p&gt;

&lt;p&gt;That could matter for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smoothness-regularized policies&lt;/li&gt;
&lt;li&gt;sim-to-real transfer&lt;/li&gt;
&lt;li&gt;controller comparisons&lt;/li&gt;
&lt;li&gt;teleoperation system evaluation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But again:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A discontinuity is a signal, not automatically a failure.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Finding #4: A Dataset Can Be Structurally Clean and Still Need Review
&lt;/h1&gt;

&lt;p&gt;One of the most useful observations from the benchmark was the separation between integrity and behavior.&lt;/p&gt;

&lt;p&gt;Outside of the intentionally corrupted ALOHA fixture, the tested datasets were largely clean at the basic integrity layer.&lt;/p&gt;

&lt;p&gt;Yet the behavioral layer still flagged many episodes for review.&lt;/p&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"The files are valid" and "the demonstrations are ideal for training" are different questions.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This seems obvious after writing it down.&lt;/p&gt;

&lt;p&gt;In practice, however, many pipelines stop at the first question.&lt;/p&gt;




&lt;h1&gt;
  
  
  Finding #5: Sometimes the Dataset Copy Is the Problem
&lt;/h1&gt;

&lt;p&gt;One of the most interesting cases was LIBERO.&lt;/p&gt;

&lt;p&gt;The local metadata declared:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1,693 episodes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But only:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;920 episodes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;could actually be read from the local Parquet files.&lt;/p&gt;

&lt;p&gt;The remaining:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;773 episodes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;were missing from the local copy.&lt;/p&gt;

&lt;p&gt;An earlier loader implementation could interpret this kind of metadata/data-layout mismatch as zero-frame episodes.&lt;/p&gt;

&lt;p&gt;The loader was changed to scan the actual Parquet layout and build a fallback episode index.&lt;/p&gt;

&lt;p&gt;The result was more honest:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The local copy is incomplete.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LIBERO contains 773 empty episodes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This distinction matters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A broken local copy is not necessarily a broken upstream dataset.&lt;/strong&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Then I Compared RDA with Other Tools
&lt;/h1&gt;

&lt;p&gt;I also wanted to understand how different robot-data tooling behaves on deliberately corrupted data.&lt;/p&gt;

&lt;p&gt;So I ran a small cross-tool benchmark involving:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RDA&lt;/li&gt;
&lt;li&gt;trajlens&lt;/li&gt;
&lt;li&gt;ORBIT&lt;/li&gt;
&lt;li&gt;lerobot-doctor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The test included known injected defects.&lt;/p&gt;

&lt;p&gt;One result looked like this:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Defect&lt;/th&gt;
&lt;th&gt;RDA&lt;/th&gt;
&lt;th&gt;trajlens&lt;/th&gt;
&lt;th&gt;ORBIT&lt;/th&gt;
&lt;th&gt;lerobot-doctor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;NaN actions&lt;/td&gt;
&lt;td&gt;EXCLUDE&lt;/td&gt;
&lt;td&gt;WARN&lt;/td&gt;
&lt;td&gt;Crash&lt;/td&gt;
&lt;td&gt;FAIL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timestamp reversal&lt;/td&gt;
&lt;td&gt;EXCLUDE&lt;/td&gt;
&lt;td&gt;FAIL&lt;/td&gt;
&lt;td&gt;Crash&lt;/td&gt;
&lt;td&gt;FAIL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frozen actions&lt;/td&gt;
&lt;td&gt;PASS&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;FAIL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important result wasn't that RDA "won."&lt;/p&gt;

&lt;p&gt;It didn't.&lt;/p&gt;

&lt;p&gt;The frozen-action case exposed a real blind spot.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Frozen-Segment Blind Spot
&lt;/h1&gt;

&lt;p&gt;RDA's current &lt;code&gt;idle_ratio&lt;/code&gt; metric is primarily episode-level.&lt;/p&gt;

&lt;p&gt;That means a dataset can have a reasonable overall idle ratio while still containing a long locally frozen segment.&lt;/p&gt;

&lt;p&gt;Another tool had a dedicated consecutive-identical-actions check and caught it.&lt;/p&gt;

&lt;p&gt;This gives RDA a very concrete next feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;frozen_segment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A good audit tool should be able to identify its own blind spots.&lt;/p&gt;

&lt;p&gt;This one is now on our priority list.&lt;/p&gt;




&lt;h1&gt;
  
  
  Can Data Auditing Actually Improve Training?
&lt;/h1&gt;

&lt;p&gt;Finding suspicious data is only half the problem.&lt;/p&gt;

&lt;p&gt;The more interesting question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Can audit results tell us what to do with the dataset?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I ran several experiments around idle-data pruning.&lt;/p&gt;

&lt;p&gt;The result was much more nuanced than I initially expected.&lt;/p&gt;




&lt;h1&gt;
  
  
  Moderate Pruning Helped — Aggressive Pruning Hurt
&lt;/h1&gt;

&lt;p&gt;In one experiment:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Data retained&lt;/th&gt;
&lt;th&gt;MSE change&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep 50%&lt;/td&gt;
&lt;td&gt;50.1%&lt;/td&gt;
&lt;td&gt;-28.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep 40%&lt;/td&gt;
&lt;td&gt;40.1%&lt;/td&gt;
&lt;td&gt;-12.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep 30%&lt;/td&gt;
&lt;td&gt;30.1%&lt;/td&gt;
&lt;td&gt;-13.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep 20%&lt;/td&gt;
&lt;td&gt;20.0%&lt;/td&gt;
&lt;td&gt;+11.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep 10%&lt;/td&gt;
&lt;td&gt;10.0%&lt;/td&gt;
&lt;td&gt;+98.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There was a clear dose-response pattern.&lt;/p&gt;

&lt;p&gt;Moderate pruning helped in this experiment.&lt;/p&gt;

&lt;p&gt;Aggressive pruning eventually became harmful.&lt;/p&gt;

&lt;p&gt;So the conclusion is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Remove idle data."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;There may be a useful pruning region, but it depends on how the remaining data is used.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Then We Tested Different Model Architectures
&lt;/h1&gt;

&lt;p&gt;This was probably the most interesting result.&lt;/p&gt;

&lt;p&gt;We compared a frame-wise MLP with a temporal Transformer.&lt;/p&gt;

&lt;p&gt;The result was almost the opposite.&lt;/p&gt;

&lt;h3&gt;
  
  
  MLP
&lt;/h3&gt;

&lt;p&gt;Idle-data pruning:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;-21.6% MSE&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Temporal Transformer
&lt;/h3&gt;

&lt;p&gt;Idle-data pruning:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;+95.5% MSE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because temporal models need context.&lt;/p&gt;

&lt;p&gt;Suppose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;idle ratio ≈ 70%&lt;/li&gt;
&lt;li&gt;active segments are scattered&lt;/li&gt;
&lt;li&gt;sequence length = 10&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After pruning, many active segments become shorter than the required temporal window.&lt;/p&gt;

&lt;p&gt;The result:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You removed "low-value" frames and accidentally removed the context required to construct training samples.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is another issue.&lt;/p&gt;

&lt;p&gt;A temporal policy may need to learn the transition:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;idle → movement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If all idle context is removed, the model may never see how movement starts.&lt;/p&gt;




&lt;h1&gt;
  
  
  The Practical Lesson
&lt;/h1&gt;

&lt;p&gt;This changed how I think about automated dataset optimization.&lt;/p&gt;

&lt;p&gt;A rule like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;idle_ratio &amp;gt; 70% → delete&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;is too simplistic.&lt;/p&gt;

&lt;p&gt;The better question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What model are you training, and what temporal structure does that model need?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The current experiments suggest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gentle trimming can be reasonable for frame-wise models&lt;/li&gt;
&lt;li&gt;aggressive idle pruning can be harmful&lt;/li&gt;
&lt;li&gt;temporal models need special handling&lt;/li&gt;
&lt;li&gt;dataset/task domain matters&lt;/li&gt;
&lt;li&gt;audit signals should not automatically become deletion rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why RDA's recommendation layer takes the intended model type into account.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Local-First Architecture
&lt;/h1&gt;

&lt;p&gt;Robot datasets can contain commercially sensitive information.&lt;/p&gt;

&lt;p&gt;They may reveal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;robot configurations&lt;/li&gt;
&lt;li&gt;manipulation strategies&lt;/li&gt;
&lt;li&gt;factory environments&lt;/li&gt;
&lt;li&gt;camera observations&lt;/li&gt;
&lt;li&gt;proprietary tasks&lt;/li&gt;
&lt;li&gt;operator behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RDA's core audit therefore runs locally.&lt;/p&gt;

&lt;p&gt;It can generate a blind report containing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;anonymized paths&lt;/li&gt;
&lt;li&gt;dataset statistics&lt;/li&gt;
&lt;li&gt;episode/frame counts&lt;/li&gt;
&lt;li&gt;metrics&lt;/li&gt;
&lt;li&gt;verdicts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;without sending the raw trajectories or images.&lt;/p&gt;

&lt;p&gt;The goal is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Share evidence without sharing the dataset.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  What RDA Does NOT Claim
&lt;/h1&gt;

&lt;p&gt;This is probably the most important section.&lt;/p&gt;

&lt;p&gt;The current experiments do &lt;strong&gt;not&lt;/strong&gt; establish:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RDA precision&lt;/li&gt;
&lt;li&gt;RDA recall&lt;/li&gt;
&lt;li&gt;universally optimal thresholds&lt;/li&gt;
&lt;li&gt;that every &lt;code&gt;EXCLUDE&lt;/code&gt; episode should be deleted&lt;/li&gt;
&lt;li&gt;that action discontinuity means corruption&lt;/li&gt;
&lt;li&gt;that high idle ratio means useless data&lt;/li&gt;
&lt;li&gt;that RDA improves training success rate&lt;/li&gt;
&lt;li&gt;that RDA certifies compliance with any data-quality standard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benchmark is based on real local dataset runs, but it does not have independent ground-truth labels.&lt;/p&gt;

&lt;p&gt;So the next experiment is obvious:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Get real human or customer QC labels and compare them against RDA without exposing the RDA verdict first.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  The Next Experiment: Blind Human Review
&lt;/h1&gt;

&lt;p&gt;The proposed validation workflow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Select 100–500 episodes from one robot platform.&lt;/li&gt;
&lt;li&gt;Generate anonymized samples.&lt;/li&gt;
&lt;li&gt;Have reviewers independently label them:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;KEEP&lt;/li&gt;
&lt;li&gt;REVIEW&lt;/li&gt;
&lt;li&gt;REMOVE

&lt;ol&gt;
&lt;li&gt;Do not show them RDA's verdict.&lt;/li&gt;
&lt;li&gt;Preserve reviewer decisions and notes.&lt;/li&gt;
&lt;li&gt;Reveal RDA results only after labeling.&lt;/li&gt;
&lt;li&gt;Compare the two sets of evidence.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That would allow us to measure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;overlap between RDA &lt;code&gt;HARD_FAIL&lt;/code&gt; and human &lt;code&gt;REMOVE&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;overlap between RDA &lt;code&gt;RISK_SIGNAL&lt;/code&gt; and human &lt;code&gt;REVIEW&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;additional defects found by RDA&lt;/li&gt;
&lt;li&gt;reviewer time per episode&lt;/li&gt;
&lt;li&gt;review queue reduction&lt;/li&gt;
&lt;li&gt;potential downstream training impact&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Until that experiment is completed, these remain validation targets rather than marketing claims.&lt;/p&gt;




&lt;h1&gt;
  
  
  Try It
&lt;/h1&gt;

&lt;p&gt;RDA is open source and currently supports LeRobot v2.1 and v3.0.&lt;/p&gt;

&lt;p&gt;Install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;robot-data-audit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Audit a dataset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rda audit /path/to/lerobot/dataset &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate a blind report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rda audit /path/to/lerobot/dataset &lt;span class="nt"&gt;--blind&lt;/span&gt; &lt;span class="nt"&gt;--format&lt;/span&gt; json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate optimization recommendations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rda recommend /path/to/dataset &lt;span class="nt"&gt;--policy&lt;/span&gt; frame-wise
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rda recommend /path/to/dataset &lt;span class="nt"&gt;--policy&lt;/span&gt; temporal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Launch the optional UI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;robot-data-audit[ui]
rda ui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/liesliy/rda" rel="noopener noreferrer"&gt;https://github.com/liesliy/rda&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PyPI:&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://pypi.org/project/robot-data-audit/" rel="noopener noreferrer"&gt;https://pypi.org/project/robot-data-audit/&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  What I Want to Test Next
&lt;/h1&gt;

&lt;p&gt;The next step isn't another synthetic benchmark.&lt;/p&gt;

&lt;p&gt;I want to test RDA against &lt;strong&gt;real robot data with independent QC labels&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In particular, I'm looking for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;real-world teleoperation datasets&lt;/li&gt;
&lt;li&gt;datasets with existing QC labels&lt;/li&gt;
&lt;li&gt;datasets containing known failure cases&lt;/li&gt;
&lt;li&gt;datasets used for sim-to-real experiments&lt;/li&gt;
&lt;li&gt;robot companies or research groups willing to run a local audit&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The raw data does not need to leave your environment.&lt;/p&gt;

&lt;p&gt;A small validation set — even &lt;strong&gt;100–500 episodes from one robot and 1–3 tasks&lt;/strong&gt; — would already be extremely useful.&lt;/p&gt;

&lt;p&gt;If you work with robot manipulation data and are willing to challenge these results, I'd love to compare notes.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Takeaway
&lt;/h1&gt;

&lt;p&gt;After auditing thousands of robot episodes, my conclusion is not that robot datasets are "bad."&lt;/p&gt;

&lt;p&gt;It is more subtle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Robot datasets contain many properties that are invisible to a simple "can I load this file?" check.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And those properties can matter differently depending on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the robot&lt;/li&gt;
&lt;li&gt;the task&lt;/li&gt;
&lt;li&gt;the controller&lt;/li&gt;
&lt;li&gt;the dataset format&lt;/li&gt;
&lt;li&gt;the policy architecture&lt;/li&gt;
&lt;li&gt;the intended use of the data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal of RDA is not to produce another mysterious quality score.&lt;/p&gt;

&lt;p&gt;It is to make the path from:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;measurement → diagnosis → human review → optimization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;more reproducible.&lt;/p&gt;

&lt;p&gt;And eventually, hopefully, to make robot data quality something we can discuss with evidence rather than intuition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before the GPU bill arrives, audit the data.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>robotics</category>
      <category>machinelearning</category>
      <category>opensource</category>
      <category>dataset</category>
    </item>
    <item>
      <title># Public Robot Dataset Health Check — as measured by RDA v0.5.2</title>
      <dc:creator>liesliy</dc:creator>
      <pubDate>Wed, 19 Aug 2026 03:30:56 +0000</pubDate>
      <link>https://dev.to/liesliy/-public-robot-dataset-health-check-as-measured-by-rda-v052-1ge8</link>
      <guid>https://dev.to/liesliy/-public-robot-dataset-health-check-as-measured-by-rda-v052-1ge8</guid>
      <description>&lt;p&gt;We ran RDA across &lt;strong&gt;11 public LeRobot-format datasets — 4,909 episodes&lt;/strong&gt; in total, spanning sim and real, scripted and human teleop, research arms and $100 hobby hardware. Summary:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;  
  &lt;thead&gt;  
    &lt;tr&gt;  
      &lt;th&gt;Dataset&lt;/th&gt;  
      &lt;th&gt;Type&lt;/th&gt;  
      &lt;th&gt;Eps&lt;/th&gt;  
      &lt;th&gt;Verdicts (P/R/E)&lt;/th&gt;  
      &lt;th&gt;Action spikes&lt;/th&gt;  
      &lt;th&gt;Idle median&lt;/th&gt;  
      &lt;th&gt;Idle p5&lt;/th&gt;  
    &lt;/tr&gt;  
  &lt;/thead&gt;  
  &lt;tbody&gt;  
    &lt;tr&gt;  
      &lt;td&gt;aloha_sim_insertion_human&lt;/td&gt;  
      &lt;td&gt;sim, human&lt;/td&gt;  
      &lt;td&gt;50&lt;/td&gt;  
      &lt;td&gt;5 / 45 / 0&lt;/td&gt;  
      &lt;td&gt;1,338 (100% eps)&lt;/td&gt;  
      &lt;td&gt;70.7%&lt;/td&gt;  
      &lt;td&gt;65.1%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;aloha_sim_transfer_cube_scripted&lt;/td&gt;  
      &lt;td&gt;sim, scripted&lt;/td&gt;  
      &lt;td&gt;50&lt;/td&gt;  
      &lt;td&gt;5 / 45 / 0&lt;/td&gt;  
      &lt;td&gt;2,489 (100% eps)&lt;/td&gt;  
      &lt;td&gt;64.0%&lt;/td&gt;  
      &lt;td&gt;44.2%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;aloha_sim_insertion_scripted&lt;/td&gt;  
      &lt;td&gt;sim, scripted&lt;/td&gt;  
      &lt;td&gt;50&lt;/td&gt;  
      &lt;td&gt;1 / 49 / 0&lt;/td&gt;  
      &lt;td&gt;1,633 (100% eps)&lt;/td&gt;  
      &lt;td&gt;63.7%&lt;/td&gt;  
      &lt;td&gt;53.7%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;droid_100&lt;/td&gt;  
      &lt;td&gt;real Franka&lt;/td&gt;  
      &lt;td&gt;100&lt;/td&gt;  
      &lt;td&gt;34 / 66 / 0&lt;/td&gt;  
      &lt;td&gt;1,428 (99% eps)&lt;/td&gt;  
      &lt;td&gt;70.7%&lt;/td&gt;  
      &lt;td&gt;55.7%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;pusht&lt;/td&gt;  
      &lt;td&gt;sim&lt;/td&gt;  
      &lt;td&gt;206&lt;/td&gt;  
      &lt;td&gt;43 / 163 / 0&lt;/td&gt;  
      &lt;td&gt;1,148 (97% eps)&lt;/td&gt;  
      &lt;td&gt;81.7%&lt;/td&gt;  
      &lt;td&gt;59.5%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;HuggingFaceVLA/libero&lt;/td&gt;  
      &lt;td&gt;sim&lt;/td&gt;  
      &lt;td&gt;1,693&lt;/td&gt;  
      &lt;td&gt;0 / 3 / 1,690&lt;/td&gt;  
      &lt;td&gt;34 (3 eps)&lt;/td&gt;  
      &lt;td&gt;76.5% (3 eps)&lt;/td&gt;  
      &lt;td&gt;74.6%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;bridge_orig_lerobot (sampled)&lt;/td&gt;  
      &lt;td&gt;real WidowX&lt;/td&gt;  
      &lt;td&gt;25&lt;/td&gt;  
      &lt;td&gt;4 / 21 / 0&lt;/td&gt;  
      &lt;td&gt;91 (84% eps)&lt;/td&gt;  
      &lt;td&gt;&lt;strong&gt;93.3%&lt;/strong&gt;&lt;/td&gt;  
      &lt;td&gt;20.5%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;xarm_lift_medium&lt;/td&gt;  
      &lt;td&gt;real xArm&lt;/td&gt;  
      &lt;td&gt;800&lt;/td&gt;  
      &lt;td&gt;
&lt;strong&gt;767&lt;/strong&gt; / 33 / 0&lt;/td&gt;  
      &lt;td&gt;6 (1% eps)&lt;/td&gt;  
      &lt;td&gt;&lt;strong&gt;20.8%&lt;/strong&gt;&lt;/td&gt;  
      &lt;td&gt;12.5%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;xarm_push_medium&lt;/td&gt;  
      &lt;td&gt;real xArm&lt;/td&gt;  
      &lt;td&gt;800&lt;/td&gt;  
      &lt;td&gt;238 / 562 / 0&lt;/td&gt;  
      &lt;td&gt;845 (62% eps)&lt;/td&gt;  
      &lt;td&gt;83.3%&lt;/td&gt;  
      &lt;td&gt;16.7%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;svla_so101_pickplace&lt;/td&gt;  
      &lt;td&gt;real SO-100&lt;/td&gt;  
      &lt;td&gt;50&lt;/td&gt;  
      &lt;td&gt;5 / 45 / 0&lt;/td&gt;  
      &lt;td&gt;260 (100% eps)&lt;/td&gt;  
      &lt;td&gt;86.7%&lt;/td&gt;  
      &lt;td&gt;59.5%&lt;/td&gt;  
    &lt;/tr&gt;  
    &lt;tr&gt;  
      &lt;td&gt;jaco_play&lt;/td&gt;  
      &lt;td&gt;real Jaco&lt;/td&gt;  
      &lt;td&gt;1,085&lt;/td&gt;  
      &lt;td&gt;390 / 695 / 0&lt;/td&gt;  
      &lt;td&gt;11,958 (77% eps)&lt;/td&gt;  
      &lt;td&gt;74.1%&lt;/td&gt;  
      &lt;td&gt;52.7%&lt;/td&gt;  
    &lt;/tr&gt;  
  &lt;/tbody&gt;  
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;All integrity layers (NaN/Inf, timestamp validity, missing frames, schema) came back clean on all 11. libero note: 1,690 of 1,693 episodes read 0 frames — a dataset-side meta/layout mismatch, now flagged EXCLUDE instead of silently passing. bridge sampled 25 episodes; the other 10 datasets were audited in full. (&lt;code&gt;aloha_sim_transfer_cube_human&lt;/code&gt; was audited earlier at v0.5.1 with matching results: 1/49/0, 1,535 spikes, 71.2% idle — it's now a gated repo, so we couldn't re-pull it.)&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Five patterns worth knowing before you train
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Median idle runs 20.8%–93.3%, and 8 of 11 datasets sit above 65%.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Loss functions trained on a 75%-idle distribution are structurally biased toward predicting "do nothing" unless you weight or curriculum it. Bridge data pushes it to 93%. Measure yours before the GPU bill, not after.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Same robot, same lab, four-fold idle difference.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;xarm_lift_medium&lt;/code&gt;: 20.8% median idle, 767/800 episodes PASS. &lt;code&gt;xarm_push_medium&lt;/code&gt;: 83.3% median idle, 562/800 REVIEW. Same xArm platform — the difference is task difficulty (lifting vs. pushing a flat object), not collection sloppiness. High idle isn't always a bug; it's a property you need to know and design around. RDA flags both sides of this honestly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Action discontinuity tracks the controller, not the dataset's reputation.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Sim ALOHA and the SO-100 hobby setup spike in literally 100% of episodes; xArm lift data has 6 spikes across 800 episodes. If your policy uses smoothness regularization or you're doing sim-to-real action statistics, this number decides your curriculum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Clean integrity ≠ good training data.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Integrity passed 11/11 — zero NaNs, zero timestamp reversals, zero missing frames anywhere. The behavior layer still flagged 45–98% of episodes for review in most datasets. Both layers matter; most pipelines check neither.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Cheap hardware produces the most expensive data.&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
The community SO-100 pick-place set: 86.7% median idle plus spikes in every episode. If you're fine-tuning on hobby-robot uploads, this is what you're inheriting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;robot-data-audit
rda audit &amp;lt;any lerobot dataset&amp;gt; &lt;span class="nt"&gt;-v&lt;/span&gt;
rda recommend &amp;lt;dataset&amp;gt; &lt;span class="nt"&gt;--policy&lt;/span&gt; temporal   &lt;span class="c"&gt;# or frame-wise, --lang en&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tool: &lt;a href="https://github.com/liesliy/rda" rel="noopener noreferrer"&gt;https://github.com/liesliy/rda&lt;/a&gt; · PyPI: &lt;code&gt;robot-data-audit&lt;/code&gt; · UI: &lt;code&gt;rda ui&lt;/code&gt; (EN/中文)&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Caveats: RDA flags statistical anomalies, not ground-truth errors. REVIEW means "look before you train," not "discard." All thresholds are open for debate — that's what the issue tracker is for.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>robotics</category>
      <category>opensource</category>
      <category>python</category>
    </item>
    <item>
      <title>I Open-Sourced a Data Quality Auditor for Robot Datasets — It Found 1,535 Action Spikes in the Official ALOHA Demo Set</title>
      <dc:creator>liesliy</dc:creator>
      <pubDate>Wed, 19 Aug 2026 02:55:47 +0000</pubDate>
      <link>https://dev.to/liesliy/i-open-sourced-a-data-quality-auditor-for-robot-datasets-it-found-1535-action-spikes-in-the-24bj</link>
      <guid>https://dev.to/liesliy/i-open-sourced-a-data-quality-auditor-for-robot-datasets-it-found-1535-action-spikes-in-the-24bj</guid>
      <description>&lt;p&gt;Everyone in embodied AI says "data is the new code." Nobody audits it like code.&lt;/p&gt;

&lt;p&gt;We run linters, static analyzers, and CI gates on our source code. Then we feed 50GB of teleoperation recordings into a policy network and hope for the best. So I built &lt;strong&gt;RDA (Robot Data Audit)&lt;/strong&gt; — an open-source CLI that treats robot datasets the way &lt;code&gt;ruff&lt;/code&gt; treats a Python repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install robot-data-audit
rda audit /path/to/lerobot/dataset

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works natively on LeRobot-format datasets (v2.1 + v3.0), checks every episode across two layers — integrity (NaN actions, timestamp reversals, missing frames) and behavior (action discontinuity, idle ratio, frozen segments) — and outputs a per-episode verdict: PASS / REVIEW / EXCLUDE.&lt;/p&gt;

&lt;h3&gt;
  
  
  The dogfooding surprise
&lt;/h3&gt;

&lt;p&gt;Before releasing it, I ran RDA against the datasets everyone treats as ground truth — starting with &lt;code&gt;aloha_sim_transfer_cube_human&lt;/code&gt;, the official ALOHA simulation demonstration set that ships with the LeRobot ecosystem.&lt;/p&gt;

&lt;p&gt;Result from the behavior layer, across 50 episodes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Action discontinuity spikes: 1,535 (~30 per episode)&lt;/li&gt;
&lt;li&gt;Median idle ratio: 0.71** — the arm is effectively stationary 71% of frames&lt;/li&gt;
&lt;li&gt;Median effective motion ratio: 0.29&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To be clear about what this does and doesn't mean: none of this is corruption. The integrity layer came back clean — no NaNs, no broken timestamps. The spikes are real discontinuities in the action space (large frame-to-frame joint jumps), and the high idle ratio likely reflects grasping/hover phases where the gripper holds still. Neither is necessarily a bug in the dataset.&lt;/p&gt;

&lt;p&gt;But that's exactly the point. If you're benchmarking a policy on this data, or worse, fine-tuning on it, these numbers are &lt;strong&gt;context you didn't have&lt;/strong&gt;. Is 30 spikes per episode normal for this task? Does 71% idle time skew your loss toward predicting "do nothing"? Nobody asks, because nobody measures.&lt;/p&gt;

&lt;h3&gt;
  
  
  The bug I found in my own tool (while writing this post)
&lt;/h3&gt;

&lt;p&gt;Honesty section, because dev.to deserves better than marketing:&lt;/p&gt;

&lt;p&gt;My first run reported all 50 episodes as PASS. Green across the board. Celebration ensued.&lt;/p&gt;

&lt;p&gt;Then I cross-checked the behavior layer output against the verdicts and realized they weren't connected — the metrics were computing 1,535 spikes, and the verdict aggregator was ignoring behavior signals entirely. The tool had the evidence and wasn't reading it. The loudest silence in software is a metric that's computed but never consumed.&lt;/p&gt;

&lt;p&gt;Fixed now: behavior signals feed the verdict through a dataset-utility layer, and metric-level findings carry human-readable reasons. The ALOHA run now correctly flags 49/50 episodes as REVIEW with the specific signals attached.&lt;/p&gt;

&lt;p&gt;If you're building anything with a "signal producer → decision aggregator" architecture, test the wiring, not just the signals. I wrote a negative-control test for it before I trusted my own tool again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why this matters more than it sounds
&lt;/h3&gt;

&lt;p&gt;Robot learning teams are drowning in data collection — teleop sessions, sim rollouts, fleet logs — with almost no tooling for "is this batch usable before I burn GPU hours on it." An episode with a frozen sensor or a corrupted timestamp doesn't fail loudly. It trains quietly.&lt;/p&gt;

&lt;p&gt;RDA's philosophy: audit before train. Cheap checks first (seconds per episode, pure numpy/pandas), verdicts you can gate in CI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rda audit ./my_dataset &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="nt"&gt;-o&lt;/span&gt; report.json
&lt;span class="c"&gt;# fail the pipeline if any episode comes back EXCLUDE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's also a built-in UI (&lt;code&gt;rda ui&lt;/code&gt;) for browsing verdicts without spelunking JSON — and as of v0.5.2 it's fully bilingual: one toggle switches the entire dashboard, backend recommendation copy included, between English and 中文.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxlav0kxbt13hu9yr024h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxlav0kxbt13hu9yr024h.png" alt=" " width="799" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What shipped since the first post
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;rda recommend&lt;/code&gt;&lt;/strong&gt; — model-aware optimization advice. Tell it whether you're training a frame-wise model (MLP/BC) or a temporal one (ACT/Diffusion Policy), and it gives different answers for the same data — including an explicit DO_NOT_PRUNE guard for temporal models when valid-window ratio collapses. Every suggestion carries its experimental evidence: pruning cost our seq=10 temporal baseline +296% MSE, while trimmed ALOHA/PushT improved frame-wise baselines by 11–35%.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy-first architecture&lt;/strong&gt; — metrics compute locally; only &amp;lt;1KB of aggregates reach the rules API. &lt;code&gt;rda audit&lt;/code&gt; stays 100% offline, always.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;LeRobot v2.1 support&lt;/strong&gt; — bridge-style layouts now load natively (first run on bridge data: median idle ratio 93.3%. Real robots spend a lot of time deciding.).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A bug class worth naming: silent PASS.&lt;/strong&gt; 1,690 zero-frame episodes in a popular dataset were passing because "no evidence of problems" was treated as "no problems." Now zero-frame episodes are explicit EXCLUDEs with a diagnosis.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5zin3ec01e19yyxto69v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5zin3ec01e19yyxto69v.png" alt=" " width="799" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What's next
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;More behavior metrics (jitter, cycle anomalies, calibration drift)&lt;/li&gt;
&lt;li&gt;Trend dashboards across successive audits (already in the UI's History page — feedback wanted)&lt;/li&gt;
&lt;li&gt;Export-to-clean: one-click filtered dataset copy from surviving episodes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is early and hungry for real-world datasets to chew on. If you have a LeRobot-format dataset (v2.1 or v3.0), run &lt;code&gt;rda audit&lt;/code&gt; on it and tell me what turns up — especially if it's boring. Boring results from real data are how a tool earns trust.&lt;/p&gt;

&lt;p&gt;Issues, PRs, and "your idle-ratio threshold is wrong, here's why" comments all welcome.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;(RDA is MIT-licensed. I also do paid data-quality deep dives and pipeline integration for teams that want the audit without the homework.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Tool: &lt;a href="https://github.com/liesliy/rda" rel="noopener noreferrer"&gt;https://github.com/liesliy/rda&lt;/a&gt; · PyPI: &lt;code&gt;robot-data-audit&lt;/code&gt; · UI: &lt;code&gt;rda ui&lt;/code&gt; (EN/中文)&lt;/p&gt;

</description>
      <category>robotics</category>
      <category>ai</category>
      <category>opensource</category>
      <category>python</category>
    </item>
    <item>
      <title>tlabel convert: One CLI to Bridge 9 Tactile Dataset Formats</title>
      <dc:creator>liesliy</dc:creator>
      <pubDate>Tue, 11 Aug 2026 04:08:43 +0000</pubDate>
      <link>https://dev.to/liesliy/tlabel-convert-one-cli-to-bridge-9-tactile-dataset-formats-400k</link>
      <guid>https://dev.to/liesliy/tlabel-convert-one-cli-to-bridge-9-tactile-dataset-formats-400k</guid>
      <description>&lt;p&gt;How a single command can unify GelSight, PaXini, Daimon, ToucHD, and 5 other tactile sensor formats into training-ready data.&lt;/p&gt;




&lt;p&gt;If you work in tactile robotics research, you've been here before:&lt;br&gt;
A collaborator sends you a dataset collected with a PaXini PXCap force array. Your pipeline expects GelSight .pkl files. Your colleague's LeRobot training code needs Zarr. Someone else is publishing results on a Daimon DM-TacClaw in .parquet format.&lt;/p&gt;

&lt;p&gt;Three sensors. Three formats. Three days of writing ad-hoc parsing scripts that you'll delete next week.&lt;/p&gt;

&lt;p&gt;Tactile sensing is having a moment — multiple billion-dollar funding rounds in embodied AI have poured attention (and capital) into the field in 2026. But while hardware is advancing fast, data interoperability is still a mess. Every sensor vendor ships data in a proprietary format, and there's no common lingua franca for tactile manipulation datasets.&lt;/p&gt;

&lt;p&gt;TLabel is an open-source project that tackles exactly this problem. And with the maturation of its CLI and adapter architecture through v0.18.x, the workflow for converting between tactile dataset formats has gotten dramatically simpler.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What TLabel Actually Does&lt;/strong&gt;&lt;br&gt;
Before diving into commands, let's set expectations. TLabel is a data pipeline standardization layer. It does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Interface with hardware or collect data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Run inference or train models&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Replace your training pipeline&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Define a 14-dimension semantic annotation schema (covering contact, force, slip, texture, deformation, and more)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Provide adapter implementations that translate sensor-specific formats into that schema&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Export annotated data into training-ready formats (LeRobot, FTP-1 Zarr, JSON, CSV)&lt;br&gt;
Think of it as the Unicode for tactile data — one standard schema, every sensor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Adapter Landscape&lt;/strong&gt;&lt;br&gt;
TLabel currently ships with 12 built-in adapters covering 9 dataset formats and 3 real-time sensor interfaces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dataset Adapters (Offline Data Loading)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — GelSight Mini / DIGIT, visuo-tactile, .pkl, L3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — PaXini PXCap, force array, .h5, L2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — Daimon DM-TacClaw, multimodal, .parquet, L3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — ToucHD, visuo-tactile, .hdf5, L3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — UniVTAC, visuo-tactile, .hdf5, L3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — VTouch, visuo-tactile, .h5, L3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — YCB-Slide, visuo-tactile, .npy, L3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — TacQuad (AnyTouch), multi-sensor, directory, L3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — TLabel native, meta format, .json, L1–L4&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Real-Time Sensor Adapters&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — PaXini GEN3, force array, SDK connection, L2&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — Daimon DM-Tac, visuo-tactile, USB / .avi, L3&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&amp;lt;&amp;gt; — PaXini PX6D, 6-axis force, placeholder, L2&lt;br&gt;
That covers the majority of tactile sensors used in manipulation research today.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Getting Started&lt;/strong&gt;&lt;br&gt;
Install is straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;tlabel

&lt;span class="c"&gt;# Or with sensor-specific extras:&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;tlabel[gelsight]     &lt;span class="c"&gt;# GelSight / DIGIT (.pkl)&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;tlabel[paxini]       &lt;span class="c"&gt;# PaXini PXCap (.h5)&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;tlabel[daimon]       &lt;span class="c"&gt;# Daimon DM-TacClaw (.parquet)&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;tlabel[ftp1]         &lt;span class="c"&gt;# FTP-1 export (zarr)&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;tlabel[all]          &lt;span class="c"&gt;# Everything&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Exploring Adapters from the CLI&lt;/strong&gt;&lt;br&gt;
Once installed, you can inspect what's available without writing any code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all registered adapters&lt;/span&gt;
tlabel list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prints all dataset and real-time adapters with their type, native format, and compliance level. It's the first command I run when working with a new dataset.&lt;/p&gt;

&lt;p&gt;For details on a specific adapter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tlabel info gelsight
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This shows the adapter's capability declaration — which of the 14 semantic dimensions it can annotate, its compliance level, and any format-specific notes. For example, GelSight outputs force_vector (L3) but not temperature (L4), while a simple resistive sensor might only declare L1 fields like contact and slip_event.&lt;br&gt;
This capability declaration system is one of TLabel's key design decisions. Rather than forcing every sensor to produce all 14 dimensions (which would mean fabricating data it can't actually measure), each adapter honestly declares what it can and cannot provide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validating Your Data&lt;/strong&gt;&lt;br&gt;
Before converting, it's worth checking that your data passes schema validation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tlabel validate data.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This runs a compliance check against the 14-dimension Schema V2 and reports any issues. Catching format problems early saves debugging time downstream.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Converting Between Formats&lt;/strong&gt;&lt;br&gt;
Here's where things get practical. TLabel provides two paths for format conversion: CLI for quick checks and the Python API for full control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Conversion via CLI&lt;/strong&gt;&lt;br&gt;
For simple cases — say you have a single GelSight .pkl file and want a JSON summary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tlabel &lt;span class="nb"&gt;export&lt;/span&gt; &lt;span class="nt"&gt;--input&lt;/span&gt; grasp_data.pkl &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="nt"&gt;--output&lt;/span&gt; annotations.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This reads the GelSight data through its adapter, applies the Schema V2 annotation, and writes a clean JSON file with all 14 semantic dimensions (at the appropriate compliance level for the sensor).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Full Conversion Pipeline via Python&lt;/strong&gt;&lt;br&gt;
For the heavy lifting — converting entire datasets into training-ready formats — the Python API gives you the most control:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tlabel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tlabel.converters&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tlabel_to_lerobot&lt;/span&gt;

&lt;span class="c1"&gt;# Load data from any supported sensor
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tlabel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;path/to/paxini_data.h5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Inspect what you got
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;span class="c1"&gt;# -&amp;gt; {'num_frames': 500, 'sensor': 'paxini', 'compliance_level': 'L2', ...}
&lt;/span&gt;
&lt;span class="c1"&gt;# Export to JSON/CSV for analysis
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Export to FTP-1 Zarr for foundation model training
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;export_ftp1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;output.zarr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Convert to LeRobot episode format
&lt;/span&gt;&lt;span class="nf"&gt;tlabel_to_lerobot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;annotations.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lerobot_episode/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's a concrete example that walks through a realistic workflow — loading PaXini force array data, validating annotations, and exporting to both LeRobot and FTP-1 formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tlabel&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tlabel.converters&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tlabel_to_lerobot&lt;/span&gt;

&lt;span class="c1"&gt;# Step 1: Load PaXini PXCap data
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tlabel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;experiment_01.h5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Step 2: Validate schema compliance
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_annotations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Reports any missing or malformed fields
&lt;/span&gt;
&lt;span class="c1"&gt;# Step 3: Auto-annotate events from signal patterns
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;annotate_events_auto&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Detects: contact_onset, contact_loss, slip events, force spikes
&lt;/span&gt;
&lt;span class="c1"&gt;# Step 4: Export
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;experiment_01.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;# Analysis
&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;export_ftp1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;experiment_01.zarr&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;# Foundation model training
&lt;/span&gt;&lt;span class="nf"&gt;tlabel_to_lerobot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;experiment_01.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;# LeRobot pipeline
&lt;/span&gt;                   &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lerobot_episode/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Batch Processing Multiple Files&lt;/strong&gt;&lt;br&gt;
When you're dealing with an entire experiment directory (which is the typical case — real manipulation datasets have hundreds of episodes), you can batch-load and convert:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;tlabel&lt;/span&gt;

&lt;span class="n"&gt;files&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;raw_data/*.h5&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;files&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tlabel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;validate_annotations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;annotated/&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sensor&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_frames&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;f.json&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Converted &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; -&amp;gt; &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sensor&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (L&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compliance_level&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Understanding the Architecture&lt;/strong&gt;&lt;br&gt;
The adapter system sits in a three-layer architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────┐
│ Layer 1: Schema                                 │
│ 14 semantic dimensions + Compliance Level L1-L4 │
├─────────────────────────────────────────────────┤
│ Layer 2: Adapters                               │
│ DataAdapterBase │ SensorAdapterBase             │
├─────────────────────────────────────────────────┤
│ Layer 3: Downstream                             │
│ Feature derivation · Export · Augmentation      │
│ FTP-1 · LeRobot · RLDS · ROS2                  │
└─────────────────────────────────────────────────┘

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Layer 1 is the schema itself — 14 semantic dimensions covering spatial perception (contact, centroid, region), mechanics (force magnitude, force vector, torque), dynamics (slip event, slip velocity, manipulation phase), surface properties (texture class), and meta-perceptions (deformation, temperature, confidence, compliance level).&lt;br&gt;
Layer 2 is where adapters live. There are two base classes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;DataAdapterBase — for offline dataset files (sublcass this to add support for a new sensor format, takes ~30 minutes)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SensorAdapterBase — for real-time hardware connections (streaming data from a live sensor)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both produce output conforming to the same Schema V2, which means Layer 3 downstream tools work identically regardless of which sensor the data came from.&lt;/p&gt;

&lt;p&gt;Layer 3 handles everything after annotation: feature derivation, data augmentation, and export into training frameworks. This is where the LeRobot converter, FTP-1 Zarr exporter, and RLDS bridge live.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Compliance Level System&lt;/strong&gt;&lt;br&gt;
One concept worth explaining in more detail: Compliance Levels (L1–L4). This is TLabel's answer to the question "what if my sensor can't measure temperature or 6-axis force?"&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;L1 — Basic Tactile: contact, centroid, slip, confidence. Examples: Single-point resistive, proximity sensors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;L2 — Force-Aware: L1 + force_magnitude. Examples: PaXini, YCB-Slide, GelSight&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;L3 — Full-Vector: L2 + force_vector. Examples: ToucHD, calibrated DM-TAC&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;L4 — Rich-Semantic: L3 + all optional fields. Examples: BioTac, next-gen multimodal sensors&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key insight: a PaXini at L2 and a ToucHD at L3 both produce valid TLabel output. They just populate different subsets of the 14 dimensions. Downstream code can check compliance_level to decide what it can and cannot use, rather than writing sensor-specific branches.&lt;br&gt;
This is what makes cross-sensor comparison possible. You can train a model on GelSight data (L3) and evaluate it on PaXini data (L2), knowing exactly which fields are comparable and which aren't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What About My Sensor?&lt;/strong&gt;&lt;br&gt;
TLabel is designed for extensibility. If your sensor isn't supported yet, adding an adapter takes about 30 minutes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Fork the adapter template from contrib/adapter-template/&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Subclass DataAdapterBase (for datasets) or SensorAdapterBase (for hardware)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implement the required methods and declare your compliance level&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Submit a PR or publish as a standalone package&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project also supports register_external_adapter() and entry_points auto-discovery, so third-party adapters can be published independently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How This Fits Into the Embodied AI Pipeline&lt;/strong&gt;&lt;br&gt;
The broader context matters. Foundation models for robotics — like those being built on top of LeRobot, Open X-Embodiment, and similar frameworks — need diverse, standardized training data. But tactile data has been a bottleneck:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Collection is sensor-specific (hardware-dependent)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Annotation has been ad-hoc (no standard schema)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Training expects uniform input formats&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TLabel deliberately addresses step 2 and 3 only. It's a standardization layer that sits between your raw sensor data and your training pipeline. By providing a common schema with honest capability declarations, it enables:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cross-sensor training: Mix data from different sensors in the same training batch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Capability-aware models: Train models that know what information is available at each compliance level&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reproducible research: Compare results across labs using different hardware&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is also actively contributing tactile data format support upstream to LeRobot via PR #4032, which signals growing recognition that tactile data standards are needed in the broader robotics ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Reference&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;See all supported adapters → tlabel list&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Get adapter details → tlabel info gelsight&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate a data file → tlabel validate data.json&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Export to JSON → data.export("out.json")&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Export to FTP-1 Zarr → data.export_ftp1("out.zarr")&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Convert to LeRobot format → tlabel_to_lerobot(src, dst)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load any sensor data → tlabel.load("file")&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Try a demo (no files needed) → tlabel.demo("gelsight")&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Wrapping Up&lt;/strong&gt;&lt;br&gt;
Tactile data interoperability isn't glamorous work — it's infrastructure. But it's the kind of infrastructure that determines whether the field can scale beyond lab-specific pipelines to shared, reproducible, cross-sensor research.&lt;br&gt;
TLabel's adapter architecture and CLI tools won't solve every data problem in tactile robotics. But they provide a concrete, working answer to the question: "How do I get data from sensor X into format Y without writing a custom parser?"&lt;br&gt;
That question used to take a weekend. Now it takes one line.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Links:&lt;/strong&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/liesliy/tlabel" rel="noopener noreferrer"&gt;https://github.com/liesliy/tlabel&lt;/a&gt;&lt;br&gt;
PyPI: &lt;a href="https://pypi.org/project/tlabel/" rel="noopener noreferrer"&gt;https://pypi.org/project/tlabel/&lt;/a&gt;&lt;br&gt;
TLabel Paper: PDF on GitHub&lt;br&gt;
Schema V2 Spec: docs/tlabel-format.md&lt;br&gt;
Adapter Template: contrib/adapter-template&lt;br&gt;
Contributing Guide: CONTRIBUTING.md&lt;br&gt;
LeRobot PR #4032: huggingface/lerobot#4032&lt;br&gt;
Previous Dev.to post: TLabel: Unifying Tactile Data Annotation for Robotics&lt;br&gt;
Open X-Embodiment: robotics-transformer-x.github.io&lt;br&gt;
OpenTouch: opentouch.ai&lt;/p&gt;

&lt;p&gt;TL;DR — TLabel is the Unicode for tactile data: one standard schema, every sensor. Install with pip install tlabel, run tlabel list to see what's supported.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>robotics</category>
      <category>data</category>
    </item>
    <item>
      <title>How to Convert Multi-Sensor Tactile Data to LeRobot Format in One Command</title>
      <dc:creator>liesliy</dc:creator>
      <pubDate>Thu, 06 Aug 2026 09:27:10 +0000</pubDate>
      <link>https://dev.to/liesliy/how-to-convert-multi-sensor-tactile-data-to-lerobot-format-in-one-command-3okm</link>
      <guid>https://dev.to/liesliy/how-to-convert-multi-sensor-tactile-data-to-lerobot-format-in-one-command-3okm</guid>
      <description>&lt;p&gt;Stop writing custom data parsing scripts for every new tactile sensor. Here's a CLI tool that handles 9 sensor types and outputs training-ready LeRobot datasets.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;br&gt;
If you're working on robot manipulation with tactile sensing, you've hit this wall:&lt;/p&gt;

&lt;p&gt;Every tactile sensor outputs data in a different format. GelSight gives you .pkl files. PaXini uses .h5. Daimon uses .parquet. ToucHD dumps raw .npy arrays. And your robot learning framework — whether it's LeRobot, FTP-1, or something else — expects one specific format.&lt;br&gt;
So you end up writing a custom parser for each sensor. Every time you add a new sensor to your setup, you spend a day (or two) wrestling with data format conversions instead of doing actual research.&lt;br&gt;
I was in the same situation. That's why I built TLabel Convert.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What TLabel Convert Does&lt;/strong&gt;&lt;br&gt;
TLabel Convert is a CLI tool that converts raw data from 9 different tactile sensors into standardized training formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Convert a single file&lt;/span&gt;
tlabel convert &lt;span class="nt"&gt;--from&lt;/span&gt; gelsight &lt;span class="nt"&gt;--to&lt;/span&gt; lerobot &lt;span class="nt"&gt;--input&lt;/span&gt; data.pkl &lt;span class="nt"&gt;--output&lt;/span&gt; output_dir/

&lt;span class="c"&gt;# Convert an entire directory&lt;/span&gt;
tlabel batch-convert &lt;span class="nt"&gt;--from&lt;/span&gt; univtac &lt;span class="nt"&gt;--to&lt;/span&gt; ftp1 &lt;span class="nt"&gt;--input-dir&lt;/span&gt; ./raw/ &lt;span class="nt"&gt;--output-dir&lt;/span&gt; ./converted/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. Two commands. No custom parsing code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Supported Sensors&lt;/strong&gt;&lt;br&gt;
Here's what you can convert from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;GelSight Mini / DIGIT — Vision-based tactile, .pkl input → Contact, force, optical flow, 23 dimensions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;PaXini PXCap — High-res tactile array, .h5 input → Force, deformation, temporal features, 20 dimensions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Daimon DM-TacClaw — Multi-finger, .parquet input → LeRobot-compatible, force + contact&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ToucHD / AnyTouch 2 — Multi-modal, .npy + directory → Force + tactile + temporal, 22 dimensions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UniVTAC — Cross-dataset, .hdf5 input → Universal cross-dataset format&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;VTouch — Vision-based, .h5 input → Visual tactile features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;YCB-Slide (CMU DIGIT) — Sliding manipulation, .npy + directory → Sliding-specific features&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TacQuad (AnyTouch) — Multi-sensor array, .csv + directory → Multi-array data&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TLabel Format — Universal, .json input → Any data already in TLabel schema&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Supported Output Formats&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Two training-ready formats:&lt;br&gt;
LeRobot Format (HuggingFace)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tlabel convert &lt;span class="nt"&gt;--from&lt;/span&gt; gelsight &lt;span class="nt"&gt;--to&lt;/span&gt; lerobot &lt;span class="nt"&gt;--input&lt;/span&gt; data.pkl &lt;span class="nt"&gt;--output&lt;/span&gt; lerobot_dataset/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lerobot_dataset/
├── data/
│   └── chunk-0000.parquet    # Standard LeRobot parquet
└── meta/
    └── info.json              # With observation.tactile schema
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is directly compatible with LeRobotDataset:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;lerobot.common.datasets.lerobot_dataset&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LeRobotDataset&lt;/span&gt;
&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LeRobotDataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;lerobot_dataset&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Episodes: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_episodes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Tactile dims: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;features&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;observation.tactile&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 14-dim Schema V2
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;FTP-1/MTTS Format (Zarr)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tlabel convert &lt;span class="nt"&gt;--from&lt;/span&gt; paxini &lt;span class="nt"&gt;--to&lt;/span&gt; ftp1 &lt;span class="nt"&gt;--input&lt;/span&gt; data.h5 &lt;span class="nt"&gt;--output&lt;/span&gt; ftp1_dataset/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For tactile foundation model pretraining.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real Example: GelSight → LeRobot&lt;/strong&gt;&lt;br&gt;
Let me walk through a complete example. Say you have GelSight Mini data and want to use it with LeRobot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Step 1: Install&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;tlabel&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;0.19.0

&lt;span class="c"&gt;# Step 2: Convert&lt;/span&gt;
tlabel convert &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--from&lt;/span&gt; gelsight &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--to&lt;/span&gt; lerobot &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; gelsight_recording.pkl &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--output&lt;/span&gt; my_lerobot_dataset/

&lt;span class="c"&gt;# Step 3: Verify&lt;/span&gt;
tlabel adapter-info gelsight
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The converter handles:&lt;br&gt;
1.Frame extraction from the .pkl format&lt;br&gt;
2.Tactile feature mapping (23 dimensions → 14-dim TLabel Schema V2)&lt;br&gt;
3.Proper LeRobot parquet schema&lt;br&gt;
4.Metadata generation (info.json with observation.tactile field)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What About My Sensor?&lt;/strong&gt;&lt;br&gt;
If your sensor isn't in the list, you can check what's available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all supported adapters&lt;/span&gt;
tlabel list-adapters

&lt;span class="c"&gt;# Get detailed info about a specific adapter&lt;/span&gt;
tlabel adapter-info paxini

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The adapter architecture is extensible — if you're a sensor manufacturer or researcher, you can implement a new DataAdapter by subclassing DataAdapterBase. Check the contributing guide for details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Bigger Picture: TLabel Schema&lt;/strong&gt;&lt;br&gt;
TLabel Convert is part of the TLabel project, which defines a unified tactile data annotation standard.&lt;br&gt;
The schema covers 14 semantic dimensions:&lt;br&gt;
1.Contact state &amp;amp; area&lt;br&gt;
2.Force magnitude &amp;amp; direction&lt;br&gt;
3.Slip events &amp;amp; entropy&lt;br&gt;
4.Deformation magnitude &amp;amp; rate&lt;br&gt;
5.Optical flow direction &amp;amp; magnitude&lt;br&gt;
6.Texture energy&lt;br&gt;
7.And more...&lt;/p&gt;

&lt;p&gt;Each dimension has a compliance level (L1-L4) indicating how much information is available. This means you can have consistent annotations across different sensors, even if they don't all measure the same things.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Reference&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;tlabel&amp;gt;&lt;span class="o"&gt;=&lt;/span&gt;0.19.0

&lt;span class="c"&gt;# Convert single file&lt;/span&gt;
tlabel convert &lt;span class="nt"&gt;--from&lt;/span&gt; &amp;lt;adapter&amp;gt; &lt;span class="nt"&gt;--to&lt;/span&gt; &amp;lt;format&amp;gt; &lt;span class="nt"&gt;--input&lt;/span&gt; &amp;lt;path&amp;gt; &lt;span class="nt"&gt;--output&lt;/span&gt; &amp;lt;path&amp;gt;

&lt;span class="c"&gt;# Batch convert directory&lt;/span&gt;
tlabel batch-convert &lt;span class="nt"&gt;--from&lt;/span&gt; &amp;lt;adapter&amp;gt; &lt;span class="nt"&gt;--to&lt;/span&gt; &amp;lt;format&amp;gt; &lt;span class="nt"&gt;--input-dir&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;--output-dir&lt;/span&gt; &amp;lt;&lt;span class="nb"&gt;dir&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;# List supported adapters&lt;/span&gt;
tlabel list-adapters

&lt;span class="c"&gt;# Adapter details&lt;/span&gt;
tlabel adapter-info &amp;lt;name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adapters (--from): gelsight, paxini, daimon, tlabel, touchd, univtac, vtouch, ycb_slide, tacquad&lt;br&gt;
Formats (--to): lerobot, ftp1&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Links&lt;/strong&gt;&lt;br&gt;
GitHub: &lt;a href="https://github.com/liesliy/tlabel" rel="noopener noreferrer"&gt;https://github.com/liesliy/tlabel&lt;/a&gt;&lt;br&gt;
PyPI: &lt;a href="https://pypi.org/project/tlabel/" rel="noopener noreferrer"&gt;https://pypi.org/project/tlabel/&lt;/a&gt;&lt;br&gt;
HuggingFace Dataset: &lt;a href="https://huggingface.co/datasets/375720783jin/tlabel-convert" rel="noopener noreferrer"&gt;https://huggingface.co/datasets/375720783jin/tlabel-convert&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you're working with tactile data and struggling with format conversions, give it a try. Issues and PRs welcome.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
      <category>robotics</category>
    </item>
    <item>
      <title>Your AI Agent Can See, Hear, and Talk. But Can It Feel?</title>
      <dc:creator>liesliy</dc:creator>
      <pubDate>Wed, 05 Aug 2026 02:39:23 +0000</pubDate>
      <link>https://dev.to/liesliy/your-ai-agent-can-see-hear-and-talk-but-can-it-feel-3pjk</link>
      <guid>https://dev.to/liesliy/your-ai-agent-can-see-hear-and-talk-but-can-it-feel-3pjk</guid>
      <description>&lt;p&gt;Three years ago, I couldn't have imagined building software for something you can't see, hear, or photograph.&lt;/p&gt;

&lt;p&gt;Today, I spend my days thinking about how robots feel — and more specifically, how we make sense of the data their skin produces.&lt;/p&gt;

&lt;p&gt;If you've been following the AI agent space lately (and honestly, who hasn't), you've probably noticed a pattern: everyone's building agents that can see (vision), hear (audio), and talk (LLM outputs). But almost nobody's asking: &lt;strong&gt;what about touch?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The "Babel Problem" Nobody Talks About&lt;br&gt;
Here's what I found when I started working on embodied AI data:&lt;br&gt;
Every robotics lab on the planet stores tactile data differently. Different column names. Different units. Different sampling rates. Different everything.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Lab A records force in Newtons, columns named fx, fy, fz&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lab B uses raw ADC counts, columns named ch_0, ch_1...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lab C has its own JSON schema with nested objects&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Robot D has a completely different coordinate system&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Try to train a model across these datasets. Try to benchmark. Try to share data with a collaborator at another university. Good luck.&lt;/p&gt;

&lt;p&gt;I call this the Babel Problem. Everyone's speaking their own language, and nobody can understand each other.&lt;br&gt;
"But We Have MCP Now, Right?"&lt;br&gt;
Great question. MCP standardized how LLMs call tools. A2A handles agent-to-agent communication. OpenTelemetry covers observability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;None of these touch tactile perception.&lt;/strong&gt;&lt;br&gt;
There is no standard for what a "tactile reading" actually means. Not its semantics. Not its structure. Not its units. Not how you describe contact geometry, pressure distribution, slip events, or texture features.&lt;/p&gt;

&lt;p&gt;Think of it this way: if someone published a recipe using inches, Fahrenheit, and a custom unit called "glugs," you couldn't reproduce it — no matter how brilliant the cooking was. That's where tactile data is right now.&lt;/p&gt;

&lt;p&gt;Why This Matters Now&lt;br&gt;
Embodied AI is having its moment. Foundation models are being trained on robot demonstrations. Dexterous manipulation is no longer sci-fi. But the data pipeline underneath all of this is held together with tape.&lt;/p&gt;

&lt;p&gt;Without a standard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Cross-dataset training is basically impossible (you spend more time normalizing than modeling)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hardware swaps break every downstream pipeline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reproducibility is a joke (good luck replicating someone's tactile benchmark)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data sharing between labs requires a custom converter... per dataset&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What We Built&lt;/strong&gt;&lt;br&gt;
After months of frustration, I started building TLabel — an open standard for tactile data.&lt;br&gt;
The core idea is simple: define a universal schema that describes what tactile data means, regardless of which sensor produced it.&lt;/p&gt;

&lt;p&gt;TLabel defines 14 semantic dimensions, including:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Contact Geometry — where and how the contact happens&lt;/li&gt;
&lt;li&gt;Normal / Shear Force — force direction and magnitude&lt;/li&gt;
&lt;li&gt;Pressure Distribution — spatial pressure map&lt;/li&gt;
&lt;li&gt;Texture — surface micro-features&lt;/li&gt;
&lt;li&gt;Temperature — thermal perception&lt;/li&gt;
&lt;li&gt;Slip — detection of movement at contact&lt;/li&gt;
&lt;li&gt;...and 8 more (full spec in the design doc)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each data file carries a Compliance Level (L1–L4), so consumers know exactly what's available — even if some sensors only provide basic readings.&lt;/p&gt;

&lt;p&gt;The key design principle: TLabel doesn't tell you how to process tactile data. It tells you how to describe it. The processing is up to you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Show Me The Code&lt;/strong&gt;&lt;br&gt;
Load a tactile file — same API regardless of which sensor produced it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;tlabel&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TLabelFile&lt;/span&gt;
&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;TLabelFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sample.tlabel&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access standardized dimensions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;forces&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_forces&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;             &lt;span class="c1"&gt;# Newtons, always
&lt;/span&gt;&lt;span class="n"&gt;contacts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_contact_geom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;     &lt;span class="c1"&gt;# Consistent coordinate frame
&lt;/span&gt;&lt;span class="n"&gt;textures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_texture_features&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check what's available and inspect sensor metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;compliance_level&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;# L1 = basic, L4 = full spec
&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sensor_info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;        &lt;span class="c1"&gt;# Original hardware metadata preserved
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No matter whether the original data came from a GelSight, a BioTac, a custom capacitive array, or a future sensor nobody's invented yet — the interface is the same.&lt;/p&gt;

&lt;p&gt;The Python package is at v0.18.2 on PyPI, and we're actively building exporter plugins for popular formats.&lt;/p&gt;

&lt;p&gt;The open-source embodied AI ecosystem is moving fast — LeRobot, Forge, various simulators and hardware platforms. But if these systems can't share and understand tactile data, we're building a tower with no common language.&lt;/p&gt;

&lt;p&gt;I don't think TLabel is the final answer. But the conversation needs to happen, and the standard needs to be open — not owned by one company or one lab.&lt;br&gt;
The project is here if you're curious: github.com/liesliy/tlabel&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>mcp</category>
      <category>robotics</category>
    </item>
    <item>
      <title>Hello, Dev.to — I'm Building a Data Format Nobody Asked For (But Everyone Needs)</title>
      <dc:creator>liesliy</dc:creator>
      <pubDate>Sat, 01 Aug 2026 03:04:41 +0000</pubDate>
      <link>https://dev.to/liesliy/hello-devto-im-building-a-data-format-nobody-asked-for-but-everyone-needs-4a5i</link>
      <guid>https://dev.to/liesliy/hello-devto-im-building-a-data-format-nobody-asked-for-but-everyone-needs-4a5i</guid>
      <description>&lt;p&gt;Hey 👋 I'm Liesliy, a developer working on tactile data infrastructure for robots.&lt;br&gt;
&lt;strong&gt;The Problem That Brought Me Here&lt;/strong&gt;&lt;br&gt;
If you work in robotics, you've probably noticed something: nobody can agree on how to label tactile data.&lt;br&gt;
Every lab has its own format. Every dataset ships in a different schema. When you try to combine data from two sources, you spend more time writing converters than doing actual research.&lt;br&gt;
I've been there. So I built TLabel — an open-source unified format standard for tactile annotation data.&lt;/p&gt;

&lt;p&gt;Think of it like this:&lt;br&gt;
ROS standardized how robots communicate&lt;br&gt;
ROS Bag standardized how robots record&lt;br&gt;
Nobody has standardized how we label tactile data&lt;/p&gt;

&lt;p&gt;That's the gap TLabel tries to fill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What It Actually Does&lt;/strong&gt;&lt;br&gt;
Unified schema with 14 semantic dimensions and 4 compliance levels (L1–L4)&lt;br&gt;
Adapters to convert between formats (GelSight, BioTac, digit, TacTip, and more)&lt;br&gt;
PyPI-installable, plug into your existing pipeline&lt;br&gt;
It's early — v0.17 just shipped — but the architecture is solid and I'm actively looking for real-world feedback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Dev.to&lt;/strong&gt;&lt;br&gt;
I've been reading Dev.to for a while. What I appreciate about this place:&lt;br&gt;
Engineers write for engineers — no fluff, no engagement farming&lt;br&gt;
"Hello World" culture actually works — people genuinely welcome newcomers&lt;br&gt;
The comment sections are better than most conferences&lt;br&gt;
I'm here to:&lt;br&gt;
Share what I learn building a data standard nobody asked for (yet)&lt;br&gt;
Meet people working on sensor data, robotics, and embodied AI&lt;br&gt;
Get honest feedback — the kind that hurts but makes the project better&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I'd Love to Hear From You&lt;/strong&gt;&lt;br&gt;
If you work with tactile sensing, robotics data pipelines, or open-source tooling — I want to talk.&lt;br&gt;
Especially curious:&lt;br&gt;
How do you handle format conversion in your current workflow?&lt;br&gt;
What's the most painful part of working with tactile datasets?&lt;/p&gt;

&lt;p&gt;Drop a comment or DM. I promise I'm more interested in listening than pitching. 🦞&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
