<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://nhattran-97.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://nhattran-97.github.io/" rel="alternate" type="text/html" hreflang="en" /><updated>2026-10-02T08:36:16+07:00</updated><id>https://nhattran-97.github.io/feed.xml</id><title type="html">Nhat Tran</title><subtitle>Personal portfolio of Nhat Tran — robotics &amp; AI research, projects, publications and technical notes.</subtitle><entry><title type="html">Kalman Filter — A Practical Cheat Sheet</title><link href="https://nhattran-97.github.io/notes/2026/kalman-filter-cheatsheet/" rel="alternate" type="text/html" title="Kalman Filter — A Practical Cheat Sheet" /><published>2026-09-20T00:00:00+07:00</published><updated>2026-09-20T00:00:00+07:00</updated><id>https://nhattran-97.github.io/notes/2026/kalman-filter-cheatsheet</id><content type="html" xml:base="https://nhattran-97.github.io/notes/2026/kalman-filter-cheatsheet/"><![CDATA[<p>A short summary of the linear Kalman filter: the model, the two steps, and the
tuning tips I always forget. <!--more--></p>

<h2 id="system-model">System model</h2>

\[x_k = F x_{k-1} + B u_k + w_k, \qquad w_k \sim \mathcal{N}(0, Q)\]

\[z_k = H x_k + v_k, \qquad v_k \sim \mathcal{N}(0, R)\]

<h2 id="1-predict">1. Predict</h2>

\[\hat{x}_{k|k-1} = F \hat{x}_{k-1} + B u_k, \qquad
P_{k|k-1} = F P_{k-1} F^\top + Q\]

<h2 id="2-update">2. Update</h2>

\[K_k = P_{k|k-1} H^\top \left(H P_{k|k-1} H^\top + R\right)^{-1}\]

\[\hat{x}_k = \hat{x}_{k|k-1} + K_k \left(z_k - H \hat{x}_{k|k-1}\right), \qquad
P_k = (I - K_k H) P_{k|k-1}\]

<h2 id="minimal-python-implementation">Minimal Python implementation</h2>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="n">np</span>

<span class="k">class</span> <span class="nc">KalmanFilter</span><span class="p">:</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">F</span><span class="p">,</span> <span class="n">H</span><span class="p">,</span> <span class="n">Q</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">x0</span><span class="p">,</span> <span class="n">P0</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">F</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">H</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">Q</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">R</span> <span class="o">=</span> <span class="n">F</span><span class="p">,</span> <span class="n">H</span><span class="p">,</span> <span class="n">Q</span><span class="p">,</span> <span class="n">R</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">x</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">P</span> <span class="o">=</span> <span class="n">x0</span><span class="p">,</span> <span class="n">P0</span>

    <span class="k">def</span> <span class="nf">predict</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">F</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">x</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">P</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">F</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">P</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">F</span><span class="p">.</span><span class="n">T</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">Q</span>

    <span class="k">def</span> <span class="nf">update</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">z</span><span class="p">):</span>
        <span class="n">S</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">H</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">P</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">H</span><span class="p">.</span><span class="n">T</span> <span class="o">+</span> <span class="bp">self</span><span class="p">.</span><span class="n">R</span>
        <span class="n">K</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">P</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">H</span><span class="p">.</span><span class="n">T</span> <span class="o">@</span> <span class="n">np</span><span class="p">.</span><span class="n">linalg</span><span class="p">.</span><span class="n">inv</span><span class="p">(</span><span class="n">S</span><span class="p">)</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">x</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">x</span> <span class="o">+</span> <span class="n">K</span> <span class="o">@</span> <span class="p">(</span><span class="n">z</span> <span class="o">-</span> <span class="bp">self</span><span class="p">.</span><span class="n">H</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">x</span><span class="p">)</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">P</span> <span class="o">=</span> <span class="p">(</span><span class="n">np</span><span class="p">.</span><span class="n">eye</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">x</span><span class="p">))</span> <span class="o">-</span> <span class="n">K</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">H</span><span class="p">)</span> <span class="o">@</span> <span class="bp">self</span><span class="p">.</span><span class="n">P</span>
</code></pre></div></div>

<h2 id="tuning-tips">Tuning tips</h2>

<table>
  <thead>
    <tr>
      <th>Symptom</th>
      <th>Likely cause</th>
      <th>Fix</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Estimate lags behind measurements</td>
      <td>$Q$ too small</td>
      <td>Increase $Q$</td>
    </tr>
    <tr>
      <td>Estimate is noisy</td>
      <td>$R$ too small</td>
      <td>Increase $R$</td>
    </tr>
    <tr>
      <td>Filter diverges</td>
      <td>Model mismatch / bad $P_0$</td>
      <td>Check $F$, inflate $P_0$</td>
    </tr>
  </tbody>
</table>

<blockquote>
  <p><strong>Takeaway:</strong> the ratio between $Q$ and $R$ matters more than their absolute values.</p>
</blockquote>]]></content><author><name></name></author><category term="Autonomy" /><category term="Estimation" /><category term="Robotics" /><summary type="html"><![CDATA[The linear Kalman filter on one page: system model, predict/update equations, a minimal Python implementation and tuning tips.]]></summary></entry><entry><title type="html">ROS 2 Commands I Use Every Day</title><link href="https://nhattran-97.github.io/notes/2026/ros2-cheatsheet/" rel="alternate" type="text/html" title="ROS 2 Commands I Use Every Day" /><published>2026-08-10T00:00:00+07:00</published><updated>2026-08-10T00:00:00+07:00</updated><id>https://nhattran-97.github.io/notes/2026/ros2-cheatsheet</id><content type="html" xml:base="https://nhattran-97.github.io/notes/2026/ros2-cheatsheet/"><![CDATA[<p>A living list of ROS 2 CLI commands for debugging nodes, topics and TF. <!--more--></p>

