<?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>GanniPiece Blog</title>
    <link>https://blog.gannipiece.tw/en/</link>
    <description>Recent content on GanniPiece Blog</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Sat, 09 May 2026 15:49:35 +0000</lastBuildDate>
    <atom:link href="https://blog.gannipiece.tw/en/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>How to Use an iPad as a ROS2 Sensor and Receive Data on a Mac</title>
      <link>https://blog.gannipiece.tw/en/posts/how-to-connect-ipad-and-macbook-by-ros2/</link>
      <pubDate>Sat, 09 May 2026 12:00:00 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/how-to-connect-ipad-and-macbook-by-ros2/</guid>
      <description>&lt;p&gt;&lt;em&gt;(the post is automatically translated by AI)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been learning ROS, but I don&amp;rsquo;t have a robot at hand. My idea: use the iPad I already have as a ROS node and receive data on my Mac — sensor data like IMU, Camera, Battery, etc. — to understand how ROS nodes collect and publish data.&lt;/p&gt;
&lt;p&gt;In this article, we&amp;rsquo;ll:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set up the MacBook as a ROS node (using Docker)&lt;/li&gt;
&lt;li&gt;Turn the iPad into a ROS node (using Conduit)&lt;/li&gt;
&lt;li&gt;Receive the iPad&amp;rsquo;s sensor data on the MacBook&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;setting-up-the-macbook-as-a-ros-node-docker&#34;&gt;Setting Up the MacBook as a ROS Node (Docker)&lt;/h2&gt;
&lt;p&gt;The ROS documentation mentions &lt;a href=&#34;https://docs.ros.org/en/kilted/Installation/Alternatives/macOS-Development-Setup.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;installing ROS2 natively on macOS&lt;/a&gt;, but in practice this runs into many deprecated packages and version dependency issues. After a few rounds of debugging with Claude Code, I decided to skip native installation — my goal at this stage was to see the data format ROS2 produces, not fight with the toolchain.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Startup Journey 0002 | Why Isn&#39;t Auto-Scaling Working? The System Just Crashes</title>
      <link>https://blog.gannipiece.tw/en/posts/startup-journey-0002-autoscaling-deep-dive/</link>
      <pubDate>Sat, 11 Apr 2026 06:32:00 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/startup-journey-0002-autoscaling-deep-dive/</guid>
      <description>Startup Journal 0002. Starting a health check on the old system.</description>
    </item>
    <item>
      <title>Startup Journey 0001 | It&#39;s There, But Also Not There</title>
      <link>https://blog.gannipiece.tw/en/posts/startup-journey-0001-environment-consistency/</link>
      <pubDate>Fri, 03 Apr 2026 15:27:00 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/startup-journey-0001-environment-consistency/</guid>
      <description>Startup Journal 0001. Our environments need to be consistent!</description>
    </item>
    <item>
      <title>Startup Journey 0000 | To Join or Not To Join</title>
      <link>https://blog.gannipiece.tw/en/posts/startup-journey-0000-to-join-or-not/</link>
      <pubDate>Sat, 21 Mar 2026 10:00:00 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/startup-journey-0000-to-join-or-not/</guid>
      <description>Startup Journal 0000. I left a big tech company and joined a startup!</description>
    </item>
    <item>
      <title>How to Install Sushi DAW on macOS</title>
      <link>https://blog.gannipiece.tw/en/posts/install-sushi-daw-on-macos/</link>
      <pubDate>Sat, 01 Jun 2024 10:11:44 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/install-sushi-daw-on-macos/</guid>
      <description>Sushi is the plugin host and DAW for the Elk Audio OS. Since version 1.0, it also supports building on macOS. This article documents how to install Sushi DAW on macOS and verify the installation.</description>
    </item>
    <item>
      <title>How to Deploy Hugo to GitLab Pages and Point It to a Gandi Domain</title>
      <link>https://blog.gannipiece.tw/en/posts/deploy-hugo-to-gitlab-with-gandi/</link>
      <pubDate>Sat, 28 Oct 2023 03:49:22 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/deploy-hugo-to-gitlab-with-gandi/</guid>
      <description>My personal website was previously hosted on GitHub, deployed via GitHub Actions. I decided to migrate the workflow to GitLab — here&amp;#39;s how.</description>
    </item>
    <item>
      <title>How to Map MediaPipe Skeleton to Unity Humanoid</title>
      <link>https://blog.gannipiece.tw/en/posts/mediapipe-skeleton-to-unity-humanoid/</link>
      <pubDate>Wed, 08 Mar 2023 00:00:00 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/mediapipe-skeleton-to-unity-humanoid/</guid>
      <description>Using MediaPipe for Motion Capture and mapping the result to a Unity humanoid skeleton</description>
    </item>
    <item>
      <title>Why Coroutine? (Part 2) — Implementing a Coroutine in C</title>
      <link>https://blog.gannipiece.tw/en/posts/why-coroutine-part-2-implementing-in-c/</link>
      <pubDate>Mon, 10 Oct 2022 03:00:17 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/why-coroutine-part-2-implementing-in-c/</guid>
      <description>&lt;p&gt;&lt;em&gt;(the post is automatically translated by AI)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In the previous article, &lt;a href=&#34;https://blog.gannipiece.tw/en/posts/why-coroutine-part-1-is-multithreading-bad/&#34;&gt;Why Coroutine? (Part 1) — Is Multithreading Not Enough?&lt;/a&gt;, we covered the underlying principles of Coroutines and listed the interface we need to implement one in C. In this article, we&amp;rsquo;ll walk through the code line by line.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Source code: &lt;a href=&#34;https://github.com/GanniPiece/SimpleCCoroutine&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GanniPiece/SimpleCCoroutine: A simple coroutine example implemented using C (github.com)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;background-knowledge&#34;&gt;Background Knowledge&lt;/h2&gt;
