<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Case Study on Mahdi Sarfarazi</title>
    <link>https://mahdisf.ir/categories/case-study/</link>
    <description>Recent content in Case Study on Mahdi Sarfarazi</description>
    <image>
      <title>Mahdi Sarfarazi</title>
      <url>https://mahdisf.ir/images/social-card.png</url>
      <link>https://mahdisf.ir/images/social-card.png</link>
    </image>
    <generator>Hugo</generator>
    <language>en-US</language>
    <lastBuildDate>Thu, 24 Sep 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://mahdisf.ir/categories/case-study/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Taking an AI control-design platform from concept to a validated MVP</title>
      <link>https://mahdisf.ir/projects/ai-control-design-platform/</link>
      <pubDate>Thu, 24 Sep 2026 00:00:00 +0000</pubDate>
      <guid>https://mahdisf.ir/projects/ai-control-design-platform/</guid>
      <description>Product case study: as Technical Product Manager at an agentic-AI startup, I took an AI-assisted control-design platform from concept to an MVP that passed two proof-of-concept cycles and an internal readiness gate.</description>
      <content:encoded><![CDATA[<div class="case-summary">
<p>I took an AI-assisted control-design platform from concept to an MVP. It has completed two proof-of-concept cycles and passed the company&rsquo;s internal product-readiness gate.</p>
<p>The product has not launched commercially. A formal B2B product-market-fit programme comes next, so this page makes no claims about paying customers, revenue or product-market fit. The company is an early-stage agentic-AI startup, and its name, customers and internal targets are confidential.</p>
</div>
<dl class="snapshot">
  <div><dt>My role</dt><dd>Technical Product Manager (Mar 2026 to present). Before that, Robotics Software Engineer on the same product (Nov 2025 to Mar 2026).</dd></div>
  <div><dt>Team</dt><dd>Seven engineers and three stakeholders across AI, control engineering, software, product design and QA</dd></div>
  <div><dt>Stage</dt><dd>MVP, two POC cycles complete, readiness gate approved</dd></div>
  <div><dt>Ways of working</dt><dd>Agile/Scrum with Jira, Mizito, Notion and Google Workspace</dd></div>
</dl>
<figure>
<img src="workflow.svg" width="960" height="540" alt="Illustrative diagram of an AI-assisted control-design workflow: model, operating point, linearization, controller candidates, closed-loop simulation and verification, with AI agents supporting each step." loading="lazy">
<figcaption>The kind of workflow the platform automates. This diagram is illustrative and does not show the product interface.</figcaption>
</figure>
<h2 id="the-problem">The problem</h2>
<p>Designing a controller takes a chain of specialist steps. An engineer starts from a nonlinear model of the system, finds an operating point and linearizes it into a state-space model. Then they design and tune candidate controllers, run closed-loop simulations, and check stability and frequency response. Each step needs expertise and usually a different tool, and when a check fails, much of the chain has to be repeated.</p>
<p>The product&rsquo;s bet is that AI agents can carry much of that chain, from a system description to a verified controller candidate.</p>
<h2 id="my-role">My role</h2>
<p>I joined the engineering team in November 2025 and was promoted to Technical Product Manager in March 2026.</p>
<p>As an engineer, I built parts of the automated pipeline. That included an agent workflow that generates operating points, state-space models, controller candidates and closed-loop simulations from nonlinear system descriptions. I also worked on model parsing, signal interconnection, Jacobian linearization, and the stability and frequency-domain checks.</p>
<p>As product manager, I own the product definition and its delivery. I wrote the market requirements document, business plan and business model canvas. I also run discovery, write requirements and acceptance criteria, manage the backlog, coordinate the team, validate releases, and wrote the go-to-market strategy and plan.</p>
<p>Having built the pipeline myself made it much easier to write requirements the engineers could act on, and to judge whether a result was correct.</p>
<h2 id="discovery">Discovery</h2>
<p>I ran market research, competitive analysis and more than 100 customer interviews. The interviews tested our assumptions about the problem and set our priorities. I turned the findings into product requirements and a prioritized roadmap.</p>
<h2 id="key-product-decisions">Main product decisions</h2>
<h3 id="scope-the-mvp-around-design-simulation-and-verification">Scope the MVP around design, simulation and verification</h3>
<p>The first release put the capabilities an engineer needs to trust a result first: automated design, closed-loop simulation and verification. Verification was in the core product from the start.</p>
<h3 id="use-acceptance-criteria-as-the-shared-definition-of-done">Use acceptance criteria as the shared definition of done</h3>
<p>Every capability had user stories and acceptance criteria written in control-engineering terms. Completed features were checked against them before release, so engineering, design and QA all worked to the same definition of &ldquo;done&rdquo;.</p>
<h3 id="validate-before-selling">Validate before selling</h3>
<p>After the MVP, the product went through two proof-of-concept cycles and then an internal readiness gate. Go-to-market execution starts only after that gate.</p>
<h3 id="keep-technical-validation-apart-from-market-evidence">Keep technical validation apart from market evidence</h3>
<p>Test users can show that the product works. Only companies can show that they need it. The go-to-market plan I wrote defines the company-level evidence the next phase has to collect, so proof-of-concept usage is not counted as traction.</p>
<h2 id="delivery">Delivery</h2>
<p>I ran delivery in Agile/Scrum and kept the backlog prioritized in Jira, with Mizito, Notion and Google Workspace alongside it. I coordinated seven engineers and three stakeholders across AI, control engineering, software, product design and QA, and validated each completed feature against its acceptance criteria before release.</p>
<h2 id="results">Evidence and results</h2>
<p>In the first proof of concept, 38 academic test users created 198 projects on the platform. The second proof of concept is complete, and the product-readiness gate was approved internally, which clears the product for the next phase.</p>
<p>This is technical product validation with test users. It does not show paid usage, a company pilot or product-market fit.</p>
<h2 id="whats-next">What&rsquo;s next</h2>
<p>I wrote the go-to-market strategy and plan for the next phase. It covers target accounts, qualification, a launch sequence with gates, and the company-level evidence needed to judge product-market fit. The plan names me as the owner of PMF and go-to-market operations. The formal three-month B2B programme is the next step, and I will add its results here once there are results to report.</p>
<div class="callout">
<p>The company name, customer names, pricing, roadmap details and any internal metrics beyond those above are confidential. The diagram is illustrative. I&rsquo;m happy to discuss the work in more depth in an interview, within those limits.</p>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>ViGenX: an AI video editor that shows its plan before it runs</title>
      <link>https://mahdisf.ir/projects/vigenx-agentic-video-editor/</link>
      <pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate>
      <guid>https://mahdisf.ir/projects/vigenx-agentic-video-editor/</guid>
      <description>Independent open-source product: a video editor that compiles a plain-language brief into a workflow you can inspect and edit, and waits for human approval before rendering.</description>
      <content:encoded><![CDATA[<div class="case-summary">
<p>ViGenX turns a plain-language editing brief into a typed, validated workflow. A person can inspect and change that workflow, and nothing renders until they approve it.</p>
<p>It is my own open-source project. I built the initial MVP in 2025 and showed it at Diginext&rsquo;s 10th Startup Camp. The current release is pre-1.0, suitable for development and testing, and has not yet been validated with external users.</p>
</div>
<dl class="snapshot">
  <div><dt>My role</dt><dd>Independent product and technical lead</dd></div>
  <div><dt>Stage</dt><dd>Pre-1.0, locally run, Apache-2.0</dd></div>
  <div><dt>Built with</dt><dd>Python, Flask, React Flow, Whisper and FFmpeg, with optional Gemini, Groq or NVIDIA planning</dd></div>
  <div><dt>Links</dt><dd><a href="https://github.com/mahdisf/vigenx">Repository</a> · <a href="https://mahdisf.ir/vigenx/">Landing page</a></dd></div>
</dl>
<figure>
<img src="workflow-editor.webp" width="1440" height="900" alt="ViGenX workflow editor. A brief reads 'Turn this podcast into three vertical clips with yellow captions and music'; below it, connected blocks run from Source through Transcribe, Key Moments, Vertical Format, Subtitles and Background Music to Export Clips." loading="lazy">
<figcaption>The brief becomes a graph of registered blocks that can be edited before it runs.</figcaption>
</figure>
<h2 id="the-problem">The problem</h2>
<p>Turning a long recording into short clips means repeating the same steps. You transcribe it, find the moments worth keeping, reframe for vertical video, add captions and music, and export. One-prompt generative tools promise to automate this, but they tend to return a finished render. You can&rsquo;t see which decisions were made or change one step without starting again, and rerunning the same edit gives a different result.</p>
<p>That matters more when the footage carries obligations, such as licensed music, people&rsquo;s faces or third-party clips, because an opaque result is hard to review. My working hypothesis was that creators would trust automation more if they could read and change the plan before it touched their footage.</p>
<h2 id="my-role">My role</h2>
<p>ViGenX is my own project. I defined the product vision, requirements, MVP scope and roadmap, and I led the technical build. Diginext hosted the startup camp where I showed the first MVP. It was not my employer and does not own the project.</p>
<h2 id="what-i-know-about-users-so-far">What I know about users so far</h2>
<p>There has been no structured external user research yet. The problem definition comes from my earlier work producing and editing video content, and from building the first MVP.</p>
<p>That MVP shipped three fixed pipelines: general, speaker and gaming. The current version replaces them with composable blocks that a planner assembles for each brief, so a new kind of edit needs a new block instead of a new pipeline. The fixed pipelines stay available until the graph version reaches parity.</p>
<h2 id="key-product-decisions">Main product decisions</h2>
<h3 id="the-model-plans-and-a-person-approves">The model plans and a person approves</h3>
<p>I considered letting a language model drive the edit end to end. That is the fastest route to a demo, but it is opaque and hard to repeat. Instead, the planner compiles a brief into a graph built only from registered blocks. It cannot invent block types, parameters, file paths, commands or upload targets, and it marks every workflow it generates as requiring approval. The cost is that the planner can only do what the block catalog supports, so new capabilities need engineering work.</p>
<h3 id="users-edit-the-workflow-directly">Users edit the workflow directly</h3>
<p>The graph is serializable JSON. It opens in a visual editor and can be saved and rerun, so users spend their time reviewing, adjusting and reusing an edit instead of regenerating it from another prompt.</p>
<h3 id="planning-works-without-an-api-key">Planning works without an API key</h3>
<p>A deterministic local planner handles common requests such as clip count, duration, vertical format, captions, music and branding. Model-backed planning is optional. In <em>Auto</em> mode ViGenX falls back to the local planner when no key is set, and in <em>AI</em> mode it fails with an error if no provider is configured. The local planner understands a narrower range of briefs.</p>
<h3 id="every-export-carries-rights-information">Every export carries rights information</h3>
<p>Each export writes a rights manifest and metadata. Publishing adapters act only on approved jobs and default to private visibility where the platform supports it. The documentation says plainly that automation does not establish fair use or ownership.</p>
<h3 id="what-i-left-out">What I left out</h3>
<p>ViGenX is not a hosted service, has no multi-user authentication (it binds to localhost) and is not meant to edit autonomously. Leaving these out kept the scope achievable for one person and kept the trust boundary simple.</p>
<h2 id="delivery">Delivery</h2>
<p>I built the initial MVP in 2025 in five-week Agile sprints. It was a Python and Flask pipeline that turned long-form video into short clips, with transcription, key-moment scoring and face blurring using Whisper, MediaPipe, YOLOv8 and Gemini. It also had live job monitoring, a review queue, and metadata and rights files.</p>
<p>The open-source version, public since June 2026, adds a React Flow editor with generated inspector controls, templates and undo/redo. It has a block catalog for editing, audio, branding, AI analysis and export, per-node progress, batch sources, publisher adapters that wait for approval, and an entry point for third-party blocks.</p>
<h2 id="results">Evidence and results</h2>
<p>What exists today:</p>
<ul>
<li>a public, Apache-2.0 repository with continuous integration and unit, API, planner, concurrency and persistence tests;</li>
<li>a working prompt-to-workflow path that runs without downloading models or setting an API key;</li>
<li>the showing of the initial MVP at Diginext&rsquo;s 10th Startup Camp.</li>
</ul>
<p>There is no external usage data, structured user feedback or measured time saving yet. The test suite does not prove render quality on arbitrary footage, and the documentation says so. I am not claiming adoption or product-market fit.</p>
<h2 id="what-i-learned-and-whats-next">What I learned, and what&rsquo;s next</h2>
<p>Separating planning from execution is what makes this AI feature reviewable. I apply the same pattern to AI in engineering software, where a wrong action is expensive and users need to check what the system intends to do before it acts.</p>
<p>Writing down the non-goals and the rights disclaimer early made later scope decisions faster.</p>
<p>The next validation step is to get the first external users to run ViGenX on footage they are allowed to edit and report exactly where it fails. On the engineering side, the open priorities are prompt-to-workflow evaluations with small licensed test videos, bounded render verification, node caching, and workflow diffs with dry-run cost estimates.</p>
<h2 id="artifacts">Artifacts</h2>
<ul>
<li><a href="https://github.com/mahdisf/vigenx">Source code and documentation</a></li>
<li><a href="https://mahdisf.ir/vigenx/">Landing page</a></li>
<li><a href="https://github.com/mahdisf/vigenx/blob/master/CONTRIBUTING.md">Contribution guide</a></li>
</ul>
]]></content:encoded>
    </item>
    <item>
      <title>Adaptive sit-to-stand assistance for the FUM-NEXA knee exoskeleton</title>
      <link>https://mahdisf.ir/projects/fuzzy-aan-knee-exoskeleton/</link>
      <pubDate>Sat, 23 Aug 2025 00:00:00 +0000</pubDate>
      <guid>https://mahdisf.ir/projects/fuzzy-aan-knee-exoskeleton/</guid>
      <description>Real-time ROS2 control for a knee exoskeleton that adapts sit-to-stand assistance to the user&amp;#39;s measured motion. Engineering prototype; first-author preprint.</description>
      <content:encoded><![CDATA[<div class="case-summary">
<p>A fuzzy &ldquo;Strength Index&rdquo; adapts knee-exoskeleton torque in real time while the user stands up from a chair. In a five-person engineering study it cut measured muscle effort by 30% at slow speed, with smaller gains at faster speeds.</p>
<p>This is a research prototype from FUM CARE. I am first author of a <a href="https://doi.org/10.2139/ssrn.6335794">preprint on SSRN</a>, which has not been peer-reviewed. The study was an engineering evaluation and was not clinical.</p>
</div>
<dl class="snapshot">
  <div><dt>My role</dt><dd>Project manager and first author, in a university research team</dd></div>
  <div><dt>Device</dt><dd>FUM-NEXA: passive hip and actuated knee joint per leg</dd></div>
  <div><dt>Task</dt><dd>Standing up from a 46 cm chair</dd></div>
  <div><dt>Runtime</dt><dd>Raspberry Pi 4B, ROS2 (Python/C++), CAN motor control</dd></div>
  <div><dt>Evaluation</dt><dd>5 healthy subjects × 3 speeds × 3 device conditions</dd></div>
</dl>
<h2 id="the-problem">The problem</h2>
<p>Fixed torque profiles are simple to deploy, but they can&rsquo;t tell a user who is moving faster than the reference from one who needs substantial help. A rehabilitation device also has to avoid the opposite failure: giving so much torque that the user stops contributing.</p>
<p>The project had to meet several constraints at once:</p>
<ul>
<li>estimate how much help is needed from signals available on the robot, without continuous EMG control;</li>
<li>adapt torque <em>during</em> the movement as well as between sessions;</li>
<li>run on a Raspberry Pi-class computer with a small sensor and actuator set;</li>
<li>start assisting at the right moment, close to lifting off the chair;</li>
<li>show that the device reduces effort <strong>after</strong> accounting for its own weight and inertia.</li>
</ul>
<p>The last constraint turned out to matter most. Wearing the exoskeleton with the motors off <em>increased</em> measured muscle effort by about 40%, so the controller had to more than offset the device&rsquo;s own burden before it could help.</p>
<h2 id="my-role">My role</h2>
<p>I was project manager and first author. It was a team project at FUM CARE, and I was not the sole designer, fabricator or experimenter.</p>
<p>I developed the control concept, meaning the Strength Index, the fuzzy rule base and the torque-scaling policy. I connected the controller to ROS2, the CAN sensors and actuators, real-time filtering and logging. I coordinated the control, mechanical, experimental and writing work needed to get from concept to a working prototype, and helped structure the three device conditions and three speeds used for validation. I also wrote the manuscript and prepared its figures.</p>
<h2 id="main-design-decisions">Main design decisions</h2>
<p>The controller estimates how much help the user needs from hip and knee velocity errors and torque feedback, without EMG. That estimate of the user&rsquo;s capability is indirect, but it needs no extra sensors on the body.</p>
<p>It scales a reference torque using the index: assistive torque = desired torque × (1 − Strength Index). The movement target stays the same while the amount of help changes.</p>
<p>We chose a small rule base. Nine fuzzy rules run comfortably on a Raspberry Pi and are easy to inspect and tune, which suited a small team and limited compute better than a learned model.</p>
<p>Assistance starts at chair lift-off. The right torque at the wrong phase of the movement is still a bad experience, so we treated the trigger point as a requirement.</p>
<p>The evaluation included a motors-off condition, which separated the device&rsquo;s burden from the controller&rsquo;s benefit.</p>
<p><img alt="The four phases of standing up and the assistance trigger point near chair lift-off" loading="lazy" src="/projects/fuzzy-aan-knee-exoskeleton/sts-trigger-phases.jpg"></p>
<p><em>The four sit-to-stand phases, with the trigger point near chair lift-off.</em></p>
<h2 id="results">Results</h2>
<p>Average change in muscle effort (EMG IRMS) across the five subjects, relative to standing up without the exoskeleton. Positive values mean less effort.</p>
<table>
  <thead>
      <tr>
          <th>Condition</th>
          <th>Speed</th>
          <th style="text-align: right">Effort change</th>
          <th style="text-align: right">Variability change</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Assistance on (50% setting)</td>
          <td>Slow</td>
          <td style="text-align: right">30.34% less</td>
          <td style="text-align: right">33.81% less</td>
      </tr>
      <tr>
          <td>Assistance on (50% setting)</td>
          <td>Normal</td>
          <td style="text-align: right">13.20% less</td>
          <td style="text-align: right">16.45% less</td>
      </tr>
      <tr>
          <td>Assistance on (50% setting)</td>
          <td>Fast</td>
          <td style="text-align: right">7.59% less</td>
          <td style="text-align: right">14.10% less</td>
      </tr>
      <tr>
          <td>Motors off</td>
          <td>Slow</td>
          <td style="text-align: right">41.21% more</td>
          <td style="text-align: right">30.09% more</td>
      </tr>
      <tr>
          <td>Motors off</td>
          <td>Normal</td>
          <td style="text-align: right">38.70% more</td>
          <td style="text-align: right">36.17% more</td>
      </tr>
      <tr>
          <td>Motors off</td>
          <td>Fast</td>
          <td style="text-align: right">40.87% more</td>
          <td style="text-align: right">42.53% more</td>
      </tr>
  </tbody>
</table>
<p>Assistance reduced measured effort at all three speeds. The benefit was largest at slow speed, where help matters most for users who struggle to follow the reference, and it shrank at fast speed, so the controller was not equally effective everywhere. The device&rsquo;s own burden was large enough that the results could only be interpreted against the motors-off condition.</p>
<div class="callout">
<p>Five healthy subjects are not a clinical cohort. These results show engineering feasibility and say nothing yet about rehabilitation efficacy. The study did not report latency, confidence intervals, statistical significance, actuator safety margins or long-term reliability. The next step would need more and more varied participants, comfort and safety measures, and repeatability data.</p>
</div>
<p><img alt="Assistive torque follows the shape of the full desired torque profile at lower magnitude at slow, normal and fast speeds" loading="lazy" src="/projects/fuzzy-aan-knee-exoskeleton/aan-torque-profile.png"></p>
<p><em>The adaptive torque keeps the shape of the reference profile at a lower magnitude across the three speeds.</em></p>
<h2 id="what-i-took-into-product-work">What I took into product work</h2>
<p>A feature can make things worse before it helps, so I now try to measure the cost of adopting a product separately from the value of using it.</p>
<p>Timing belongs in the requirements. Correct output delivered at the wrong moment still fails the user.</p>
<p>Limited compute and sensing pushed this design toward a small controller that is easy to explain, and that worked in its favour.</p>
<h2 id="technical-detail">Technical detail</h2>
<details>
<summary>How the Strength Index works</summary>
<p>The controller represents the user&rsquo;s instantaneous capability as a value between 0 and 1. It takes three inputs: knee angular-velocity error, hip angular-velocity error, and the difference between desired and delivered assistive torque. Each input maps to Negative, Zero or Positive fuzzy sets, and the output uses five bands. A nine-rule Mamdani system combines them, using the minimum for rule firing and centroid defuzzification.</p>
<p>When the user keeps up with the reference, the index rises and assistance falls. When the user lags, or the robot isn&rsquo;t delivering the expected torque, the index falls and assistance rises.</p>
<p>The desired hip and knee velocity profiles are sixth-degree polynomials fitted to 20 normal sit-to-stand motions from able-bodied data. A normalized knee torque-angle profile provides the full-assistance reference, which the index scales.</p>
</details>
<details>
<summary>Runtime architecture</summary>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">CAN sensor data
</span></span><span class="line"><span class="cl">  → filter joint velocity and torque
</span></span><span class="line"><span class="cl">  → compute motion and torque errors
</span></span><span class="line"><span class="cl">  → fuzzy Strength Index → scale desired torque
</span></span><span class="line"><span class="cl">  → motor-driver PID → CAN → knee BLDC actuators
</span></span><span class="line"><span class="cl">  → log sensor, motor and controller data
</span></span></code></pre></div><p>The controller is written in Python, with C++ ROS2 nodes for CAN reading and motor commands (SocketCAN). Real-time second-order Butterworth filters, configured for a 400 Hz sampling assumption, use a 5 Hz cutoff for hip velocity and 10 Hz for knee velocity and torque feedback.</p>
<p><img alt="Functional ROS2 architecture for sensor acquisition, fuzzy control, motor commands and logging" loading="lazy" src="/projects/fuzzy-aan-knee-exoskeleton/ros2-architecture.svg"></p>
</details>
<details>
<summary>Experimental protocol</summary>
<p>Five healthy subjects stood up from a 46 cm chair at three target speeds (slow 20°/s, normal 35°/s, fast 60°/s) under three conditions: no exoskeleton, exoskeleton with motors off, and exoskeleton with assistance at the 50% setting. EMG was recorded from the vastus lateralis, semimembranosus and hamstrings. The analysis used IRMS as a measure of overall muscle effort, signal standard deviation for variability, and percentage change from the no-exoskeleton baseline.</p>
<p><img alt="Processed vastus lateralis EMG for the nine speed and condition combinations" loading="lazy" src="/projects/fuzzy-aan-knee-exoskeleton/emg-results.png"></p>
</details>
<details>
<summary>Hardware and software stack</summary>
<ul>
<li>Two T-Motor BLDC knee actuators (rated up to 48 Nm) with magnetic joint encoders</li>
<li>Raspberry Pi 4B running ROS2</li>
<li>Python, C++, NumPy, SciPy and scikit-fuzzy</li>
<li>CAN bus for sensor acquisition and motor commands</li>
<li>Fuzzy assistance controller on top, PID torque control on the motor driver</li>
</ul>
</details>
<h2 id="publication">Publication</h2>
<p>S. M. Sarfarazi, S. Farhadi, H. Sabzali, M. H. Gheshlaghi, I. Kardan and A. Akbarzadeh, &ldquo;A Fuzzy Strength Index for Adaptive Assist-as-Needed Control of a Knee Exoskeleton Robot to Enhance Sit-to-Stand Transition,&rdquo; SSRN preprint, posted March 2026. <a href="https://doi.org/10.2139/ssrn.6335794">doi:10.2139/ssrn.6335794</a>. The preprint has not been peer-reviewed. Code and video are not public.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