<h2 id="workspace">Workspace</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>colcon build <span class="nt">--symlink-install</span> <span class="nt">--packages-select</span> my_pkg
<span class="nb">source install</span>/setup.bash
</code></pre></div></div>

<h2 id="topics">Topics</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ros2 topic list <span class="nt">-t</span>                 <span class="c"># list with message types</span>
ros2 topic <span class="nb">echo</span> /odom <span class="nt">--once</span>       <span class="c"># print a single message</span>
ros2 topic hz /scan                <span class="c"># check publish rate</span>
</code></pre></div></div>

<h2 id="tf">TF</h2>

<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ros2 run tf2_ros tf2_echo map base_link
ros2 run tf2_tools view_frames      <span class="c"># generates frames.pdf</span>
</code></pre></div></div>

<h2 id="notes">Notes</h2>

<ul>
  <li>Use <code class="language-plaintext highlighter-rouge">--symlink-install</code> so Python and launch file edits take effect without rebuilding.</li>
  <li><code class="language-plaintext highlighter-rouge">ros2 doctor --report</code> is a quick sanity check when something feels off.</li>
</ul>]]></content><author><name></name></author><category term="Tools &amp; Tips" /><category term="ROS 2" /><category term="Tools" /><summary type="html"><![CDATA[A living list of ROS 2 CLI commands for building workspaces and debugging nodes, topics and TF.]]></summary></entry><entry><title type="html">How I Read a Research Paper</title><link href="https://nhattran-97.github.io/notes/2026/how-to-read-a-paper/" rel="alternate" type="text/html" title="How I Read a Research Paper" /><published>2026-07-02T00:00:00+07:00</published><updated>2026-07-02T00:00:00+07:00</updated><id>https://nhattran-97.github.io/notes/2026/how-to-read-a-paper</id><content type="html" xml:base="https://nhattran-97.github.io/notes/2026/how-to-read-a-paper/"><![CDATA[<p>My three-pass method for reading papers efficiently, adapted from S. Keshav. <!--more--></p>

<h2 id="pass-1--the-birds-eye-view-510-min">Pass 1 — The bird’s-eye view (5–10 min)</h2>

<p>Read the title, abstract, introduction, section headings and conclusion.
Decide: <em>is this paper worth reading further?</em></p>

<h2 id="pass-2--the-content-1-hour">Pass 2 — The content (~1 hour)</h2>

<p>Look carefully at figures and tables. Note the key claims and the evidence
for each. Mark unfamiliar references to read later.</p>

<h2 id="pass-3--virtual-re-implementation-several-hours">Pass 3 — Virtual re-implementation (several hours)</h2>

<p>Try to reproduce the paper in your head (or in code). This is where you find
hidden assumptions and weaknesses.</p>

<h2 id="template-i-keep-for-every-paper">Template I keep for every paper</h2>

<div class="language-markdown highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="gs">**Problem:**</span>
<span class="gs">**Key idea:**</span>
<span class="gs">**Method:**</span>
<span class="gs">**Results:**</span>
<span class="gs">**Limitations:**</span>
<span class="gs">**What I can reuse:**</span>
</code></pre></div></div>]]></content><author><name></name></author><category term="Research" /><category term="Research" /><summary type="html"><![CDATA[My three-pass method for reading research papers efficiently, plus the note template I keep for every paper.]]></summary></entry></feed>