&lt;p&gt;Before we begin, if you&amp;rsquo;re not familiar with Coroutines, please read the previous article first. In it we mentioned that we can manipulate &lt;code&gt;ucontext_t&lt;/code&gt; [1] using four operations defined in &lt;code&gt;&amp;lt;ucontext.h&amp;gt;&lt;/code&gt;:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Code Expansion: Macro vs Inline Function</title>
      <link>https://blog.gannipiece.tw/en/posts/macro-vs-inline-function/</link>
      <pubDate>Sat, 08 Oct 2022 16:06:04 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/macro-vs-inline-function/</guid>
      <description>&lt;p&gt;&lt;em&gt;(the post is automatically translated by AI)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Macros and inline functions are two techniques for code reuse and expansion. Unlike regular function calls, both avoid the overhead of subroutine push/pop operations at runtime, which can speed up execution.&lt;/p&gt;
&lt;p&gt;The key difference between them is &lt;strong&gt;when&lt;/strong&gt; the expansion happens: macros are substituted by the preprocessor before compilation, while inline functions are expanded by the compiler during compilation. However, both result in larger binary sizes compared to using regular functions, since the code is duplicated at every call site.&lt;/p&gt;</description>
    </item>
    <item>
      <title>#: The Language of the Preprocessor</title>
      <link>https://blog.gannipiece.tw/en/posts/preprocessor-language/</link>
      <pubDate>Wed, 05 Oct 2022 08:30:53 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/preprocessor-language/</guid>
      <description>The preprocessor runs before the compilation phase. It can handle conditional compilation, file inclusion, macro definitions, and more. In this article, we introduce several types of preprocessor directives, such as Conditional inclusion and Replacing text macros.</description>
    </item>
    <item>
      <title>How to Use an iPad as a Wireless MIDI Controller</title>
      <link>https://blog.gannipiece.tw/en/posts/ipad-as-wireless-midi-controller/</link>
      <pubDate>Thu, 14 Jul 2022 02:57:32 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/ipad-as-wireless-midi-controller/</guid>
      <description>In this article, we document how to turn an iPad into a MIDI keyboard and receive its signals on both macOS and Windows.</description>
    </item>
    <item>
      <title>How to Edit a Specific Commit Message in Git</title>
      <link>https://blog.gannipiece.tw/en/posts/how-to-edit-commit-message/</link>
      <pubDate>Sun, 29 May 2022 03:27:37 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/how-to-edit-commit-message/</guid>
      <description>&lt;p&gt;&lt;em&gt;(the post is automatically translated by AI)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;When using &lt;a href=&#34;https://git-scm.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Git&lt;/a&gt; [1] for version control, it&amp;rsquo;s easy to accidentally make a typo in a commit message — or simply realize later that it could be worded better. In those cases, you need to go back and fix the commit message.&lt;/p&gt;
&lt;p&gt;The basic approach is &lt;code&gt;git commit --amend&lt;/code&gt; [2], which corrects the most recent commit message. In this article, I&amp;rsquo;ll document how to go back to an older commit — not just the last one — and edit its message for future reference.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Why Coroutine? (Part 1) — Is Multithreading Not Enough?</title>
      <link>https://blog.gannipiece.tw/en/posts/why-coroutine-part-1-is-multithreading-bad/</link>
      <pubDate>Sat, 28 May 2022 07:54:19 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/why-coroutine-part-1-is-multithreading-bad/</guid>
      <description>While working with UniVRM, I noticed that many Unity development scenarios rely on Coroutines — such as opening a file dialog or loading resources. In this article, I&amp;#39;ll explain what a Coroutine is and compare it with Threads.</description>
    </item>
    <item>
      <title>How to Enable and Detect Memory Leaks in the Unity Editor</title>
      <link>https://blog.gannipiece.tw/en/posts/detect-memory-leak-in-unity/</link>
      <pubDate>Tue, 03 May 2022 06:51:18 +0000</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/detect-memory-leak-in-unity/</guid>
      <description>&lt;p&gt;&lt;em&gt;(the post is automatically translated by AI)&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&#34;introduction&#34;&gt;Introduction&lt;/h2&gt;
