<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Digital-Twin on Mulham Fetna</title>
    <link>https://mulhamfetna.com/tags/digital-twin/</link>
    <description>Recent content in Digital-Twin on Mulham Fetna</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <managingEditor>contact@mulhamfetna.com (Mulham Fetna)</managingEditor>
    <webMaster>contact@mulhamfetna.com (Mulham Fetna)</webMaster>
    <copyright>© 2026 Mulham Fetna</copyright>
    <lastBuildDate>Wed, 16 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://mulhamfetna.com/tags/digital-twin/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>From tutorial project to production robot: a roadmap for the tendon hand twin</title>
      <link>https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/roadmap-to-production/</link>
      <pubDate>Wed, 16 Sep 2026 00:00:00 +0000</pubDate>
      <author>contact@mulhamfetna.com (Mulham Fetna)</author>
      <guid>https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/roadmap-to-production/</guid>
      <description>&lt;div class=&#34;lead text-neutral-500 dark:text-neutral-400 !mb-9 text-xl&#34;&gt;&#xA;  The system works, and it teaches well. Getting it to drive real servos safely is a sequence of&#xA;well-scoped upgrades — each one grounded in a limitation measured earlier in this series.&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;h2 class=&#34;relative group&#34;&gt;Where it stands&#xA;    &lt;div id=&#34;where-it-stands&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#where-it-stands&#34; aria-label=&#34;Anchor&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Area&lt;/th&gt;&#xA;          &lt;th&gt;Today&lt;/th&gt;&#xA;          &lt;th&gt;Production target&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Hand tracking&lt;/td&gt;&#xA;          &lt;td&gt;image-normalized landmarks, one global calibration&lt;/td&gt;&#xA;          &lt;td&gt;metric world landmarks, per-finger calibration, a temporal filter&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Command mapping&lt;/td&gt;&#xA;          &lt;td&gt;flexion → ±50 N; the twin is a switch&lt;/td&gt;&#xA;          &lt;td&gt;flexion → tendon length; proportional curl&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Physics model&lt;/td&gt;&#xA;          &lt;td&gt;force motors, decorative horns, no self-contact&lt;/td&gt;&#xA;          &lt;td&gt;position servos on horns, tuned stiffness, contacts for grasping&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Middleware&lt;/td&gt;&#xA;          &lt;td&gt;one topic, default QoS, open on the LAN&lt;/td&gt;&#xA;          &lt;td&gt;parameters, explicit QoS, a watchdog, SROS 2&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Containers&lt;/td&gt;&#xA;          &lt;td&gt;privileged, host namespaces, root, &lt;code&gt;xhost&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;least privilege, non-root, optional headless&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Code&lt;/td&gt;&#xA;          &lt;td&gt;classes copied into three files, no tests&lt;/td&gt;&#xA;          &lt;td&gt;one shared package, tests, CI&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Hardware&lt;/td&gt;&#xA;          &lt;td&gt;simulation only&lt;/td&gt;&#xA;          &lt;td&gt;a servo driver on the same topic&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;ol class=&#34;border-s-2 border-primary-500 dark:border-primary-300 list-none&#34;&gt;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&#xA;&lt;li&gt;&#xA;  &lt;div class=&#34;flex&#34;&gt;&#xA;    &lt;div&#xA;      class=&#34;bg-primary-500 dark:bg-primary-300 text-neutral-50 dark:text-neutral-700 min-w-[30px] h-8 text-2xl flex items-center justify-center rounded-full ltr:-ml-12 rtl:-mr-[79px] mt-5&#34;&gt;&#xA;      &lt;span class=&#34;relative block icon&#34;&gt;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; viewBox=&#34;0 0 448 512&#34;&gt;&lt;path fill=&#34;currentColor&#34; d=&#34;M438.6 105.4C451.1 117.9 451.1 138.1 438.6 150.6L182.6 406.6C170.1 419.1 149.9 419.1 137.4 406.6L9.372 278.6C-3.124 266.1-3.124 245.9 9.372 233.4C21.87 220.9 42.13 220.9 54.63 233.4L159.1 338.7L393.4 105.4C405.9 92.88 426.1 92.88 438.6 105.4H438.6z&#34;/&gt;&lt;/svg&gt;&#xA;&lt;/span&gt;&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;block p-6 rounded-lg shadow-2xl flex-1 ms-6 mb-10 break-words&#34;&gt;&#xA;      &lt;div class=&#34;flex justify-between&#34;&gt;&#xA;        &#xA;          &lt;h2 class=&#34;mt-0&#34;&gt;Stage 1 · Correctness&lt;/h2&gt;&#xA;        &#xA;        &#xA;      &lt;/div&gt;&#xA;      &#xA;        &lt;h4 class=&#34;mt-0&#34;&gt;&#xA;          Measure the right thing, command the right quantity&#xA;        &lt;/h4&gt;&#xA;      &#xA;      &lt;div class=&#34;mb-6&#34;&gt;&#xA;        &lt;p&gt;&lt;strong&gt;World landmarks.&lt;/strong&gt; Image-normalized coordinates bend angles by up to 16° with hand orientation&#xA;(&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/mediapipe-hands/&#34; &gt;Part 4&lt;/a&gt;).&#xA;Read &lt;code&gt;multi_hand_world_landmarks&lt;/code&gt; instead, then recalibrate.&lt;/p&gt;</description>
      <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/roadmap-to-production/cover.png" />
    </item>
    
    <item>
      <title>How a webcam moves a simulated tendon-driven hand</title>
      <link>https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/architecture/</link>
      <pubDate>Wed, 16 Sep 2026 00:00:00 +0000</pubDate>
      <author>contact@mulhamfetna.com (Mulham Fetna)</author>
      <guid>https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/architecture/</guid>
      <description>&lt;div class=&#34;lead text-neutral-500 dark:text-neutral-400 !mb-9 text-xl&#34;&gt;&#xA;  One vision container turns webcam frames into five numbers. One simulation container turns those&#xA;numbers into tendon forces. Everything else in this series is detail inside one of those two boxes&#xA;— or the pipe between them.&#xA;&lt;/div&gt;&#xA;&#xA;&lt;figure&gt;&lt;img&#xA;    class=&#34;my-0 rounded-md&#34;&#xA;    loading=&#34;lazy&#34;&#xA;    decoding=&#34;async&#34;&#xA;    fetchpriority=&#34;auto&#34;&#xA;    alt=&#34;Peace sign, live: camera with MediaPipe landmarks, the twin with ring and pinky curled, and the motor forces −21 N on ring and pinky&#34;&#xA;    width=&#34;1570&#34;&#xA;    height=&#34;480&#34;&#xA;    src=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/architecture/live_peace_sign_hu_10d6cdce7106932.jpg&#34;&#xA;    srcset=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/architecture/live_peace_sign_hu_10d6cdce7106932.jpg 800w, https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/architecture/live_peace_sign_hu_c82c14c5f3244f84.jpg 1280w&#34;&#xA;    sizes=&#34;(min-width: 768px) 50vw, 65vw&#34;&#xA;    data-zoom-src=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/architecture/live_peace_sign.jpg&#34;&gt;&lt;figcaption&gt;Left to right, three layers in one frame: vision (landmarks), simulation (the twin), actuation (live motor forces from MuJoCo&amp;rsquo;s Control panel).&lt;/figcaption&gt;&lt;/figure&gt;&#xA;&#xA;&lt;h2 class=&#34;relative group&#34;&gt;End to end&#xA;    &lt;div id=&#34;end-to-end&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#end-to-end&#34; aria-label=&#34;Anchor&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h2&gt;&#xA;&lt;pre class=&#34;not-prose mermaid&#34;&gt;&#xA;flowchart LR&#xA;    subgraph VISION[&#34;🐳 vision_tracker container&#34;]&#xA;        direction TB&#xA;        A[&#34;Webcam frame&lt;br&gt;640×480 BGR&#34;] --&gt; B[&#34;MediaPipe Hands&lt;br&gt;21 landmarks&#34;]&#xA;        B --&gt; C[&#34;3 knuckle angles / finger&lt;br&gt;dot product&#34;]&#xA;        C --&gt; D[&#34;mean → 1 curl angle&lt;br&gt;(underactuation)&#34;]&#xA;        D --&gt; E[&#34;normalize + clip&lt;br&gt;flexion 0..1&#34;]&#xA;    end&#xA;    subgraph TWIN[&#34;🐳 mujoco_twin container&#34;]&#xA;        direction TB&#xA;        F[&#34;lerp&lt;br&gt;+50 N … −50 N&#34;] --&gt; G[&#34;data.ctrl on&lt;br&gt;pull_{finger} motor&#34;]&#xA;        G --&gt; H[&#34;spatial tendon&lt;br&gt;through 6 sites&#34;]&#xA;        H --&gt; I[&#34;3 passive hinge joints&lt;br&gt;curl&#34;]&#xA;        I --&gt; J[&#34;MuJoCo viewer&#34;]&#xA;    end&#xA;    E -- &#34;ROS 2 · /hand/target_flexions&lt;br&gt;sensor_msgs/JointState&#34; --&gt; F&#xA;&lt;/pre&gt;&#xA;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Stage&lt;/th&gt;&#xA;          &lt;th&gt;What comes out&lt;/th&gt;&#xA;          &lt;th&gt;Deep dive&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;MediaPipe Hands&lt;/td&gt;&#xA;          &lt;td&gt;21 (x, y, z) landmarks per frame&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/mediapipe-hands/&#34; &gt;Part 4&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Triplet angles&lt;/td&gt;&#xA;          &lt;td&gt;3 interior angles per finger, in radians&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/joint-angles-dot-product/&#34; &gt;Part 5&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Averaging&lt;/td&gt;&#xA;          &lt;td&gt;1 curl angle per finger&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/underactuation-averaging/&#34; &gt;Part 6&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Normalization&lt;/td&gt;&#xA;          &lt;td&gt;flexion 0..1 (the thumb has its own window)&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/flexion-normalization/&#34; &gt;Parts 7&lt;/a&gt;–&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/thumb-thresholds/&#34; &gt;8&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;ROS 2 topic&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;JointState&lt;/code&gt;: names are fingers, positions are flexions&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/ros2-topic-contract/&#34; &gt;Part 15&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Lerp&lt;/td&gt;&#xA;          &lt;td&gt;force in newtons per tendon&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/flexion-to-force/&#34; &gt;Part 10&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Tendon physics&lt;/td&gt;&#xA;          &lt;td&gt;joint angles&lt;/td&gt;&#xA;          &lt;td&gt;&lt;a href=&#34;https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/tendon-physics-switch/&#34; &gt;Part 11&lt;/a&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h2 class=&#34;relative group&#34;&gt;Why the pipe carries flexions, not angles or forces&#xA;    &lt;div id=&#34;why-the-pipe-carries-flexions-not-angles-or-forces&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#why-the-pipe-carries-flexions-not-angles-or-forces&#34; aria-label=&#34;Anchor&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The contract between the containers is five unitless numbers: 0.0 is an open finger, 1.0 is a closed&#xA;one. That choice is the architecture.&lt;/p&gt;</description>
      <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/architecture/cover.png" />
    </item>
    
    <item>
      <title>Why the simulated tendon finger is a switch — and three fixes tested in MuJoCo</title>
      <link>https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/tendon-physics-switch/</link>
      <pubDate>Wed, 16 Sep 2026 00:00:00 +0000</pubDate>
      <author>contact@mulhamfetna.com (Mulham Fetna)</author>
      <guid>https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/tendon-physics-switch/</guid>
      <description>&lt;div class=&#34;lead text-neutral-500 dark:text-neutral-400 !mb-9 text-xl&#34;&gt;&#xA;  The vision layer sends a carefully normalized, smooth 0-to-1 signal. The simulated finger turns it&#xA;into two states: open and closed. This is the most important thing to understand about the twin —&#xA;and every number below was measured on the model in the repository.&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;h2 class=&#34;relative group&#34;&gt;The measurement&#xA;    &lt;div id=&#34;the-measurement&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#the-measurement&#34; aria-label=&#34;Anchor&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h2&gt;&#xA;&lt;p&gt;The same flexion was applied to all five motors, the model simulated for 3 s from rest, and the&#xA;steady-state joint angles recorded — 41 flexion values from 0 to 1.&lt;/p&gt;&#xA;&#xA;&lt;div class=&#34;chart&#34;&gt;&#xA;  &lt;canvas id=&#34;chart-21ff2680002d0af6f1365e2e937bcf1a&#34;&gt;&lt;/canvas&gt;&#xA;  &lt;script type=&#34;text/javascript&#34;&gt;&#xA;    window.addEventListener(&#34;DOMContentLoaded&#34;, (event) =&gt; {&#xA;      const ctx = document.getElementById(&#34;chart-21ff2680002d0af6f1365e2e937bcf1a&#34;);&#xA;      const chart = new Chart(ctx, {&#xA;        &#xA;type: &#39;line&#39;,&#xA;data: {&#xA;  labels: [&#39;0.000&#39;,&#39;0.025&#39;,&#39;0.050&#39;,&#39;0.075&#39;,&#39;0.100&#39;,&#39;0.125&#39;,&#39;0.150&#39;,&#39;0.175&#39;,&#39;0.200&#39;,&#39;0.225&#39;,&#39;0.250&#39;,&#39;0.275&#39;,&#39;0.300&#39;,&#39;0.325&#39;,&#39;0.350&#39;,&#39;0.375&#39;,&#39;0.400&#39;,&#39;0.425&#39;,&#39;0.450&#39;,&#39;0.475&#39;,&#39;0.500&#39;,&#39;0.525&#39;,&#39;0.550&#39;,&#39;0.575&#39;,&#39;0.600&#39;,&#39;0.625&#39;,&#39;0.650&#39;,&#39;0.675&#39;,&#39;0.700&#39;,&#39;0.725&#39;,&#39;0.750&#39;,&#39;0.775&#39;,&#39;0.800&#39;,&#39;0.825&#39;,&#39;0.850&#39;,&#39;0.875&#39;,&#39;0.900&#39;,&#39;0.925&#39;,&#39;0.950&#39;,&#39;0.975&#39;,&#39;1.000&#39;],&#xA;  datasets: [&#xA;    { label: &#39;Index finger (mean of MCP, PIP, DIP)&#39;, data: [-3.3,-3.1,-2.9,-2.8,-2.6,-2.5,-2.3,-2.1,-2.0,-1.8,-1.7,-1.5,-1.3,-1.2,-1.0,-0.8,-0.7,-0.5,-0.3,-0.2,0.0,90.2,90.4,90.6,90.8,91.0,91.2,91.5,91.7,91.9,92.1,92.2,92.4,92.6,92.8,93.0,93.2,93.4,93.5,93.7,93.9], borderColor: &#39;#2a78d6&#39;, backgroundColor: &#39;#2a78d6&#39;, borderWidth: 2, pointRadius: 1.5, tension: 0 },&#xA;    { label: &#39;Thumb CMC&#39;, data: [-2.9,-2.8,-2.6,-2.5,-2.4,-2.2,-2.1,-1.9,-1.8,-1.6,-1.5,-1.4,-1.2,-1.1,-0.9,-0.8,-0.6,-0.5,-0.3,-0.1,0.0,90.1,90.2,90.4,90.5,90.6,90.7,90.8,91.0,91.1,91.2,91.3,91.4,91.5,91.6,91.7,91.8,92.0,92.1,92.2,92.3], borderColor: &#39;#1baf7a&#39;, backgroundColor: &#39;#1baf7a&#39;, borderWidth: 2, pointRadius: 1.5, tension: 0 },&#xA;    { label: &#39;Thumb IP&#39;, data: [-2.7,-2.6,-2.5,-2.3,-2.2,-2.0,-1.9,-1.8,-1.6,-1.5,-1.4,-1.2,-1.1,-0.9,-0.8,-0.7,-0.5,-0.4,-0.3,-0.1,0.0,41.2,44.3,45.1,45.5,45.6,45.7,45.8,45.8,45.9,45.9,45.9,45.9,45.9,45.9,46.0,46.0,46.0,46.0,46.0,46.0], borderColor: &#39;#eb6834&#39;, backgroundColor: &#39;#eb6834&#39;, borderWidth: 2, pointRadius: 1.5, tension: 0 }&#xA;  ]&#xA;},&#xA;options: {&#xA;  plugins: { title: { display: true, text: &#39;Simulated joint bend vs flexion — flat, then a wall at 0.5&#39; } },&#xA;  scales: { x: { title: { display: true, text: &#39;flexion command (0.5 = 0 N)&#39; } }, y: { min: -10, max: 100, title: { display: true, text: &#39;joint bend (°)&#39; } } }&#xA;}&#xA;&#xA;      });&#xA;    });&#xA;  &lt;/script&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Flexion&lt;/th&gt;&#xA;          &lt;th&gt;Force&lt;/th&gt;&#xA;          &lt;th&gt;Index MCP / PIP / DIP&lt;/th&gt;&#xA;          &lt;th&gt;Thumb CMC / MP / IP&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;0.000&lt;/td&gt;&#xA;          &lt;td&gt;+50.0 N&lt;/td&gt;&#xA;          &lt;td&gt;−3.3° / −3.2° / −3.3°&lt;/td&gt;&#xA;          &lt;td&gt;−2.9° / −2.7° / −2.7°&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;0.250&lt;/td&gt;&#xA;          &lt;td&gt;+25.0 N&lt;/td&gt;&#xA;          &lt;td&gt;−1.7° / −1.6° / −1.7°&lt;/td&gt;&#xA;          &lt;td&gt;−1.5° / −1.3° / −1.4°&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;0.500&lt;/td&gt;&#xA;          &lt;td&gt;0.0 N&lt;/td&gt;&#xA;          &lt;td&gt;0.0° / 0.0° / 0.0°&lt;/td&gt;&#xA;          &lt;td&gt;0.0° / 0.0° / 0.0°&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;0.625&lt;/td&gt;&#xA;          &lt;td&gt;−12.5 N&lt;/td&gt;&#xA;          &lt;td&gt;91.1° / 91.0° / 91.0°&lt;/td&gt;&#xA;          &lt;td&gt;90.6° / 53.9° / 45.6°&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;1.000&lt;/td&gt;&#xA;          &lt;td&gt;−50.0 N&lt;/td&gt;&#xA;          &lt;td&gt;94.0° / 93.8° / 93.9°&lt;/td&gt;&#xA;          &lt;td&gt;92.3° / 54.2° / 46.0°&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;&lt;em&gt;Joint limits are 90°; values just above it are MuJoCo&amp;rsquo;s soft limit being pressed.&lt;/em&gt;&lt;/p&gt;</description>
      <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://mulhamfetna.com/projects/ros2-tendon-driven-hand-mujoco-digital-twin-vision-teleoperation/tendon-physics-switch/cover.png" />
    </item>
    
    <item>
      <title>A webcam, some vector geometry, and a hand that moves</title>
      <link>https://mulhamfetna.com/projects/ros2-mediapipe-robotic-hand-digital-twin-vision-teleoperation/overview/</link>
      <pubDate>Tue, 08 Sep 2026 00:00:00 +0000</pubDate>
      <author>contact@mulhamfetna.com (Mulham Fetna)</author>
      <guid>https://mulhamfetna.com/projects/ros2-mediapipe-robotic-hand-digital-twin-vision-teleoperation/overview/</guid>
      <description>&lt;div class=&#34;lead text-neutral-500 dark:text-neutral-400 !mb-9 text-xl&#34;&gt;&#xA;  Everything in this series in one read: how a $20 webcam ends up driving a 15-DOF CAD model in&#xA;real time, why every step is deliberately explicit rather than learned, and what broke along the&#xA;way.&#xA;&lt;/div&gt;&#xA;&#xA;&lt;p&gt;You hold your hand up to a laptop camera. On the other half of the screen, a robotic hand —&#xA;designed in CAD, never manufactured — closes its fingers at the same moment yours do.&lt;/p&gt;&#xA;&lt;p&gt;There is no glove, no marker, no depth sensor. Just an RGB webcam, two small neural networks,&#xA;about forty lines of vector geometry, and a middleware stack that thinks it is talking to a real&#xA;robot.&lt;/p&gt;&#xA;&lt;p&gt;All of it is open source under AGPL-3.0 and archived with a DOI:&#xA;&lt;a href=&#34;https://doi.org/10.5281/zenodo.22658556&#34;  target=&#34;_blank&#34; rel=&#34;noreferrer&#34;&gt;10.5281/zenodo.22658556&lt;/a&gt;.&lt;/p&gt;&#xA;&lt;pre class=&#34;not-prose mermaid&#34;&gt;&#xA;flowchart LR&#xA;    A[&#34;📷 Webcam&lt;br&gt;/dev/video0&#34;] --&gt; B[&#34;BlazePalm&lt;br&gt;palm detector&#34;]&#xA;    B --&gt; C[&#34;Landmark regressor&lt;br&gt;21 × (x, y, z)&#34;]&#xA;    C --&gt; D[&#34;Dot-product geometry&lt;br&gt;15 interior angles&#34;]&#xA;    D --&gt; E[&#34;Normalize → flexion&lt;br&gt;0.0 straight · 1.0 curled&#34;]&#xA;    E --&gt; F[&#34;Lerp onto the URDF&#39;s&lt;br&gt;mechanical limits&#34;]&#xA;    F --&gt; G[&#34;/joint_states&#34;]&#xA;    G --&gt; H[&#34;robot_state_publisher&lt;br&gt;→ /tf&#34;]&#xA;    H --&gt; I[&#34;🖥️ RViz digital twin&#34;]&#xA;&lt;/pre&gt;&#xA;&#xA;&#xA;&lt;h2 class=&#34;relative group&#34;&gt;The rule that shaped the build&#xA;    &lt;div id=&#34;the-rule-that-shaped-the-build&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#the-rule-that-shaped-the-build&#34; aria-label=&#34;Anchor&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h2&gt;&#xA;&lt;p&gt;There is an easier version of this project. Collect a few thousand frames of a hand next to the&#xA;corresponding CAD poses, train a network to map one to the other, and let gradient descent work out&#xA;the relationship.&lt;/p&gt;</description>
      <media:content xmlns:media="http://search.yahoo.com/mrss/" url="https://mulhamfetna.com/projects/ros2-mediapipe-robotic-hand-digital-twin-vision-teleoperation/overview/featured.png" />
    </item>
    
  </channel>
</rss>