&lt;p&gt;A memory leak occurs when allocated memory is never freed. While it doesn&amp;rsquo;t necessarily cause immediate crashes, a leak gradually reduces the available memory, degrading system performance over time. In severe cases, it can lead to unpredictable errors or even security vulnerabilities &lt;a href=&#34;https://owasp.org/www-community/vulnerabilities/Memory_leak&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;1&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Memory: &amp;ldquo;Hmm? Something smells.&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One of the most common causes of memory leaks is forgetting to free dynamically allocated memory — for instance, calling &lt;code&gt;new&lt;/code&gt; on the heap and never calling &lt;code&gt;delete&lt;/code&gt;. The unpredictable timing of when this causes problems makes debugging quite difficult.&lt;/p&gt;</description>
    </item>
    <item>
      <title>How to Import a VRoid Studio Model into Unity with Mixamo Animations</title>
      <link>https://blog.gannipiece.tw/en/posts/import-vroid-model-unity-mixamo/</link>
      <pubDate>Fri, 04 Feb 2022 09:08:23 +0800</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/import-vroid-model-unity-mixamo/</guid>
      <description>A step-by-step guide on how to create a Vtuber model with VRoid Studio, export it as VRM, and bring it into Unity with Mixamo animations.</description>
    </item>
    <item>
      <title>How to Implement an XY Pad with JUCE</title>
      <link>https://blog.gannipiece.tw/en/posts/juce-xypad-implementation/</link>
      <pubDate>Tue, 25 Jan 2022 14:13:30 +0800</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/juce-xypad-implementation/</guid>
      <description>The XY Pad is a common UI design in audio plugins that lets you control two parameters simultaneously. This article covers how to implement an XY Pad using the JUCE framework, explaining the relevant Component classes and override methods.</description>
    </item>
    <item>
      <title>How to Use git rebase to Integrate Branches</title>
      <link>https://blog.gannipiece.tw/en/posts/git-rebase-merge-branches/</link>
      <pubDate>Thu, 20 Jan 2022 11:43:53 +0800</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/git-rebase-merge-branches/</guid>
      <description>Our plugin development is wrapping up, and it&amp;#39;s time to integrate my partner&amp;#39;s changes. In this article, I explain how to use git rebase and walk through a hands-on example.</description>
    </item>
    <item>
      <title>How to Use std::function to Write a Callback Function in C&#43;&#43;</title>
      <link>https://blog.gannipiece.tw/en/posts/cpp-std-function-callback/</link>
      <pubDate>Tue, 18 Jan 2022 00:53:58 +0800</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/cpp-std-function-callback/</guid>
      <description>std::function is a C&#43;&#43;11 feature defined in &amp;lt;functional&amp;gt;. Similar to a function pointer in C, it can store, copy, and invoke any CopyConstructible Callable object.</description>
    </item>
    <item>
      <title>About</title>
      <link>https://blog.gannipiece.tw/en/about/</link>
      <pubDate>Wed, 12 Jan 2022 17:35:20 +0800</pubDate>
      <guid>https://blog.gannipiece.tw/en/about/</guid>
      <description>&lt;p&gt;Contact me&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;mailto: &lt;a href=&#34;mailto:bear110088@gmail.com&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;bear110088@gmail.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LinkedIn: &lt;a href=&#34;https://www.linkedin.com/in/po-chun-wang-947495102&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Po-Chun Wang&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Threads: &lt;a href=&#34;https://www.threads.com/@gannipiece&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;gannipiece&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Github: &lt;a href=&#34;https://github.com/GanniPiece&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;github.com/GanniPiece&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>How to Run GitLab Runner in Docker</title>
      <link>https://blog.gannipiece.tw/en/posts/run-gitlab-runner-in-docker/</link>
      <pubDate>Mon, 25 Oct 2021 12:38:23 +0800</pubDate>
      <guid>https://blog.gannipiece.tw/en/posts/run-gitlab-runner-in-docker/</guid>
      <description>Besides running a locally installed GitLab Runner, GitLab also provides Docker images for running GitLab Runner inside a container. This article follows the official documentation to walk through the setup.</description>
    </item>
  </channel>
</rss>
