<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>physical-100.log</title>
        <link>https://velog.io/</link>
        <description>세상의 어려운 문제를 해결하자</description>
        <lastBuildDate>Fri, 24 Apr 2026 10:37:29 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>physical-100.log</title>
            <url>https://velog.velcdn.com/images/physical-100/profile/7762471e-c46c-4c96-a3c8-f56638445760/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. physical-100.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/physical-100" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[취준은 힘들다 ..]]></title>
            <link>https://velog.io/@physical-100/%EC%B7%A8%EC%A4%80%EC%9D%80-%ED%9E%98%EB%93%A4%EB%8B%A4-</link>
            <guid>https://velog.io/@physical-100/%EC%B7%A8%EC%A4%80%EC%9D%80-%ED%9E%98%EB%93%A4%EB%8B%A4-</guid>
            <pubDate>Fri, 24 Apr 2026 10:37:29 GMT</pubDate>
            <description><![CDATA[<p>금주는 바빴습니다.. 한화에어로스페이스 1차 직무면접, 코딩테스트, 영어테스트를 진행했거든요.</p>
<p>그런 와중에 작성한 서류들의 결과가 나왔는데 대한항공 일체험 인턴마저 서류 불합격하는 군요.. 시간이 없어서 지원서를 조금 대충 쓰기는 했지만.. 생산 기술 관련 경험이 없긴 하지만 속상한 하루입니다. </p>
<p>한화에어로스페이스의 1차 면접은 크흠... 저 됐어요!!
ㅈ댔어요!!..</p>
<p>이렇게 망한 면접이 있을까 싶을 정도로 당황해서 아무말이나 막 내뱉다 온 것 같은 느낌이 듭니다... 후압....</p>
<p>시간이 부족했다는 핑계를 대고 싶기도 하지만 다들 그렇게 촉박한 일정에 준비했을텐데 저만 그런것은 아니겠죠?
뭐 암튼.. </p>
<p>꿈의 회사의 면접 기회를 얻었다는 것만으로 일단은 만족해보겠습니다...</p>
<p>차별점, 이런 것 보다는 긍정적인 자세와 나의 경험 정리가 무엇보다 중요하다는 것을 알게 되었고 기본적인 지식을 단단히 다져야겠다는 생각이 드네요..</p>
<p>너무 아무것도 모르고 얘기한 사람이 되어벌임..</p>
<p>그래도 서류 합격률이 조금 늘어난만큼 다시금 도전해보겠습니다!@</p>
<ul>
<li>인적성을 틈틈히 풀 것</li>
<li>알고리즘 지식, CS 지식을 보완할것. </li>
<li>전체 플로우차트 작성 및 흐름 정리를 할 것 .</li>
<li>나의 경험 정리를 마칠 것.</li>
<li>하드웨어 지식을 조금 더 쌓고 보완하기 위한 프로젝트들을 진행해볼 것.
쓰읍... 크흠. </li>
</ul>
<h2 id="할-수-있다">할 수 있다!.</h2>
<h4 id="ps-질문-주시면-아는-부분은-가능한-선에서-최대한-알려드리겠습니다">p.s. 질문 주시면 아는 부분은 가능한 선에서 최대한 알려드리겠습니다..</h4>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 3기를 마무리하며 ]]></title>
            <link>https://velog.io/@physical-100/VEDA-3%EA%B8%B0%EB%A5%BC-%EB%A7%88%EB%AC%B4%EB%A6%AC%ED%95%98%EB%A9%B0</link>
            <guid>https://velog.io/@physical-100/VEDA-3%EA%B8%B0%EB%A5%BC-%EB%A7%88%EB%AC%B4%EB%A6%AC%ED%95%98%EB%A9%B0</guid>
            <pubDate>Mon, 13 Apr 2026 05:00:15 GMT</pubDate>
            <description><![CDATA[<p>최종 프로젝트 발표를 마지막으로 VEDA 3기 교육이 끝났습니다.
2개월간 프로젝트에 열의를 가지고 멘토링에 임해주신 <code>신</code>인우 연구원님 정말 감사드립니다. 추가적으로 한화 비전뿐만 아니라 취업에 많은 조언과 팁을 아낌없이 베풀어주신 <code>편장윤</code>과장님께도 무한한 감사를 드립니다. + 프로젝트를 진행하며 도움을 주신 홍영헌 수석님(?), 김명준 책임님 , 마현진 선임 연구원님 모두 감사드립니다. </p>
<p>프로젝트를 진행하며 많은 우여곡절을 겪었고 동시에 많이 배울 수 있는 시간이었습니다. 특히나 하드웨어 제어 디바이스 드라이버 개념과 실습을 진행할 수 있어 초기의 목표 이상을 달성할 수 있었습니다. 한화 비전 카메라 백엔드에서 다루는 RTSP,영상 처리, 보안 등의 실습은 진행하지 못한 점이 아쉬움으로 남지만 그래도 직접 제품을 사용하며 어떤 식으로 동작하고 어떻게 연동되는지를 알 수 있는 시간이었습니다 .</p>
<p>VEDA 교육이 끝나고 다시금 사회에 내던져졌는데 6개월간의 치열하게 살아온 모습은 일주일만에 녹아내리는중 .. </p>
<p>다시금 열의를 불태우며 꾸준히 집중해나가겠습니다. </p>
<p>RS-485와 RTOS를 활용한 장거리 저지연 및 고신뢰성 실시간 시스템을 구현해보자..!!</p>
<p>교육을 들으면서 claude 이 녀석의 무서운 발전에 놀라기도 했지만 한편으로 혼자서 해낼 수 있는 영역이 늘어나서 더 재밌어지는 것 같습니다. </p>
<p>취준의 끝이 어디로 갈지는 모르겠지만 다들 파이팅해봅시다..!</p>
<p>Shot out to VEDA 3 . 6회차 .!</p>
<hr>
<h3 id="최종-프로젝트-code">최종 프로젝트 Code</h3>
<p><a href="https://github.com/VEDA36tmea1/SFEPS">https://github.com/VEDA36tmea1/SFEPS</a></p>
<p>깃허브에 올라가는 있지만 중구난방으로 정리가 되어 있지 않으므로 천천히 코드 리뷰 및 정리로 돌아오겠습니다... </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 22주차 기록 ]]></title>
            <link>https://velog.io/@physical-100/VEDA-22%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@physical-100/VEDA-22%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Tue, 31 Mar 2026 00:51:52 GMT</pubDate>
            <description><![CDATA[<p>22주차. </p>
<h3 id="veda를-마무리하며">VEDA를 마무리하며</h3>
<p>프로젝트 시간이 조금만 더 주어졌더라면 더 완성도 있는  프로젝트를 해낼 수 있었을 것 같다는 아쉬움이 많이 남는 한주였습니다. </p>
<p>근 2주간은 채용 공고, 자소서 작성,  프로젝트까지 쉴 틈없는 하루하루를 보냈습니다.</p>
<p>이제 며칠 뒤면 VEDA 친구들을 못 본다 생각하니 가슴 한켠이.. <strong>시리지가 않네요 ...</strong></p>
<p>진작에 종합레포츠 동아리인 올데이프로젝트를 구성하여 각자의 목표를 이루는 VEDA가 되었으면 하는 아쉬움도 있습니다. </p>
<p>최종 프로젝트의 결과물은 발표 이후에 github와 함께 공개하도록 하겠습니다.</p>
<p>혹시 모를 보안 때문(^^ 찡긋 )</p>
<h4 id="다들">다들</h4>
<p>고생하셨고 치열하게 살아낸 모든 이들에게 박수를 </p>
<h4 id="ps-이종관---탁구-다시-들어와라">PS. 이종관 -&gt; 탁구 다시 들어와라..</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/8b0b3b31-2c41-400a-8c25-53398d8c6dff/image.jpg" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 21주차 기록 ]]></title>
            <link>https://velog.io/@physical-100/VEDA-21%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@physical-100/VEDA-21%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Mon, 23 Mar 2026 08:17:24 GMT</pubDate>
            <description><![CDATA[<p>지난 주는 고민으로 가득한 시도뿐이라 기록할 것이 별로 없었습니다. 그래도 21주차에는 눈에 보이는 성과가 있어서 너무나도 도파민이 뿜뿜했던 기억이 있습니다. </p>
<p>그러면 바로 구현 내용으로 들어가보도록 하겠습니다. </p>
<h2 id="rfid-부정승차-감지-레이저-트래킹-시스템-개발기">RFID 부정승차 감지 레이저 트래킹 시스템 개발기</h2>
<blockquote>
<p>카메라 캘리브레이션부터 RBF 매핑, Z=1200mm 평면 설계, DeepSORT 트래킹까지</p>
</blockquote>
<hr>
<h3 id="목차">목차</h3>
<ol>
<li><a href="#2-z1200mm-%ED%83%80%EA%B2%9F-%ED%8F%89%EB%A9%B4-%EC%84%A4%EA%B3%84">Z=1200mm 타겟 평면 설계</a></li>
<li><a href="#3-%EC%BA%98%EB%A6%AC%EB%B8%8C%EB%A0%88%EC%9D%B4%EC%85%98-%EB%B0%8F-rbf-%EB%A7%A4%ED%95%91">캘리브레이션 및 RBF 매핑</a></li>
<li><a href="#4-bbox-%EC%98%A4%EC%B0%A8-%EB%AC%B8%EC%A0%9C%EC%99%80-deepsort-%EB%8F%84%EC%9E%85-%EB%B0%B0%EA%B2%BD">bbox 오차 문제와 DeepSORT 도입 배경</a></li>
<li><a href="#5-%EC%95%9E%EC%9C%BC%EB%A1%9C-%EA%B5%AC%ED%98%84%ED%95%A0-%EB%82%B4%EC%9A%A9">앞으로 구현할 내용</a></li>
</ol>
<hr>
<blockquote>
<p>💡 <strong>핵심 흐름</strong>
RFID 태깅 감지 → 해당 인물의 신체 좌표 추출 → 레이저로 1200mm 높이 조준 → 관리자 확인</p>
</blockquote>
<h3 id="하드웨어-구성">하드웨어 구성</h3>
<table>
<thead>
<tr>
<th>구성 요소</th>
<th>모델/사양</th>
<th>역할</th>
</tr>
</thead>
<tbody><tr>
<td>IP 카메라</td>
<td>ONVIF 지원 (1920×1080)</td>
<td>RTSP 영상 + 메타데이터</td>
</tr>
<tr>
<td>RFID 리더기</td>
<td>TCP 소켓 연결</td>
<td>태깅 감지 → person_id 전달</td>
</tr>
<tr>
<td>PC</td>
<td>Intel Xe 내장 GPU</td>
<td>영상처리, RBF 연산, 관리자 UI</td>
</tr>
<tr>
<td>ESP8266</td>
<td>WiFi 모듈</td>
<td>UDP 수신 → UART → STM32</td>
</tr>
<tr>
<td>STM32</td>
<td>ARM Cortex-M4</td>
<td>PWM 생성 → 팬틸트 서보 제어</td>
</tr>
<tr>
<td>서보 모터</td>
<td>HDS-2288 × 2</td>
<td>팬(좌우) + 틸트(상하) 2축</td>
</tr>
<tr>
<td>레이저</td>
<td>포인터 모듈</td>
<td>1200mm 평면 조준</td>
</tr>
</tbody></table>
<h3 id="전체-시스템-흐름">전체 시스템 흐름</h3>
<pre><code>RFID 태깅
  → TCP 수신 → person_id 확정
  → RFID 리더기 위치 픽셀(rfid_v) 기준 bbox ratio 계산

매 프레임
  → ONVIF bbox 수신 → 칼만 필터 노이즈 제거
  → target_u = bbox_cx
  → target_v = bbox_top + bbox_height × ratio
  → RBF eval(u, v) → pan_pwm, tilt_pwm
  → UDP → ESP8266 → UART → STM32 → 서보 구동</code></pre><hr>
<h2 id="1-z1200mm-타겟-평면-설계">1. Z=1200mm 타겟 평면 설계</h2>
<h3 id="11-깊이-추정-문제">1.1 깊이 추정 문제</h3>
<p><img src="https://velog.velcdn.com/images/physical-100/post/8f77b7d2-376b-4dd5-b942-bfa1ba553a97/image.png" alt=""></p>
<p>레이저가 실제로 가리켜야 할 3D 좌표를 구하려면 깊이(Z) 정보가 필요하다. 그런데 <strong>단안 카메라만으로는 깊이를 직접 측정할 수 없다.</strong> 처음에는 다음과 같은 방법들을 검토했다.</p>
<table>
<thead>
<tr>
<th>방법</th>
<th>문제점</th>
</tr>
</thead>
<tbody><tr>
<td>사람 키 + 픽셀 비율로 추정</td>
<td>키가 다르고, 가려지면 bbox가 잘려 비율이 틀어짐</td>
</tr>
<tr>
<td>바닥면(Z=0) 교차</td>
<td>카메라 틸트각 정밀 측정 필요, 교실 환경 내에서 책상이나 의자에 가려지면 추정 실패</td>
</tr>
<tr>
<td>스테레오 카메라 추가</td>
<td>하드웨어 추가 비용 및 설치 복잡도</td>
</tr>
<tr>
<td><strong>Z=1200mm 고정 평면</strong></td>
<td><strong>키/거리 무관, 깊이 추정 불필요 ✅</strong></td>
</tr>
</tbody></table>
<h3 id="12-1200mm-고정-평면의-핵심-아이디어">1.2 1200mm 고정 평면의 핵심 아이디어</h3>
<blockquote>
<p>💡 사람의 최소 키를 120cm로 가정하면, <strong>1200mm 높이는 어떤 사람이든 몸통에 해당</strong>한다. 이 평면을 고정 타겟으로 삼으면 거리/키에 관계없이 일관된 조준이 가능하다.</p>
</blockquote>
<p>카메라가 천장 벽면 끝에 비스듬히 설치되어 있기 때문에, 실세계의 수평 평면(Z=1200mm)은 카메라 영상에서 직선이 아닌 <strong>곡선으로 보인다.</strong> RBF 캘리브레이션을 통해 이 평면이 영상에서 어떤 픽셀 위치에 해당하는지 역산할 수 있다.
<img src="https://velog.velcdn.com/images/physical-100/post/e4e9fe31-ae9d-432c-900c-e20cae4676da/image.png" alt=""></p>
<h3 id="13-rfid-태깅-기반-ratio-초기화">1.3 RFID 태깅 기반 ratio 초기화</h3>
<p>1200mm 평면의 영상 픽셀을 구하더라도, 사람의 bbox에서 그 위치가 상단 몇 %인지는 사람마다, 거리마다 다르다. 이를 해결하기 위해 <strong>RFID 태깅 순간을 활용</strong>했다.</p>
<pre><code class="language-python"># RFID 리더기 위치 = 실세계 정확히 Z=1200mm
# 태깅 순간 그 픽셀의 v 좌표 = rfid_v (사전 측정, 고정값)

# 태깅 순간 bbox에서의 비율 계산
ratio = (rfid_v - bbox_top) / bbox_height

# 이후 추적에서 동일 비율 적용
target_v = bbox_top + bbox_height * ratio</code></pre>
<blockquote>
<p>✅ <strong>장점:</strong> 키가 달라도, 거리가 달라도 태깅 순간의 실측값으로 ratio가 결정되므로 추정 오차가 없다. RFID 리더기가 Re-ID보다 훨씬 정확한 &#39;높이 캘리브레이션 도구&#39;가 된다.</p>
</blockquote>
<hr>
<h2 id="2-캘리브레이션-및-rbf-매핑">2. 캘리브레이션 및 RBF 매핑</h2>
<h3 id="21-실세계-캘리브레이션-포인트-측정">2.1 실세계 캘리브레이션 포인트 측정</h3>
<p>카메라 내부 파라미터(fx, fy, cx, cy)는 체커보드 캘리브레이션으로 사전에 구했다. 카메라 틸트각, 레이저 오프셋 등 나머지 미지수는 모두 <strong>현장 측정으로 한번에 흡수</strong>했다.</p>
<p>총 16개 막대를 바닥의 격자 위치에 세우고, 막대 1200mm 높이에 스티커를 붙인 뒤 다음 두 가지를 기록했다.</p>
<ul>
<li>카메라 화면에서 스티커의 픽셀 좌표 (u, v)</li>
<li>키보드로 레이저를 수동 조준했을 때의 서보 PWM 값 (pan, tilt)</li>
</ul>
<table>
<thead>
<tr>
<th>포인트</th>
<th>X(cm)</th>
<th>Y(cm)</th>
<th>u(px)</th>
<th>v(px)</th>
<th>pan PWM</th>
<th>tilt PWM</th>
</tr>
</thead>
<tbody><tr>
<td>p0</td>
<td>-370</td>
<td>65</td>
<td>80</td>
<td>405</td>
<td>890</td>
<td>1320</td>
</tr>
<tr>
<td>p7</td>
<td>0</td>
<td>221</td>
<td>1607</td>
<td>550</td>
<td>1605</td>
<td>1235</td>
</tr>
<tr>
<td>p10</td>
<td>-234</td>
<td>0</td>
<td>5</td>
<td>632</td>
<td>870</td>
<td>1170</td>
</tr>
<tr>
<td>p15</td>
<td>0</td>
<td>100</td>
<td>1535</td>
<td>898</td>
<td>1570</td>
<td>1065</td>
</tr>
<tr>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
<tr>
<td>(총 16개)</td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody></table>
<h3 id="22-rbf-thin-plate-spline-원리">2.2 RBF (Thin-Plate Spline) 원리</h3>
<p><img src="https://velog.velcdn.com/images/physical-100/post/594869d2-d1fe-4074-b430-d993cd251d7a/image.png" alt=""></p>
<p>16개 캘리브 포인트를 이용해 두 가지 RBF 보간 함수를 학습했다.</p>
<ul>
<li><code>pixel(u, v)</code> → <code>pan PWM</code></li>
<li><code>pixel(u, v)</code> → <code>tilt PWM</code></li>
</ul>
<p>RBF(Radial Basis Function)는 <strong>알고 있는 점들로부터의 거리를 기반으로 모르는 점을 추정</strong>하는 방법이다. Thin-Plate Spline 커널 <code>φ(r) = r²·log(r)</code> 을 사용하면 2D 픽셀 공간에서 가장 부드럽고 정확한 보간이 가능하다.</p>
<pre><code class="language-python"># 학습 (1회)
from scipy.interpolate import RBFInterpolator

rbf_pan  = RBFInterpolator(pixels, pwms[:,0],
                            kernel=&#39;thin_plate_spline&#39;)
rbf_tilt = RBFInterpolator(pixels, pwms[:,1],
                            kernel=&#39;thin_plate_spline&#39;)

# 추론 (매 프레임)
pan  = int(rbf_pan([[u, v]])[0])
tilt = int(rbf_tilt([[u, v]])[0])</code></pre>
<p>카메라 파라미터, 서보 스펙, 레이저 오프셋을 <strong>아무것도 몰라도 된다.</strong> 그냥 &quot;이 픽셀이면 이 PWM이더라&quot;는 실측 데이터 16개만 있으면 끝이다.</p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/f53ea554-cd45-4041-a477-5c8688523194/image.png" alt=""></p>
<h3 id="23-교차-검증-결과">2.3 교차 검증 결과</h3>
<p>Leave-One-Out 교차검증으로 16개 포인트 각각을 제외하고 나머지 15개로 보간한 뒤 예측 오차를 측정했다.</p>
<table>
<thead>
<tr>
<th>항목</th>
<th>pan 오차</th>
<th>tilt 오차</th>
</tr>
</thead>
<tbody><tr>
<td>평균 오차</td>
<td><strong>6.1 PWM</strong></td>
<td><strong>7.4 PWM</strong></td>
</tr>
<tr>
<td>최대 오차</td>
<td>23.0 PWM</td>
<td>34.0 PWM</td>
</tr>
<tr>
<td>각도 환산</td>
<td>≈ 0.6°</td>
<td>≈ 0.7°</td>
</tr>
<tr>
<td>실용 판정</td>
<td>✅ 충분</td>
<td>✅ 충분</td>
</tr>
</tbody></table>
<blockquote>
<p>📌 <strong>p15 포인트(X=0, Y=100) 추가 후</strong> 기존 p7의 tilt 오차가 146 PWM → 9 PWM으로 <strong>94% 감소</strong>했다. 데이터 분포가 고른 것이 정확도에 결정적 영향을 준다.</p>
</blockquote>
<h3 id="24-영상-내-1200mm-평면-격자-투영">2.4 영상 내 1200mm 평면 격자 투영</h3>
<p>세계좌표(X, Y) → 픽셀(u, v) 역방향 RBF도 함께 학습하여, 실세계 격자가 카메라 영상에서 어떻게 보이는지 실시간으로 오버레이했다.</p>
<pre><code class="language-python"># 실세계 격자 → 영상 투영
for X in range(-500, 10, 100):     # X 등간격 (cm)
    for Y in range(0, 1050, 100):  # Y 등간격 (cm)
        u = rbf_u.eval(X, Y)       # 세계→픽셀 RBF
        v = rbf_v.eval(X, Y)
        cv2.circle(frame, (int(u), int(v)), 3, (80, 220, 80), -1)</code></pre>
<p>투영 결과, 실세계에서 수평인 격자가 영상에서는 카메라 시점에 따라 <strong>곡선으로 휘어져</strong> 보였다. 카메라가 비스듬히 설치되어 있기 때문에 당연한 현상이며, RBF가 이 왜곡을 자연스럽게 학습했음을 확인했다.</p>
<h4 id="실제-평면-구현도">실제 평면 구현도</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/a381e846-5dde-4142-a900-f4aaed8b821d/image.png" alt=""></p>
<hr>
<h2 id="3-bbox-오차-문제와-deepsort-도입-배경">3. bbox 오차 문제와 DeepSORT 도입 배경</h2>
<h3 id="31-onvif-bbox-노이즈">3.1 ONVIF bbox 노이즈</h3>
<p>카메라 ONVIF 메타데이터로 받는 bbox는 카메라 내부 AI가 매 프레임 독립적으로 계산하기 때문에, 사람이 가만히 있어도 bbox가 흔들린다. 실측 결과는 충격적이었다.</p>
<table>
<thead>
<tr>
<th>구분</th>
<th>측정값</th>
<th>영향</th>
</tr>
</thead>
<tbody><tr>
<td>pan 노이즈</td>
<td>30 PWM</td>
<td>레이저 좌우 떨림</td>
</tr>
<tr>
<td>tilt 노이즈</td>
<td><strong>52 PWM</strong></td>
<td>레이저 상하 떨림 (더 심각)</td>
</tr>
<tr>
<td>bbox 픽셀 오차</td>
<td><strong>약 104px</strong></td>
<td>tilt 방향 RBF 민감도가 높음</td>
</tr>
</tbody></table>
<h3 id="32-visual-trackercsrtkcf를-시도했지만">3.2 Visual Tracker(CSRT/KCF)를 시도했지만...</h3>
<p>bbox 노이즈 문제를 해결하기 위해 OpenCV의 CSRT, KCF 트래커를 시도했다. 초기화 이후 bbox 노이즈가 크게 줄어드는 장점이 있었지만 치명적인 문제들이 있었다.</p>
<ul>
<li>❌ <strong>겹침 처리 불가:</strong> 두 사람이 겹치면 다른 사람으로 붙어버림</li>
<li>❌ <strong>CSRT FPS 저하:</strong> 1920×1080 풀 해상도에서 겨우 6fps</li>
<li>❌ <strong>장시간 드리프트:</strong> 외형 변화에 따라 서서히 위치가 틀어짐</li>
</ul>
<blockquote>
<p>⚠️ Visual Tracker는 단기 추적에는 효과적이지만, 사람이 겹치거나 일시적으로 가려지는 실제 환경에서는 신뢰할 수 없다는 결론에 도달했다.</p>
</blockquote>
<h4 id="실제-추적-결과">실제 추적 결과</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/70b892de-872f-4f11-9b21-9ee8c6a744d7/image.gif" alt=""></p>
<h3 id="😭">😭</h3>
<h3 id="33-deepsort-경량-구현-방향">3.3 DeepSORT 경량 구현 방향</h3>
<p>현업에서 가장 널리 쓰이는 <strong>DeepSORT(Detection + 칼만 필터 + Re-ID)</strong> 를 도입하기로 결정했다. 우리 시스템의 특성상 전체 DeepSORT를 구현할 필요는 없다.
<a href="https://gngsn.tistory.com/94">DeepSORT</a> 에 대해 잘 설명된 블로그를 첨부하며 <code>DeepSORT</code>에 대한 설명을 생략하도록 하겠다.</p>
<table>
<thead>
<tr>
<th>DeepSORT 구성요소</th>
<th>필요 여부</th>
<th>이유</th>
</tr>
</thead>
<tbody><tr>
<td>Detection (ONVIF)</td>
<td>✅ 이미 있음</td>
<td>카메라 AI가 처리</td>
</tr>
<tr>
<td>칼만 필터</td>
<td>✅ 필요</td>
<td>bbox 노이즈 흡수</td>
</tr>
<tr>
<td>헝가리안 매칭</td>
<td>✅ 필요</td>
<td>겹칠 때 올바른 ID 유지</td>
</tr>
<tr>
<td>CNN Re-ID</td>
<td>△ 선택</td>
<td>색상 히스토그램으로 대체 가능</td>
</tr>
<tr>
<td>다중 트랙 관리</td>
<td>△ 단순화</td>
<td>RFID가 타겟 ID 확정</td>
</tr>
</tbody></table>
<p><strong>RFID가 이미 타겟 ID를 100% 정확하게 확정해주기 때문에</strong>, DeepSORT의 Re-ID 역할 대부분을 RFID가 대체한다. 결과적으로 칼만 필터 + 색상 기반 Re-ID + 헝가리안 매칭의 경량 구현으로 충분하다.</p>
<hr>
<h2 id="4-앞으로-구현할-내용">4. 앞으로 구현할 내용</h2>
<h3 id="41-mediapipe-어깨-중심점-기반-몸-중심-탐지">4.1 MediaPipe 어깨 중심점 기반 몸 중심 탐지</h3>
<p>현재 bbox 중앙을 타겟으로 사용하면 <strong>팔을 벌리거나 돌아서는 경우 bbox 중심이 실제 몸 중심과 달라지는 문제</strong>가 있다. MediaPipe Pose를 도입하여 어깨 keypoint를 직접 추출할 예정이다.</p>
<pre><code class="language-python"># MediaPipe 어깨 중심점 추출
mp_pose = mp.solutions.pose
pose = mp_pose.Pose(min_detection_confidence=0.5)

result = pose.process(roi_rgb)
lm = result.pose_landmarks.landmark

L_SH = lm[mp_pose.PoseLandmark.LEFT_SHOULDER]
R_SH = lm[mp_pose.PoseLandmark.RIGHT_SHOULDER]

# 가시성 기반 fallback 전략
if L_SH.visibility &gt; 0.5 and R_SH.visibility &gt; 0.5:
    # 1순위: 양쪽 어깨 중점
    u = (L_SH.x + R_SH.x) / 2 * img_w
    v = (L_SH.y + R_SH.y) / 2 * img_h
elif L_SH.visibility &gt; 0.5:
    # 2순위: 한쪽 어깨
    u, v = L_SH.x * img_w, L_SH.y * img_h
else:
    # 3순위: bbox 상단 26% fallback
    u = (x1 + x2) / 2
    v = y1 + (y2 - y1) * 0.26</code></pre>
<p>어깨 keypoint는 팔을 벌려도 변하지 않고, bbox 가로 크기 변화에 영향받지 않는다. 또한 RFID 태깅 순간 어깨 픽셀 위치와 1200mm 기준점의 오프셋 비율을 계산해두면, 이후 어깨가 가려져도 안정적으로 타겟을 유지할 수 있다.</p>
<h3 id="42-deepsort-적용으로-트래킹-진동-제거">4.2 DeepSORT 적용으로 트래킹 진동 제거</h3>
<p>경량 DeepSORT를 구현하여 사람이 겹치거나 일시적으로 화면을 벗어나는 상황에서도 ID를 안정적으로 유지할 계획이다.</p>
<ul>
<li><strong>칼만 필터:</strong> bbox 노이즈 흡수 및 가려짐 시 위치 예측 유지</li>
<li><strong>색상 히스토그램 Re-ID:</strong> HSV 히스토그램 기반 외형 매칭 (CPU만으로 578fps 가능)</li>
<li><strong>헝가리안 알고리즘:</strong> 다중 사람 겹침 시 최적 ID 매칭</li>
<li><strong>RFID 트리거:</strong> 태깅 순간 트랙 ID와 person_id 연결</li>
</ul>
<blockquote>
<p>🔧 <strong>실용적 접근:</strong> <code>deep-sort-realtime</code> Python 라이브러리로 먼저 검증한 뒤, 검증이 완료되면 C++로 이식한다. ONVIF Detection이 이미 구현되어 있으므로 Re-ID + 칼만 + 헝가리안만 추가하면 된다.</p>
</blockquote>
<h3 id="43-stm32-코드-포팅-rbf-eval">4.3 STM32 코드 포팅 (RBF eval)</h3>
<p>현재 PC에서 수행하는 RBF 연산(pixel → PWM)을 STM32로 이식하면, PC로부터 <strong>픽셀 좌표(u, v)만 받아도 서보를 직접 제어</strong>할 수 있다. 통신 부하가 줄어들고, PC 연결이 끊겨도 마지막 픽셀 기준으로 자체 동작이 가능해진다.</p>
<table>
<thead>
<tr>
<th>항목</th>
<th>값</th>
<th>비고</th>
</tr>
</thead>
<tbody><tr>
<td>RBF eval 연산량</td>
<td>~262회 부동소수점</td>
<td>pan + tilt 각 1회</td>
</tr>
<tr>
<td>예상 실행 시간</td>
<td><strong>~13μs</strong></td>
<td>STM32F4 @ 168MHz</td>
</tr>
<tr>
<td>30fps 예산</td>
<td>33,333μs</td>
<td>여유 <strong>2,500배</strong></td>
</tr>
<tr>
<td>메모리 사용량</td>
<td>~432 bytes</td>
<td>SRAM 192KB 중 0.2%</td>
</tr>
<tr>
<td>필요 구현</td>
<td>eval() 함수만</td>
<td>fit()은 PC에서 1회 계산</td>
</tr>
</tbody></table>
<pre><code class="language-c">// STM32 RBF eval (C)
// 학습된 가중치는 PC에서 추출 후 const 배열로 저장
float rbf_eval(float u, float v,
               const float* W,
               float a0, float a1, float a2) {
    float s = a0 + a1*u + a2*v;
    for (int i = 0; i &lt; 16; i++) {
        float du = u - CALIB_U[i];
        float dv = v - CALIB_V[i];
        float r  = sqrtf(du*du + dv*dv);
        s += W[i] * r * r * logf(r + 1e-6f);
    }
    return s;
}

// 사용: UART로 (u, v) 수신 후
float pan  = rbf_eval(u, v, PAN_W,  PAN_A0,  PAN_A1,  PAN_A2);
float tilt = rbf_eval(u, v, TILT_W, TILT_A0, TILT_A1, TILT_A2);
servo_set_pwm((int)pan, (int)tilt);</code></pre>
<hr>
<h2 id="마치며">마치며</h2>
<p>이 프로젝트에서 가장 어려웠던 부분은 <strong>&quot;레이저가 실제로 어디를 가리켜야 하는가&quot;</strong> 라는 좌표 설계 문제였다. 단안 카메라만으로 3D 좌표를 정확히 추정하는 것은 본질적으로 어렵다.</p>
<p><strong>Z=1200mm 고정 평면 + RFID 태깅 기반 ratio 초기화</strong> 라는 조합은 이 문제를 하드웨어 제약을 활용해 우아하게 해결한 방법이었다. 카메라를 추가하거나 복잡한 알고리즘을 쓰지 않아도, 이미 존재하는 RFID 인프라가 3D 좌표 캘리브레이션 도구가 되었습니다.</p>
<p>앞으로 MediaPipe 어깨 탐지와 DeepSORT, STM32 포팅까지 완료되면, 하드웨어부터 임베디드까지 전 스택이 완성된 실시간 레이저 트래킹 시스템이 구축될 것 같습니다 .
두구두구두구 <del>~</del>///!! </p>
<hr>
<p><em>Tags: <code>Computer Vision</code> <code>Calibration</code> <code>RBF</code> <code>DeepSORT</code> <code>STM32</code> <code>레이저 트래킹</code> <code>RFID</code></em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 헤일메리 - review]]></title>
            <link>https://velog.io/@physical-100/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%97%A4%EC%9D%BC%EB%A9%94%EB%A6%AC-review</link>
            <guid>https://velog.io/@physical-100/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%97%A4%EC%9D%BC%EB%A9%94%EB%A6%AC-review</guid>
            <pubDate>Sat, 21 Mar 2026 14:25:36 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/physical-100/post/dfe4f97b-209e-4f34-b0af-a572d2ea259d/image.png" alt=""></p>
<h3 id="프로젝트-헤일메리">프로젝트 헤일메리</h3>
<p>유튜브를 보다 뜬 예고편을 보고 흥미가 생겨서 개봉한지 불과 3일여만에 영화관으로 달려갔다. </p>
<p>라이언 고슬링의 &quot;I met an alien&quot; 로 시작하는 예고편을 보고 나오는 바위 덩이를 보고서는 그 호기심을 감출 수 없었다 .</p>
<p>사실 나는 SF 영화를 상당히 좋아한다. 취향을 알게 된 것은 불과 몇년도 채 되지 않았다. 나이가 들어감에 따라 취향에 대해서 알게 되는 것 같다.</p>
<h4 id="anyway">Anyway,,</h4>
<p>아무런 정보도 없이 시작한 영화는 다소 흥미로웠다 ..</p>
<p>.
.
.
.</p>
<p>여기서부터는 다소 스포일러가 있을 수 있으니 원치 않는 분들은 뒤로가기를 눌러버렸!!! ㅎㅎ </p>
<p>우선 태양의 에너지를 양분 삼아 <code>CO2</code>가 풍부한 대기로 나아가는 미생물의 존재 , 그리고 미생물이 초래하는 태양계의 위기라는 소재가 상당히 신선했다. </p>
<p>그리고 그레이스라는 주인공이 생물의 필수 요소를 부정하는 과학자라는 이유로 선발된 것이 이후 나오는 외계인과의 연관 요소가 있을 것 같았지만 별도의 이야기가 이후에 전개되지는 않았다.</p>
<p>앞서 말한 위기는 전 우주로 퍼져나가고 있었고 한 행성계에서 관측된 예외를 관찰하기 위해 지구에서는 소수 인원을 편도 여행을 보내게 된다.</p>
<p>다시 그레이스 시점에서 과거 기억과 현재 우주가 긴박하게 이어지며 <code>로키</code>라는 외계 생물을 마주하게 된다. </p>
<p>로키와 대화를 시도하는 과학자 그레이스의 모습을 보며 내가 저기에 있다면 저렇게 할 수 있을까? 라는 생각이 들었다. &#39;음 TTS, STT, 파형, 전기 회로 관련 지식이 필요하군&#39; 이라는 생각을 하면서 살짝 취준에 절어있는 모습 발견 ;;</p>
<p>사실 SF 영화에서 그런 새로운 기술이 적용되는 모습을 찾는 것 또한 나에게 하나의 재미이다. 그래서 이번 영화에서도 로키와 그레이스가 로키에게 적합한 목소리를 고르는 장면을 보며 신선하기도 했다. 실제 사람들이 여러 서비스에서 사용하는 것과 다르지 않았으니. </p>
<p>이후에는 비슷한 상황에 처한 두 존재가 협력하는 내용이 이어진다. 
위기를 겪으며 한가지 든 생각은 우주선이라는 기체 자체는 정말 다양한 상황에서도 작동하는 시스템이 중요하겠다는 생각이 들었다. 연료 탱크를 사출하거나 특정 시스템에 고장이 나거나 압력 차이로 인해 시스템이 예상치 못한 속도로 충돌이 발생했을 때에도 정상적인 동작이 가능하도록 하는 안정 시스템이 필요하다는 것을 느끼며 어떻게 구현할 수 있을까? 라는 고민도 하게 되는 시간이었다. </p>
<h3 id="후기">후기</h3>
<p>영화는 생각한 SF영화와 같이 흥미진진한 액션영화는 아니었지만 새로운 소재의 더욱이 신선한 영화였다. 특히 여자친구가 중간에 살짝 지루한 표정을 지어서 걱정을 했었다. <code>으악 같이 보러오쟀는데 별로인가?</code> 라는 .</p>
<p>그런 걱정이 무색하게 영화가 종료되고 퇴장을 하면서 살면서 본 영화 중 가장 재미있었다는 평을 해주었다.( 은근 기분 좋음 😳)</p>
<p>또한 사실상 라이언 고슬링의 독백 영화이지만 연기력이 너무나 뛰어나서 몰입할 수 있었다. </p>
<h4 id="한줄평">한줄평</h4>
<p>큰 파장을 준 <u>이동진 평론가</u>의 말을 빌려 표현하겠다. </p>
<blockquote>
<p>인생은 원래 편도 여행이다.</p>
</blockquote>
<p>인생은 본디 편도 여행이다. 되돌아갈 수도 없고 앞에는 무엇이 있을지 모른다.
그러니 겁먹지 말자. 후회하지 말자. 
사실 나 또한 주인공의 상황에 처한다면 쉽사리 무조건 우주선에 올라타겠다고 말을 할 수 는 없다. 우주 여행이 인생의 목표 중 하나인 사람이지만서도. </p>
<p>보장된 20년 남짓과 사명감을 가진 임무. </p>
<p>물론 끝은 죽음으로 동일하지만 용기가 필요한 법이다. 그런 관점에서 프로젝트 헤일메리는 그런 용기를 조금이나마 더해준 그런 영화이다. </p>
<p>소설 원작인 것을 그제야 처음 알았다. </p>
<h3 id="의문-😒">의문 😒</h3>
<p>영화가 끝난 이후 여운을 가지고 영화에 대해서 조금 더 서칭을 진행. 소설 원작인 것을 그제야 처음 알았다. 원작에서는 왜 그레이스인지에 대한 묘사가 더 많이 나온다고 한다. 또한 더 많은 위기를 겪지만 영화에서는 2시간 40분이라는 타임라인 안에 담기 위해 많은 각색이 추가되었다고 한다.</p>
<ol>
<li><p>왜 우주에서 연구 장비를 사용하기 위해서 중력을 만들어내는 원심분리기가 필요할까 ?</p>
<ul>
<li>이에 대한 해답은 한 유튜브에서 얻을 수 있었습니다.
<a href="https://youtu.be/KXkyy8cawnw?si=Ngn99FcxOD-XNA4Q">리뷰엉이 : 헤일메리 속 과학 총 정리</a></li>
</ul>
</li>
<li><p>로키는 어떻게 뚝딱 대기 환경까지 조절을 할 수 있나?</p>
<ul>
<li>이건 그냥 외계 생물 특수성 </li>
</ul>
</li>
<li><p>로키와 그레이스는 비슷하다 동료가 본인 외에 다 죽은 상태에서 깼다는 것까지 . 하지만 로키의 동료들이 죽은 이유는 그레이스가 설명한다. 왜 그레이스는 혼자만 깨어나게 되었을까?</p>
<ul>
<li>이는 소설에 언급이 되어있다고 한다. 그레이스는 혼수 저항 유전자를 가진 특별한 인간이라고 .  </li>
</ul>
</li>
</ol>
<h3 id="외계-생물">외계 생물</h3>
<p>아스트로파지부터 로키, 그리고 해결 미생물까지 이는 다양한 관점에서 외계 생물을 바라보게 했다. </p>
<p>로키 : 지구에서 희생을 요구당할 때 로키는 희생을 보여주었다. 
어쩌면 인류보다 더욱 동료애를 확인할 수 있는 귀여운 존재였다 .</p>
<p>아스트로파지 : 엄청난 에너지 전환율을 가진 생물로 에너지원으로도 사용되는 모습을 보여준다. 사실 미생물 단위에서는 상상 이상의 속도, 에너지 전환율을 보여준다는 것을 다시금 상상해볼 수 있는 기회였다. </p>
<pre><code>지구의 위기를 초래한 dot이지만 중간 중간 황홀한 시각적 자극을 제공해준다. </code></pre><hr>
<p>소설도 읽어봐야겠다 생각하며 <strong>프로젝트 헤일메리 추천@!</strong></p>
<h1 id="👎">👎</h1>
<p>thumbs up !</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AlldayProject_OPIC-2]]></title>
            <link>https://velog.io/@physical-100/AlldayProjectOPIC-2</link>
            <guid>https://velog.io/@physical-100/AlldayProjectOPIC-2</guid>
            <pubDate>Sun, 15 Mar 2026 17:22:24 GMT</pubDate>
            <description><![CDATA[<p>이번주에는 후다닥 오픽을 보았습니다.,,
그 결과는 살짝 망.. 평소보다 더듬으며 실제 답변을 마감하라는 알림을 보며 급한 마음에 문장을 너무 성급히 마무리한 느낌이 많습니다.</p>
<p>속상하게도 별로 준비하지 않은 독서와 재활용에 대한 질문이 주를 이뤘습니다 .</p>
<p>난이도 6-6. </p>
<p>질문 자체는 어렵지 않았음 </p>
<p>skip 1회. </p>
<p>new apartment에 대한 사회적 이슈 (돌발) </p>
<ul>
<li><p>재활용 </p>
<ul>
<li>이사왔는데 관리실에 재활용 관련 질문하라 </li>
</ul>
</li>
<li><p>영화 </p>
<ul>
<li>좋아하는 영화 장르 </li>
<li>가장 최근에 본 영화 </li>
<li>영화관에 가서 하는 행동.before , after </li>
</ul>
</li>
<li><p>독서</p>
<ul>
<li>가장 최근에 읽은 책 </li>
<li>책을 구매한 경험 누군가에게 선물한 경험 </li>
</ul>
</li>
<li><p>country </p>
<ul>
<li>특별한 기억 </li>
<li>과거에 비해 어떻게 달라졌는지 </li>
</ul>
</li>
<li><p>사는 공간 </p>
<ul>
<li>과거에 비해 어떻게 달라졌는지 </li>
</ul>
</li>
</ul>
<p>정확히는 기억나지 않지만 준비해간 표현들은 새카맣게 까먹어버렸다 ...</p>
<hr>
<h2 id="opic-표현-정리-">OPIC 표현 정리 .</h2>
<h3 id="헬스장">헬스장</h3>
<ul>
<li><p>운동 루틴</p>
<p>So, working out is honestly a big part of my daily routine. I usually stick to a workout routine — I try to go to the gym at least three or four times a week.</p>
<p>  When I get there, I usually start with about 20 minutes on the treadmill just to warm up. Then I move on to weightlifting machines — I focus on different muscle groups depending on the day.</p>
<p>  I&#39;m not really a tiny, weak beginner anymore, but I&#39;m definitely not an expert either. I&#39;d say I&#39;m somewhere in the middle. I find it really satisfying when I can feel myself getting stronger, you know?</p>
<p>  After my workout, I always feel totally refreshed — like, all the stress just disappears. That&#39;s probably what I really love about going to the gym. It&#39;s the best way for me to blow off steam after a long day__._</p>
</li>
</ul>
<ul>
<li>Gym Describe</li>
</ul>
<pre><code>My gym is actually pretty spacious — like, it never really feels cramped, which I appreciate. It has cutting-edge equipment, so you&#39;ve got everything from treadmills to stationary bicycles to all kinds of weightlifting machines.

The only downside is that it can get pretty packed during peak hours — you know, right after work. So I usually try to go either early in the morning or late at night to avoid the crowd.

What I really love about my gym is that it&#39;s super close to my place, so there&#39;s no excuse not to go. I tend to feel way more motivated when the gym is convenient, you know what I mean?

Overall, I think it&#39;s a really solid gym. It would be great if they had a sauna though — that&#39;s the one thing I wish they&#39;d add.</code></pre><ul>
<li>role Playing</li>
</ul>
<pre><code>**📞 전화 시작**

Hi there! Um, I&#39;m actually thinking about joining your gym, so I just had a few questions if that&#39;s okay.

**💰 비용 문의**

First of all, how much does that cost per month? And are there any promotions or deals for new members? I just want to make sure it&#39;s affordable before I commit.

**🏢 시설 문의**

Also, I was wondering — is the gym spacious? And does it have cutting-edge equipment? I&#39;m specifically looking for a place with good weightlifting machines and treadmills.

**⏰ 혼잡도 문의**

One more thing — does it get pretty packed during certain hours? I&#39;d like to know the best time to go to avoid the crowd.

**✅ 마무리**

Okay, that&#39;s really helpful. I&#39;ll check it out and maybe come by this week. Thanks so much — you&#39;ve made my day!</code></pre><table>
<thead>
<tr>
<th>표현</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td><code>blow off steam</code></td>
<td>스트레스를 풀다</td>
</tr>
<tr>
<td><code>stick to a workout routine</code></td>
<td>꾸준히 운동하다</td>
</tr>
<tr>
<td><code>feel refreshed / feel loose</code></td>
<td>몸이 개운해지다</td>
</tr>
<tr>
<td><code>workout buddy</code></td>
<td>운동 친구</td>
</tr>
<tr>
<td><code>push myself to the limit</code></td>
<td>한계까지 밀어붙이다</td>
</tr>
<tr>
<td><code>spacious</code></td>
<td>널찍한</td>
</tr>
<tr>
<td><code>treadmill</code></td>
<td>러닝머신</td>
</tr>
<tr>
<td><code>stationary bicycle</code></td>
<td>자전거 머신</td>
</tr>
<tr>
<td><code>weightlifting machine</code></td>
<td>웨이트 기구</td>
</tr>
<tr>
<td><code>has cutting-edge equipment</code></td>
<td>최신 장비가 갖춰져 있다</td>
</tr>
<tr>
<td><code>cutting edge</code></td>
<td>최첨단의, 최신의</td>
</tr>
<tr>
<td><code>get pretty crowded</code></td>
<td>꽤 붐비다</td>
</tr>
<tr>
<td><code>packed</code></td>
<td>붐비는</td>
</tr>
<tr>
<td><code>tiny, weak beginner</code></td>
<td>약하고 작은 초보자</td>
</tr>
<tr>
<td><code>still attend gym</code></td>
<td>여전히 헬스장에 다니다</td>
</tr>
<tr>
<td><code>enjoy leisure</code></td>
<td>여가를 즐기다</td>
</tr>
<tr>
<td><code>stand out</code></td>
<td>눈에 띄다</td>
</tr>
</tbody></table>
<hr>
<h4 id="재활용-독서-또한-준비를-해서-다시금--영어를-잘하고-싶다-">재활용 독서 또한 준비를 해서 다시금 ... 영어를 잘하고 싶다 .</h4>
<p>스크립트 따위는 없어도 잘하고 싶다 . </p>
<hr>
<p>여러분 저 됐어요 !!! 
IH 됐어요!!!!! </p>
<p>ㅎㅎㅎ 역대급 폭망 스피치인줄 알았으나 좋게 봐주셨나 봅니다 ^^ 이렇게 된거 AL까지 슈웃~~</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 20주차 기록]]></title>
            <link>https://velog.io/@physical-100/VEDA-20%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@physical-100/VEDA-20%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Sun, 15 Mar 2026 17:10:04 GMT</pubDate>
            <description><![CDATA[<p>사실 이번 주차에는 별로 쓸 수 있는 내용이 별로 없습니다.</p>
<p>이슈를 겪으며 별로 구현한 내용이 없었습니다. </p>
<p>카메라상의 좌표와 현실 세계의 좌표를 매핑하기 . </p>
<p>이것은 생각보다 어려운 난제였습니다. </p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/3e26bf2e-f93b-4ad7-8667-ee03bd773fdf/image.png" alt=""></p>
<h3 id="1pid-제어">1.PID 제어</h3>
<p>화면상에서 탐지된 레이저 좌표와 객체간의 오차를 피드백으로 P,I, D gain의 최적값을 찾기 위해 노력해보았습니다. </p>
<p>Camera(Hanwha Vision) &lt;-&gt; host(Ubuntu) &lt;-&gt; STM32(ESP)
의 무선 통신 속에서 두 가지 문제가 있었습니다. </p>
<ol>
<li><p>카메라 Delay :  FHD 영상의 인코딩 및 디코딩 과정에서 발생하는 300ms 정도의 딜레이는 Gstreamer pipeline 혹은 설정 변경을 통해 줄일 수는 없었습니다. 실제로 레이저 on 이후 카메라가 탐지되어 다시금 STM으로 넘어오기까지의 시간이 평균적으로 320ms 정도 소요되었습니다. 
해당 Delay는 PID 제어에서 오차를 누적시켜 Overshoot를 일으켰습니다.
그렇지만 overshoot를 잡기 위해 P를 낮추는 경우 실제 객체를 따라가기는 하지만 실시간으로 추적하기에는 어려움이 있었습니다 .</p>
</li>
<li><p>레이저 탐지 정확도 
카메라의 영상을 수신하여 해당 영상에서 레이저 포인트만을 정확하게 찾아내는 것 또한 한계가 있었습니다. 비교적 근거리에서는 레이저 포인터만을 분리할 수 있었습니다.  HSV 색변환을 통한 색, 밝기 기반의 탐지가 가능했지만 실제 환경처럼 카메라를 세팅하고 레이저를 포인팅 하였을 때는 실제 영상에서 차지하는 픽셀이 너무 적을 뿐만 아니라 색상 정보도 기대한 값(빨강)으로 들어오지 않았습니다. </p>
</li>
</ol>
<h3 id="2-카메라-캘리브레이션">2. 카메라 캘리브레이션</h3>
<p>인턴쉽에서 카메라 캘리브레이션을 진행해본 경험을 바탕으로 단안 거리 추정을 위한 카메라 캘리브레이션을 진행해보았습니다. </p>
<p>Python , OpenCV를 이용하여 직접 구현할 수도 있었겠지만 <code>MATLAB</code>을
이용해보았습니다. 살짝 궁금하기도 했꺼든요
<img src="https://velog.velcdn.com/images/physical-100/post/f001c711-12ff-4138-b154-aa5e1e60fca2/image.png" alt="">
checkerboard를 출력하고 내부 파라미터를 측정했습니다.<br>그 결과 평균 오차가 0.3 이하로 비교적 수월하게 얻어낼 수 있었습니다. 
(간편하게 사용할 수 있는 유용한 도구라고 느껴졌습니다. ). </p>
<p>이후 내부 파라미터를 가지고 외부 파라미터를 구해보았습니다. </p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/6d9e3e50-334d-49c2-b9f6-d87fc03f0f1f/image.png" alt=""></p>
<p>기존에 사용했던 체커보드의 경우 사이즈가 작아져 바닥 평면에서는 체커보드로 인식되지 않아 A2크기의 체커보드를 새로 출력후 한번 실제 거리를 측정해보았습니다. </p>
<p>화면상의 원점 좌표가 실제 거리는 <u>3940mm </u>이지만 파라미터 기반 추정 거리는 <u>4554mm </u> 로 측정 되었고 오차가 약 12%에 달했습니다. </p>
<p>상당한 좌절감 .</p>
<h3 id="3-homography-기반-좌표-추정">3. Homography 기반 좌표 추정</h3>
<p><img src="https://velog.velcdn.com/images/physical-100/post/451126e7-deca-4403-b42a-886ac8185f18/image.png" alt=""></p>
<h4 id="edge-기반-화면-매핑">edge 기반 화면 매핑</h4>
<p>point를 4개 지정후 실제 좌표 매핑 → <strong><code>itgeotrans</code> 으로 Z plane 좌표 변환.</strong></p>
<p>앞서 취득한 내부 파라미터를 가지고  영상을 undistort()해서 z-plane ==0 의 평면을 지정하고 이를 실제 좌표와 매칭합니다. </p>
<p>이는 이동하는 사람의 발(바운딩 박스 최하단)은 항상 바닥에 있다는 가정에서 시작한 접근법입니다. </p>
<p>실제로도 여지껏 했던 시도중 가장 적은 오차를 보였고 실제 레이저를 쏴보면서 테스트를 하려고 했습니다 .</p>
<p>그래서 영상 &lt;-&gt; 객체 &lt;-&gt; 레이저 제어를 통해 오차를 확인해보려던 찰나 또 한가지의 문제점을 발견했습니다 .</p>
<p>테스트 환경 내에 많은 책상과 모니터들로 인해 사람의 하반신이 가려지게 된다면 실제로 바운딩 박스의 크기가 제한되어 실제 발의 위치를 측정할 수 없다는 문제를 발견했습니다 .</p>
<h3 id="4-백래시">4. 백래시</h3>
<blockquote>
<p>기계적 백래시 </p>
</blockquote>
<p>실질적으로 오차를 확인하기 위해 수동으로 제어를 하던 중 현재 사용하고 있는 서보모터에 기계적 백래시가 있다는 것을 확인했습니다.</p>
<p>기계 시스템에서 백래시(Backlash)란, 서로 맞물린 두 부품 사이에 존재하는 유격(遊隙), 즉 의도하지 않은 자유 운동(free play)을 말합니다. 입력이 방향을 바꿀 때, 출력이 즉각 반응하지 않고 일정 구간 동안 &quot;헛도는&quot; 현상이 바로 백래시입니다.
<img src="https://velog.velcdn.com/images/physical-100/post/0dc2168a-a3c7-44d3-a92f-68c6bff3f898/image.png" alt=""></p>
<h4 id="발생-원인">발생 원인</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/2ef8f11d-3266-49d3-91c3-0212a15b82de/image.png" alt=""></p>
<p>뭐. 클로드한테 물어보니 이런 이유가 있다고 하네요...</p>
<p>해당 문제가 왜 프로젝트에서 치명적인지는 실제로 값을 조정하면서 확인할 수 있었습니다. </p>
<p>실제로 동일한 pwm 값을 pan, tilt에 전달했을 때 매번 출력되는 각도가 달라졌습니다. </p>
<p>특히나 진행 중이던 방향과 반대되는 방향의 값을 주었을 때 차이는 더욱 커졌습니다 ..</p>
<hr>
<h3 id="피드백-및-구현-계획">피드백 및 구현 계획</h3>
<p>위에서 언급된 이슈들을 각각 확인하다보니 성과가 없이 한 주가 지나갔습니다.
engineer의 입장에서 문제를 해결하기 위해 고민하다 보니 이렇다 할 결과가 없이 한주가 흘러가는 것이 너무나 속상하기도한 한 주였습니다..</p>
<h4 id="해결-방안">해결 방안</h4>
<ol>
<li>좌표 변환
z-plane = 1300 지점에서의 z 평면을 한번 Homography로 좌표를 구하고 사람이 가려지지 않는 범위 내에서 최적의 값을 찾아야합니다. 
<span style ="color:orange">    - 발생가능한 추가적 문제 </span>
<code>사람마다 키와 넓이가 달라 사람의 1300 위치를 어떻게 특정할 것인가 ?</code>
하는 문제가 남아있습니다. 이를 해결하기 위해 탐지되는 얼굴과 상체의 비율을 통해 포인트를 찾아나갈 계획입니다. </li>
<li>기계적 백래시<br> 이는 조금 더 방안을 구체화 해봐야할 것 같습니다. </li>
</ol>
<h4 id="이제-어느덧-2주-조금을-남겨두고-있습니다">이제 어느덧 2주 조금을 남겨두고 있습니다..</h4>
<p>빠른 시일 내에 데모 버전을 만들기 위해 21주차는 조금더 열심히 분발해보도록 하겠습니다.  VEDA 파이탱~</p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/5486877c-34fe-4a18-a2a8-cfd979c78b7c/image.JPG" alt=""></p>
<p>Embedded not Easy. </p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/701f3999-cde5-4086-9746-f5e2997df8ee/image.JPG" alt=""></p>
<p>항상 뒷통수를 조심할 것. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 1주차 ]]></title>
            <link>https://velog.io/@physical-100/VEDA-1%EC%A3%BC%EC%B0%A8</link>
            <guid>https://velog.io/@physical-100/VEDA-1%EC%A3%BC%EC%B0%A8</guid>
            <pubDate>Tue, 10 Mar 2026 00:37:07 GMT</pubDate>
            <description><![CDATA[<h3 id="veda-합류-이야기">VEDA 합류 이야기</h3>
<p>인턴 과정을 진행하며 임베디드 시스템에 벽을 느끼고 관련된 교육을 찾다 VEDA에 지원하게 되었다..
컴퓨터 비전을 활용한 프로젝트를 진행해오기도 했고 직무 관련 지식을 좀 더 쌓을 수 있다는 생각으로 지원하였.. .
사실상 VEDA 수료를 앞두고 쓰려니 처음에 지원하던 그 마음이 잘 기억나지는 않지만 암튼 ..</p>
<p>크흠 .. 임베디드에 대한 열정과 해왔던 개발 경력을 위주로 지원서를 마무리했다 . </p>
<h3 id="코딩-테스트">코딩 테스트</h3>
<p>비교적 간단하다는 후기를 듣고 파이썬 및 c++로 코딩 역량 검사 준비를 하였다 
python, c++, c 3가지 언어 중 하나를 선택할 수 있었고 코드의 빈 칸을 채우는 형식으로 문제가 출제되었다. 파이썬으로 개발을 해왔었지만 class 선언 등 내가 코딩 테스트를 위해 작성하는 코드와는 살짝 달라서 그냥 c++로 제출을 했다 
정확히 기억은 나지 않지만 이진 검색 , 정렬 , 스택 구현과 같이 3문제가 출제되었다..</p>
<p>2025.9월 즈음의 기억이니 정확하지는 않다...</p>
<p>이 할비는 조금이라도 도움이 되기를 바라며 😿
알고리즘 준비를 해왔던 사람들이라면 어렵지 않게 통과할 수 있을 정도의 난이도였고 역량 검사 전날 
<u>grok</u>과 알고리즘 카테고리 별 간단한 문제 빈 칸 문제를 내달라했던게 아주 효과적이었던 것 같다. </p>
<h3 id="면접-후기">면접 후기</h3>
<p>면접은 내가 잘하는 것 보다는 의욕을 어필했다 왜 이 교육과정에 지원하게 되었는지 . 그리고 해왔던 활동들이 교육과정과는 조금 다른데 괜찮은지 등에 대한 질문이 이어졌고 면접관 분들이 편안하게 질문해주셔서 나도 있는 그대로의 생각을 말할 수 있었다 . </p>
<h3 id="1주차-학습">1주차 학습</h3>
<h4 id="c-언어-기초">C 언어 기초</h4>
<p>👨‍💻 [C언어] &quot;이게 왜 안 돼?&quot; </p>
<h4 id="배열-vs-포인터-완벽-정리">배열 vs 포인터 완벽 정리</h4>
<p><em>배열 이름은 배열의 시작 주소를 가리키는 &#39;상수 포인터&#39;</em> 에 가깝습니다.</p>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>배열 (Array)</strong></th>
<th><strong>포인터 (Pointer)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>본질</strong></td>
<td>데이터를 저장하는 <strong>공간 자체</strong></td>
<td>주소값을 저장하는 <strong>변수</strong></td>
</tr>
<tr>
<td><strong>크기 (<code>sizeof</code>)</strong></td>
<td>배열 전체 크기 (요소 개수 × 자료형 크기)</td>
<td>포인터 변수 자체의 크기 (4 or 8바이트)</td>
</tr>
<tr>
<td><strong>값 변경</strong></td>
<td>배열 이름에 다른 주소를 대입 불가 (상수)</td>
<td>다른 주소값을 대입하여 가리키는 대상 변경 가능</td>
</tr>
<tr>
<td><strong>선언</strong></td>
<td><code>int arr[5];</code> (메모리 20바이트 할당)</td>
<td><code>int *ptr;</code> (주소 저장용 메모리만 할당)</td>
</tr>
</tbody></table>
<h4 id="💡-핵심-뽀인터">💡 핵심 뽀인터!</h4>
<p>배열은 집 그 자체이고, 포인터는 그 집의 주소가 적힌 쪽지입니다.</p>
<p>arr[i]와 *(ptr + i)는 문법적으로 동일하게 동작하지만, <code>arr = ptr</code>처럼 배열의 이름에 새로운 주소를 할당하려고 하면 컴파일 에러가 발생합니다. 배열 이름은 이사가 안 되는 붙박이 주소이기 때문이죠.</p>
<h4 id="⚠️형식-지정자-주의점">⚠️형식 지정자 주의점</h4>
<p>printf나 scanf를 쓸 때 우리를 괴롭히는 형식 지정자들. 
특히 실수하기 쉬운 포인트만 모았습니다.</p>
<p>① <code>%f</code> vs <code>%lf</code>의 이중성
printf 할 때: float와 double 모두 %f로 출력해도 무방합니다. (가변 인자 프로모션 때문)</p>
<p>scanf 할 때 (중요!): double형은 반드시 <strong><code>%lf</code></strong>를 써야 합니다. <code>%f</code>를 쓰면 값이 깨지거나 입력되지 않습니다.</p>
<p>② <code>%d</code>와 <code>%u</code>의 부호 전쟁
int 범위를 넘어가는 큰 수를 다룰 때 <code>%d</code>를 쓰면 갑자기 음수가 출력되는 마법을 볼 수 있습니다. 부호 없는 정수는 꼭 <strong><code>%u</code></strong>를 쓰세요.</p>
<p>③ 문자열 <code>%s</code>와 공백의 늪
scanf(&quot;%s&quot;, str)는 <strong>공백(스페이스, 탭, 엔터)</strong>을 만나면 입력을 멈춥니다. &quot;Hello World&quot;를 입력해도 &quot;Hello&quot;만 저장되죠. 공백을 포함하고 싶다면 fgets()를 사용하는 것이 정신 건강에 이롭습니다.</p>
<p>④ <code>%c</code> 앞에 남겨진 &#39;엔터&#39;의 유령
<code>scanf(&quot;%d&quot;, &amp;num);</code> 이후 바로 <code>scanf(&quot;%c&quot;, &amp;ch);</code>를 쓰면, 숫자 입력 후 친 <strong>엔터(&#39;\n&#39;)</strong>가 문자로 인식되어 버립니다. 이럴 땐 <code>scanf(&quot; %c&quot;, &amp;ch);</code> (한 칸 띄우기)로 버퍼를 비워줘야 합니다.</p>
<h3 id="한화비전-vision-edge-device-academy-파이탱">한화비전 Vision Edge Device Academy 파이탱~</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[ALLDAY Project OPIC  준비-1]]></title>
            <link>https://velog.io/@physical-100/ALLDAY-Project-OPIC-%EC%A4%80%EB%B9%84-1</link>
            <guid>https://velog.io/@physical-100/ALLDAY-Project-OPIC-%EC%A4%80%EB%B9%84-1</guid>
            <pubDate>Sun, 08 Mar 2026 17:18:56 GMT</pubDate>
            <description><![CDATA[<p> 공채 시즌이 다가오고 영어 어학 성적이 만료 되어감에 있어 급하게 opic 응시 일정을 잡았다 
 D-7  2026.03.15 더 이상은 물러날 곳이 없으니 준비를 해보도록 하자.</p>
<p> 질문은 동아리 회장이 고른 것을 그대로 따라가다가 몇 개만 조금 바꿔보겠다.. ..
 왜냐? 그간 그가 준비한 질문을  토대로 speaking 시간을 가졌기에 ... </p>
<p> 가보즈앗<del>!</del>! </p>
<h2 id="survey-check">Survey Check</h2>
<ol>
<li><p>일 경험 없음</p>
<ol start="2">
<li>학생 아님 / 수강 후 5년 이상 지남</li>
<li>개인 주택이나 아파트에 홀로 거주</li>
</ol>
<p><img src="https://velog.velcdn.com/images/physical-100/post/a6bdb2b4-9365-4ad5-8d60-7c1dbc14545b/image.png" alt=""></p>
<ol start="4">
<li>게임 하기 / 스포츠 관람 / 영화 보기 / 카페 or 커피 전문점 가기 
<img src="https://velog.velcdn.com/images/physical-100/post/b90989f9-cfaa-422b-ba51-00b0013109d0/image.png" alt=""></li>
<li>독서 / 음악 감상하기
<img src="https://velog.velcdn.com/images/physical-100/post/0fb397b8-a685-499f-8e0e-eba9e63a993f/image.png" alt=""></li>
<li>걷기 / 조깅 / 헬스 
<img src="https://velog.velcdn.com/images/physical-100/post/7880216b-053f-44d1-95b6-364d95f42a06/image.png" alt=""></li>
<li>집에서 보내는 휴가/ 해외 여행/ 국내 여행 </li>
</ol>
</li>
</ol>
<hr>
<h3 id="난이도-선정"><strong>난이도 선정</strong></h3>
<p>5-5 or 6-6 ? 이거는 조금 더 찾아 보자 .</p>
<h2 id="스크립트">스크립트</h2>
<ul>
<li><strong>자기 소개</strong></li>
</ul>
<h3 id="서베이-관련-질문">서베이 관련 질문</h3>
<ul>
<li><strong>집 (주택이나 아파트에 홀로 거주)</strong><ul>
<li>Tell me about the place where you live. What does it look like?</li>
</ul>
</li>
</ul>
<pre><code>- &quot;Has there been any change you made to your home in the past few years? Maybe you bought new furniture or redecorated a room. Tell me about that change.&quot;</code></pre><ul>
<li>&quot;Tell me about a problem you experienced at your home. Maybe something was broken or there was a leak. How did you handle that situation?&quot;</li>
</ul>
<ul>
<li><p><strong>집안일</strong></p>
<ul>
<li><p><em>What kinds of household chores do you usually do at home?</em></p>
</li>
<li><p><em>How often do you do household chores?</em></p>
</li>
<li><p><em>How have the household chores you do changed from when you were a child to now? What were your responsibilities back then and what are they now?</em></p>
</li>
<li><p><em>Who is responsible for the household chores in your family? How do you divide the work among family members? Tell me in detail.</em></p>
<ul>
<li>혼자 거주 :  <strong>&quot;Since I live alone, I&#39;m responsible for everything from A to Z.&quot;</strong></li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><p><strong>스포츠 관람</strong></p>
<ul>
<li><p>What sports do you like to watch? How did you become interested in them?</p>
</li>
<li><p>Describe a memorable sporting event you watched. What made it so special?</p>
</li>
<li><p>Do you prefer watching sports at home or at a stadium? Why?</p>
</li>
</ul>
</li>
<li><p><strong>영화 보기</strong></p>
<ul>
<li><em>What kind of movies do you enjoy watching? Why do you like them?</em></li>
</ul>
</li>
</ul>
<pre><code>- *Tell me about the last movie you watched. What was it about and what did you think of it?*</code></pre><ul>
<li><p><strong>게임 하기</strong></p>
<ul>
<li><em>What kind of devices do you use when playing games? Tell me about your gaming setup at home or where you usually go to play games</em></li>
<li><em>How has your interest in games changed over the years? What kind of games did you play in the past and how are they different from the ones you play now.</em></li>
</ul>
</li>
<li><p><strong>카페/커피 전문점 가기</strong></p>
<ul>
<li><em>Tell me about your favorite coffee shop. What does it look like and what makes it special compared to other cafes?</em> [자주 가는 커피숍 묘사] <ul>
<li>The cafe has a minimalist interior and the lighting is very soothing. -&gt; 유용한 표현 <ul>
<li><span style ="color:red">soothing : 편안한 </span></li>
</ul>
</li>
</ul>
</li>
<li><em>Tell me about a memorable experience you had at a coffee shop. Perhaps something unexpected happened. What was it and why was it so memorable?</em></li>
</ul>
</li>
<li><p><strong>음악 감상하기</strong></p>
<ul>
<li>What role does music play in your daily life?</li>
</ul>
</li>
</ul>
<pre><code>- Tell me about a concert or live performance you attended that left a strong impression on you.</code></pre><ul>
<li><strong>독서</strong><ul>
<li>What kinds of books do you like to read? Why do you enjoy them?</li>
</ul>
</li>
</ul>
<pre><code>- Can you tell me about a book that had a significant impact on you?


- How have your reading habits changed over the years?</code></pre><ul>
<li><p>** 걷기/조깅**</p>
<ul>
<li><em>Where do you usually go for a walk or jog? Tell me about your favorite route or park in detail. What makes that place special?</em></li>
<li><em>How has your walking or jogging habit changed over the years? When did you first start this activity, and how is your routine different now compared to the past?</em></li>
</ul>
</li>
<li><p>** 헬스 **</p>
<ul>
<li><em>Tell me about the gym you go to. What does it look like? What kind of equipment do they have, and what is your typical workout routine there?</em></li>
<li><em>Tell me about a memorable or unexpected thing that happened while you were exercising at the gym. Who were you with and what happened? How did you deal with the situation?</em></li>
</ul>
</li>
</ul>
<hr>
<ul>
<li><strong>집에서 보내는 휴가</strong><ul>
<li>How do you typically spend your vacations at home?</li>
</ul>
</li>
</ul>
<pre><code>- Some people think staying home for vacation is boring. What would you say to them?</code></pre><ul>
<li><strong>해외 여행</strong><ul>
<li><em>Tell me about a country or a city you enjoy visiting for your vacations. What does it look like? What are some things you like to do there?</em></li>
<li><em>Tell me about the very first trip you took abroad. Where did you go and who were you with? How did you feel about that trip at that time?</em><ul>
<li>&quot;모든 것이 낯설고 신기했다(Everything was new and fascinating)&quot;</li>
<li>&quot;공항에 도착했을 때 정말 설레었다(I was so thrilled when I arrived at the airport)&quot;</li>
</ul>
</li>
<li><em>Unexpected things can happen during a trip. Tell me about a time you experienced a problem while traveling abroad. What was the problem and how did you resolve the situation?</em></li>
</ul>
</li>
</ul>
<hr>
<h3 id="롤-플레잉"><strong>롤 플레잉</strong></h3>
<ul>
<li>I&#39;m sorry, but I&#39;m calling because there&#39;s a problem with your apartment. There&#39;s been a water leak reported from your unit. Can you tell me what happened?</li>
</ul>
<ol>
<li>[거주지/집안일 관련] - 가구점 방문 및 배송 문제</li>
</ol>
<ul>
<li><p>11번 (질문하기): 당신은 새로 이사한 집을 꾸미기 위해 가구점에 전화를 걸었습니다. 점원에게 가구의 종류, 가격, 배송 가능 여부에 대해 3~4가지 질문을 하세요.</p>
</li>
<li><p>12번 (문제 해결): 가구점에서 배송받은 가구가 당신이 주문한 것과 다르거나 손상된 상태로 도착했습니다. 점원에게 전화를 걸어 상황을 설명하고, 교환이나 환불 중 하나를 선택해 해결책을 제시하세요.</p>
</li>
</ul>
<ol start="2">
<li>[커피숍 관련] - 친구와 약속 및 장소 변경</li>
</ol>
<ul>
<li><p>11번 (질문하기): 당신은 친구와 커피숍에서 만나기로 했습니다. 친구에게 전화를 걸어 커피숍의 위치, 메뉴, 주변 주차 공간 등에 대해 3~4가지 질문을 하세요.</p>
</li>
<li><p>12번 (문제 해결): 약속 장소인 커피숍에 도착했는데, 사람이 너무 많아 자리가 없습니다. 친구에게 전화를 걸어 이 상황을 설명하고, 근처의 다른 카페나 장소로 옮기자고 2~3가지 대안을 제시하세요.</p>
</li>
</ul>
<ol start="3">
<li>[게임 관련] - PC방/게임기 대여 및 기술적 문제</li>
</ol>
<ul>
<li><p>11번 (질문하기): 친구와 함께 게임을 하기 위해 근처 PC방에 전화를 걸거나, 게임기를 대여하려고 합니다. 요금, 사양, 대여 가능 여부에 대해 3~4가지 질문을 하세요.</p>
</li>
<li><p>12번 (문제 해결): 친구와 게임을 시작하려는데, 컴퓨터가 켜지지 않거나 게임기에 오류가 발생했습니다. 직원에게 상황을 설명하고, 자리를 옮기거나 환불을 요청하는 등 해결책을 제시하세요.</p>
</li>
</ul>
<ol start="4">
<li>[해외 여행 관련] - 여행사 예약 및 비행기 결항</li>
</ol>
<ul>
<li><p>11번 (질문하기): 당신은 해외 여행을 계획하고 여행사에 전화를 걸었습니다. 여행 패키지 구성, 숙소 등급, 비자 필요 여부 등에 대해 3~4가지 질문을 하세요.</p>
</li>
<li><p>11번: 프런트 데스크에 필요한 물품 요청하기 (질문하기)
&quot;당신은 지금 막 호텔에 체크인했습니다.부족한 물품과 서비스에 대해 프런트에 3~4가지 질문을 하세요.&quot;</p>
<ul>
<li>용어 <ul>
<li>complimentary :  무료로 제공되는 
  <code>Is the breakfast complimentary?</code></li>
</ul>
</li>
</ul>
</li>
<li><p>12번 (문제 해결): 여행 당일, 갑작스러운 기상 악화로 비행기 편이 취소되었습니다. 여행사에 전화를 걸어 일정을 변경하거나 숙소 예약을 취소하는 등 급한 대책을 마련하세요.</p>
</li>
<li><p>12번: 숙소 시설 문제 해결하기 (문제 해결)
방에 들어와서 쉬려고 하는데, 시설에 심각한 문제가 있다는 것을 발견했습니다. 에어컨이 작동하지 않거나 따뜻한 물이 나오지 않는 상황입니다. 프런트 데스크에 전화를 걸어 상황을 설명하고, 수리나 방 교체 등의 해결책 2~3가지를 제시.</p>
</li>
</ul>
<ol start="5">
<li>[헬스장 관련] - 정보 문의 및 환불<ul>
<li>헬스장에 전화해서 정보 문의하기 (질문하기)
&quot;당신은 새로 헬스장에 등록하거나 기존 멤버십을 연장하려고 합니다. 헬스장에 전화를 걸어 등록 비용, 운영 시간, 시설 등 궁금한 사항에 대해 3~4가지 질문을 하세요.&quot;</li>
<li>헬스장에 등록한 지 얼마 되지 않아 갑자기 출장을 가야 하거나 다리를 다쳐서 한동안 운동을 할 수 없게 되었습니다. 헬스장에 전화를 걸어 상황을 설명하고, 멤버십 기간을 일시 정지(Hold)하거나 환불받을 수 있는지 2~3가지 대안을 제시하며 해결하세요</li>
</ul>
</li>
</ol>
<hr>
<h3 id="돌발-질문"><strong>돌발 질문</strong></h3>
<ul>
<li><p>You indicated that you like watching movies. How has watching movies at home changed compared to 10 years ago?</p>
</li>
<li><p>Your friend wants to start gaming but doesn&#39;t know where to begin. What advice would you give them?</p>
</li>
<li><p>Compare reading books to watching movies. Which do you prefer and why?</p>
<ol>
<li>[기술의 진보와 사회 문제] - Technology &amp; Security
&quot;Technology has changed the way we live. However, there are many concerns about privacy and security issues these days. Tell me about a specific problem related to technology that you&#39;ve heard in the news recently. What is your opinion on that?&quot;</li>
</ol>
</li>
</ul>
<ol start="2">
<li><p>[명절 및 기념일의 변화] - Holidays &amp; Traditions
&quot;Compare how people in your country used to celebrate holidays in the past with how they celebrate them today. What are some significant changes you&#39;ve noticed? Why do you think these changes occurred?&quot;</p>
</li>
<li><p>[산업의 변화] - Changes in an Industry
&quot;The way people get their groceries or household items has changed significantly over the past decade. Tell me about the changes in the retail industry in your country. How does it affect our daily lives?&quot;</p>
</li>
<li><p>[환경 문제와 개인의 노력] - Environmental Issues
&quot;Environmental issues such as climate change and plastic pollution are becoming more serious. What are some specific environmental problems in your country? What is the government doing about it, and what are you doing personally?&quot;</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 19주차 기록]]></title>
            <link>https://velog.io/@physical-100/VEDA-19%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@physical-100/VEDA-19%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Sun, 08 Mar 2026 16:32:30 GMT</pubDate>
            <description><![CDATA[<p>19주차에는 PID제어와 다투는 한 주였습니다. 
지난 주에는 Laser 하드웨어 연결 구성,그리고 노이즈 해결 및 제어 기초 코드를 작성하였는데요 금주에는 영상에서의 레이저 포인트를 바탕으로 객체를 쫓아갈 수 있도록 하는 PID 제어를 구현했습니다 .</p>
<p>하지만 너무나도 쉽지 않은 task에 두손 두발을 다 들어버렸다는 ....</p>
<p>그럼 바로 고군분투 이야기를 찾아가보도록 하겠습니다.!!!</p>
<h2 id="pid-제어란-">PID 제어란 ?</h2>
<p>그러면 PID 제어가 무엇인지 한번 Gemini에게 물어봅시다 !</p>
<p><strong>PID 제어는 제어 대상의 출력값을 목표값과 일치시키기 위해 사용하는 가장 대표적인 피드백 제어 알고리즘입니다.</strong></p>
<ol>
<li><code>P (Proportional)</code>: 비례 제어
&quot;현재의 오차에 집중하자&quot;</li>
</ol>
<p>비례 제어는 현재 오차($e(t)$)의 크기에 비례하여 제어량을 조절합니다. 오차가 크면 크게 움직이고, 작으면 작게 움직이는 가장 직관적인 방식입니다.</p>
<ul>
<li>특징: 오차에 즉각적으로 반응합니다.</li>
<li>한계: <strong>잔류 편차(Offset)</strong>가 발생합니다. 목표치에 가까워질수록 제어량이 너무 작아져서, 완전히 목표값에 도달하지 못하고 일정한 오차를 남긴 채 평형을 이뤄버리는 현상입니다.</li>
</ul>
<ol start="2">
<li><code>I (Integral)</code>: 적분 제어
&quot;누적된 과거의 오차를 해결하자&quot;
P 제어에서 해결하지 못한 &#39;잔류 편차&#39;를 없애기 위해 사용합니다. 과거부터 쌓여온 오차의 합계를 계산하여 제어량에 반영합니다.</li>
</ol>
<ul>
<li>특징: 아주 미세하게 남아있는 오차도 시간이 지나면 누적되어 제어량을 키우므로, 결국 목표값에 정확히 도달하게 만듭니다.</li>
<li>한계: 오차가 계속 쌓이다 보니 반응이 다소 느려지거나, 목표치를 지나쳐 버리는 <strong>오버슈트(Overshoot)</strong>가 발생할 수 있습니다.</li>
</ul>
<ol start="3">
<li><code>D (Derivative)</code>: 미분 제어
&quot;미래의 오차를 예측하여 대비하자&quot;
오차가 변화하는 속도(기울기)를 보고 급격한 변화를 억제합니다. 자동차 브레이크처럼 급하게 목표치에 접근할 때 속도를 줄여주는 &#39;댐퍼&#39; 역할을 합니다.</li>
</ol>
<ul>
<li>특징: 오버슈트를 줄여주고 시스템의 안정성을 높여줍니다.</li>
<li>한계: 노이즈(갑작스러운 신호 변화)에 매우 민감하게 반응하여 시스템이 떨리는 등 불안정해질 수 있습니다.</li>
</ul>
<h4 id="비교">비교</h4>
<table>
<thead>
<tr>
<th><strong>항목</strong></th>
<th><strong>명칭</strong></th>
<th><strong>중심 관점</strong></th>
<th><strong>주요 역할</strong></th>
<th><strong>부작용</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>P</strong></td>
<td>비례</td>
<td><strong>현재</strong></td>
<td>빠른 응답성 확보</td>
<td>잔류 편차 발생</td>
</tr>
<tr>
<td><strong>I</strong></td>
<td>적분</td>
<td><strong>과거</strong></td>
<td>잔류 편차 제거</td>
<td>오버슈트 발생 가능</td>
</tr>
<tr>
<td><strong>D</strong></td>
<td>미분</td>
<td><strong>미래</strong></td>
<td>오버슈트 억제 (안정화)</td>
<td>노이즈에 민감함</td>
</tr>
</tbody></table>
<hr>
<p>앞서 카메라 영상에서 레이저 포인터를 추출하였듯이 목표 객체와 픽셀간의 오차를 이용하여 제어를 시도하는 P제어 먼저 시도를 했습니다. </p>
<p>초기에는 영상 자체에서 오차를 구해 PID 항을 계산해 pwm 값만 esp8266으로 전송했지만 os 내부에서의 시간 엄격성과 계산량 분산을 위해 STM으로 PID 연산 loop를 넘겼습니다 .</p>
<hr>
<h3 id="위치형-vs-증분형-pid">위치형 VS 증분형 PID</h3>
<h4 id="1-두-방식의-가장-큰-차이-한-줄-요약">1. 두 방식의 가장 큰 차이 한 줄 요약</h4>
<ul>
<li><p>위치형 PID
→ 매번 “현재 오차에 비례해서 중립 위치에서 얼마나 떨어져야 하는지”를 직접 계산
<code>출력 = 중립값 + Kp×오차 + Ki×누적오차 + Kd×오차변화율</code></p>
</li>
<li><p>증분형 PID
→ 매번 “이번에 얼마나 더 움직여야 할지(변화량)”만 계산해서 이전 출력에 더함
이번 변화량 = Kp×오차 + Ki×오차 + Kd×(오차-이전오차)
<code>출력 = 이전 출력 + 이번 변화량</code></p>
</li>
</ul>
<h4 id="2-증분형-pid를-썼을-때-제가-겪은-문제들">2. 증분형 PID를 썼을 때 제가 겪은 문제들</h4>
<p>프로젝트 초반에 증분형으로 구현했을 때 로그는 거의 이런 패턴이었습니다.</p>
<pre><code class="language-text">ex: 45.0 → out: 1430 → 1450 → 1470 → 1490 → … → 2200 (끝까지 감)
ex: -120.0 → out: 1250 → 1220 → 1190 → … → 800 (끝까지 감)</code></pre>
<ul>
<li>오차가 같은 방향으로 오래 지속되면 PWM이 계속 한쪽으로만 쌓여서 범위 끝(800 or 2200)에 고정됨</li>
<li>목표에 도착했는데도 오차가 조금 남아 있으면 계속 미세하게 더 움직이려고 해서 떨림 발생</li>
<li>오차가 갑자기 반대 방향으로 바뀌면 이전 누적분 때문에 반응이 매우 느림 (한쪽으로 치우친 상태에서 출발)</li>
</ul>
<h4 id="3-위치형을-선택한-결정적-이유-2가지">3. 위치형을 선택한 결정적 이유 2가지</h4>
<ol>
<li>서보는 절대 위치 제어 장치이기 때문
RC 서보는 본질적으로 “특정 PWM 값 = 특정 각도”라는 절대 위치 장치입니다.</li>
<li>오차가 갑자기 반대 방향으로 바뀌면 즉시 반응
 → 이전 누적값이 없기 때문에 바로 새로운 위치로 점프
 → 빠른 방향 전환 시 지연이 거의 없음</li>
</ol>
<h3 id="p-제어의-한계">P 제어의 한계</h3>
<pre><code>왔다 갔다 / 느린 추종 / 정확도 문제</code></pre><h4 id="1-오차가-클-때-발생하는-진동오버슈트-패턴">1. 오차가 클 때 발생하는 진동/오버슈트 패턴</h4>
<ul>
<li><strong>현상</strong>
오차가 크면 $K_p \cdot e$ 항이 커져서 PWM 변화량이 급격히 증가 → 목표 근처에 도달 → 오차 방향이 반전 → 다시 반대쪽으로 크게 움직임 → 반복</li>
</ul>
<blockquote>
<p>기본 위치형 PID 출력</p>
<p>$u(k) = u_{\text{center}} + K_p \cdot e(k) + K_i \cdot \sum e(k) \cdot \Delta t + K_d \cdot \frac{e(k) - e(k-1)}{\Delta t}$</p>
</blockquote>
<ul>
<li>오차 $∣e(k)∣$가 크면 → $Kp⋅e(k)$가 매우 커짐
→ 한 번에 PWM이 50~100us 이상 변화 → 서보가 목표를 지나침 (overshoot)</li>
<li>지나친 후 오차가 반대 부호로 바뀌면 → 이번에는 반대 방향으로 큰 보정
→ 다시 지나침 → <strong>헌팅(좌우 진동)</strong> 발생</li>
</ul>
<p><strong>주요 원인</strong></p>
<ul>
<li>$K_p$ 가 너무 큼 → 초기 응답 과도</li>
<li>$K_d$가 없거나 작음 → 변화율 억제 부족</li>
<li>서보 관성 + 백래시 + 카메라 지연 → 실제 도착 시 오차가 과다 보정됨</li>
</ul>
<h3 id="2-작은-오차에서-발생하는-정특성-오차-steady-state-error">2. 작은 오차에서 발생하는 정특성 오차 (steady-state error)</h3>
<p><strong>현상</strong>
오차가 5~20px 정도로 작아지면 PWM 변화가 거의 없어서 항상 그 오차를 남긴 채 멈춤</p>
<blockquote>
<p>정상상태(steady-state)에서 오차가 일정
$e(∞)=상수⇒dedt=0,∑e=일정$</p>
</blockquote>
<blockquote>
<p>위치형 PID의 정상상태 출력:
$u(∞)=ucenter+Kp⋅e(∞)+Ki⋅∑e(∞)$</p>
</blockquote>
<ul>
<li>$K_i = 0$ 또는 매우 작을 때 → $u(∞)≈ucenter+Kp⋅e(∞)$
→ 작은 오차 e(∞)를 없애려면 Kp가 커야 하지만, Kp를 크게 하면 위 진동이 심해짐
→ 결국 <strong>작은 오차를 못 잡고 남김</strong> (정특성 오차 발생)</li>
</ul>
<p><strong>주요 원인</strong></p>
<ul>
<li>$K_i$ 부족 → 정상상태 오차 제거 불가</li>
<li>$K_p$를 크게 못 함 (진동 때문에)</li>
</ul>
<p><span style="color: orange"> 요런 문제를 가지고 있다 ...</span>
<img src="https://velog.velcdn.com/images/physical-100/post/cfbef047-99a5-408f-afc4-92b48f262c23/image.gif" alt=""></p>
<p>그래서 I와 D항을 추가하여 overshoot을 해결하면서 settle time을 줄이기 위해 P항을 증가시키며 실험적 결과를 얻어내려고 노력했다 . 
어쩌면 핑계일 수 있지만 음 P,I,D 최적의 값을 일일이 찾아내는 것은 유의미할지 모르지만 시간이 조금 부족하다고 느껴졌다.</p>
<p>그래서 우선은 라즈베리로 모터를 옮겼다. 😭😭
사용하는 servo motor는 절대적인 PWM 값으로 위치를 제어하기에 Raspi에서 수신하는 오차와 pwm값으로 최적의 P,I,D 계수를 찾기 위함이었다 . </p>
<hr>
<h3 id="raspi와-auto-tune-">Raspi와 Auto Tune ...</h3>
<blockquote>
<h4 id="pysysid"><code>pysysid</code></h4>
<p>“실제 로그 데이터(입력 PWM + 출력 오차)를 먹이면 시스템의 전달함수를 자동으로 추정해주고, 그 모델로 최적 PID 게인을 뽑아주는 Python 라이브러리”</p>
</blockquote>
<p><u>왜 이걸 쓰면 편한가? </u></p>
<p><strong>1. 로그만 주면 끝</strong>
STM32에서 찍은 PIDLOG (t, ex, out_x 등)를 txt로 떨구면 → pysysid가 자동으로 1차/2차 모델 fitting</p>
<p><strong>2. 전달함수(G(s))를 먼저 알아줌</strong>
실제 서보 + 카메라 + 지연까지 포함된 전체 플랜트의 K(게인)와 τ(시간상수)를 뽑아줌
→ “우리 시스템은 실제로 이런 응답을 하네”를 숫자로 알 수 있음</p>
<p><strong>3. 그 모델로 PID 자동 설계</strong>
<code>control.pidtune()</code>이나 <code>Ziegler-Nichols</code>, <code>pole placement</code> 등 여러 방법으로 Kp/Ki/Kd 후보를 바로 계산
→ “이론상 최적” 값이 뚝딱 나옴 (미세 조정은 필요)</p>
<p>이론 상 최적의 값이 뚝딱 나올 줄만 알았다 .</p>
<h4 id="span-stylecolor-red-issue--span"><span style="color: red"> ISSUE  </span></h4>
<ul>
<li><p><code>레이저 위치 값 오차 지연</code>
현재 레이저의 위치는 들어오는 영상에서 HSV 변환과 Masking, Morphology 연산을 거쳐 레이저 포인터를 탐지하고 3프레임 당 한번씩 ESP혹은 라즈베리파이 ethernet 통신이 이루어졌다. 통신 과정에서 발생하는 지연은 적을지라도 전체 영상 처리, 그리고 수신 및 연산 과정은 더 길어질 수 있다. </p>
</li>
<li><p>레이저 탐지 
  실시간 탐지 중에서도 레이저 포인터가 가끔 오탐지가 되는 경우가 생겼다
  이 때 갑자기 확 늘어난 오차가 전달되며이는 최적의 값을 찾는데 큰 noise가 되었다.. </p>
</li>
</ul>
<p>이런 연유로 Raspi-python 라이브러리를 활용한 최적값 탐지는 나에게 절망감을 선사했다. 동일한 환경을 구성하기 위해 wifi 연결부터 코드 이식까지 환경 구성에 하루를 소모했기 때문에 ..</p>
<p>log를 분석하며 제대로 된 값을 얻어낼 수 있었을 수도 있지만 우선은 앞으로 나아가는 길을 선택했다. PID 최적의 값을 얻어냈다면 어땠을까 하는 아쉬움을 남기며 기존의 P,I,D 값을 바탕으로 LUT를 만들었다 </p>
<h2 id="pid---lut">PID -&gt; LUT</h2>
<p>서보모터는 절대적인 pwm 값으로 각도가 결정된다. 
이를 활용하여 화면을 11X19개의 그리드로 나누고 각 그리드의 중앙값을 PID 제어를 통해 레이저로 Pointing 하는 자동화 코드를 완성했다 .</p>
<p>이 과정에서도 화면의 가장자리로 갈 수록 레이저 탐지 확률이 줄어들어 코드 수정을 몇번이나 반복했다 . </p>
<h3 id="데이터-흐름">데이터 흐름</h3>
<pre><code class="language-text">[RTSP/카메라] → rtsp_laser_demo (e_u, e_v stdout)
       ↓
  ubuntu_tcp_server (stdin → &quot;EX=float,EY=float\n&quot; TCP 전송)
       ↓
  라즈베리 파이 pid_pwm_agent.py (TCP 클라이언트, 50Hz PID → pwm0/pwm1)
       ↓
  GPIO12(pwm0)=X, GPIO13(pwm1)=Y → 서보/레이저 구동</code></pre>
<h4 id="자동-lut-수집-모드-autolut">자동 LUT 수집 모드 (AutoLUT)</h4>
<ul>
<li><p>Host: <code>rtsp_laser_demo --lut-auto</code></p>
<ul>
<li><p><strong>그리드 정의</strong></p>
<ul>
<li><code>LUT_GRID_ROWS = 11</code>, <code>LUT_GRID_COLS = 19</code></li>
<li>각 셀 중심을 하나의 LUT 포인트로 사용</li>
</ul>
</li>
<li><p><strong>AutoLutCalibrator</strong></p>
<ul>
<li>현재 셀 인덱스: <code>idx</code> → <code>(gr(), gc())</code></li>
<li>현재 셀 중심에 대응하는 <code>TargetROI</code> 생성:</li>
<li><code>currentTarget(W, H)</code> 에서 <code>(gc+0.5) * W/cols</code>, <code>(gr+0.5) * H/rows</code></li>
<li><strong>수렴 판정</strong>:<ul>
<li>조건: <code>|e_u|,|e_v| ≤ SETTLE_THRESH_PX</code> (기본 6px)</li>
<li>시간을 <code>settle_accum_s</code> 에 누적</li>
<li><code>SETTLE_TIME_SEC</code> (예: 3초) 이상이면 “수렴”으로 간주</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>PWM 요청 및 LUT 저장 흐름</strong></p>
</li>
</ul>
<ol>
<li>Host가 AutoLUT 모드에서, 특정 셀에 대해 수렴 조건 만족:<ul>
<li><code>lut.updateConvergence(e_u, e_v, dt)</code> 가 <code>true</code> 를 반환</li>
</ul>
</li>
<li>Host는 Raspi에 현재 PWM 요청:<ul>
<li><code>REQUEST_PWM,GR=X,GC=Y</code> 를 <code>stdout</code> 으로 송신</li>
</ul>
</li>
<li><code>ubuntu_tcp_server</code>:<ul>
<li><code>REQUEST_PWM,...</code> 라인은 가공 없이 TCP로 그대로 전달</li>
</ul>
</li>
<li>Raspi <code>pid_pwm_agent.py</code>:<ul>
<li><code>recv_loop</code> 에서 <code>REQUEST_PWM_RE</code> 로 매치</li>
<li><code>shared.last_ux_us</code>, <code>shared.last_uy_us</code> 를 읽어</li>
<li><code>PAN=xxxx,TILT=yyyy</code> 형태로 TCP로 응답</li>
</ul>
</li>
<li>Host:<ul>
<li><code>/tmp/lut_pwm_response</code> FIFO 에서 <code>PAN/TILT</code> 응답을 읽음</li>
<li><code>lut_data.json</code> 에</li>
<li><code>{&quot;grid_r&quot;:r,&quot;grid_c&quot;:c,&quot;target_u&quot;:...,&quot;target_v&quot;:...,&quot;pan_us&quot;:...,&quot;tilt_us&quot;:...}</code></li>
<li>형태로 한 포인트를 <strong>즉시 저장 (전체 파일 리라이트)</strong></li>
<li>다음 셀(<code>idx+1</code>) 로 넘어감</li>
</ul>
</li>
</ol>
<ul>
<li><strong>수동 레이저 위치 지정 (마우스 클릭)</strong><ul>
<li>AutoLUT 중 레이저 탐지가 어려운 셀의 경우:<ul>
<li>마우스로 이미지 상 <strong>레이저가 실제 있는 위치</strong>를 클릭</li>
<li><code>g_manual_laser_pending=true</code>, <code>g_manual_laser_pt</code> 설정</li>
<li>다음 프레임에서:<ul>
<li><code>laser.found = true</code>, <code>laser.point = g_manual_laser_pt</code></li>
<li>AutoLUT는 이 좌표를 기준으로 바로 PWM 요청·저장 수행</li>
<li>이 프레임에서는 일반 EX/EY 전송을 스킵 (<code>skip_periodic_send=true</code>)</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>====&gt; 가장자리에서 레이저 포인터가 탐지되지 않는 경우를 해결 ❗❗❗</p>
</li>
</ul>
<p>Raspi: <code>pid_pwm_agent.py --lut-mode</code></p>
<ul>
<li>PID 제어를 사용하여 실제 레이저를 타겟 중앙에 수렴시키고,<br>각 셀마다 “오차 이내”일 때 AutoLUT가 PWM을 가져가도록 돕는 모드.</li>
</ul>
<hr>
<h3 id="result">result</h3>
<p><img src="https://velog.velcdn.com/images/physical-100/post/c59cfa55-ca35-4dc8-b1e5-0732ebd7b706/image.gif" alt="">
이렇게 각 그리드에서 값을 탐지하고 이후 보간법을 이용해 화면 내에서 동일한 픽셀의 경우 빠른 추종이 가능하도록 만들었다.</p>
<p>하지만 추후 발생할 수 있는 문제로는 카메라와 객체의 거리가 달라질 경우 레이저의 각도가 미묘하게 달라질 필요가 있다. </p>
<p>이는 자동 캘리브레이션 코드와 LUT+PID 코드 구현으로 문제점을 해결해 나갈 생각이다. </p>
<h3 id="현재-시스템의-tracking-성능-수준-로그-기반-평가">현재 시스템의 tracking 성능 수준 (로그 기반 평가)</h3>
<pre><code>🍎좋은 점
- 위치형 PID로 전환 후 → 오차=0 시 정확히 멈춤
- 시간이 지나면 제자리로 수렴 → 기본적인 closed-loop 동작 확인

☠️아직 부족한 점
- settling time (오차가 줄어드는 시간)이 1~2초 이상 
      → 사람 0.5m/s만 움직여도 따라가지 못함
- 레이저 탐지 불안정 → 오차가 순간 0이 되거나 튀면 PID가 혼란
- 지연 (RTSP + TCP + 3프레임 전송) → PID가 과거 오차로 계산</code></pre><h3 id="칼만-필터">+칼만 필터</h3>
<p>실시간으로 객체를 추적하기 위해 위치 예측을 추가했다. 아직은 간단한 2D 칼만 필터를 추가했지만 추가로 고도화 할 계획이다.
!youtube[8StNxj_AEZo]</p>
<h3 id="시도">시도</h3>
<ul>
<li>호스트 PC(리눅스에서도 프레임별 연산 외에 비동기로 제어 주기와 동일하게 신호 전송  =. 엄격한 시간 스케줄링)</li>
<li>LUT + PID </li>
<li>pysysid 라이브러리 최적값 탐지 </li>
<li>카메라 캘리브레이션 및 거리 추정 </li>
</ul>
<hr>
<h3 id="추가로">추가로</h3>
<p>공채 시즌이 시작되면서 더욱이 바쁜 나날을 보내고 있습니다 ..</p>
<p>죽는 느낌..   <span style= "color:yellow">ALL RIGHT .!! </span></p>
<h4 id="짜투리-">짜투리 ...</h4>
<img src  = "https://velog.velcdn.com/images/physical-100/post/7bb2d6fd-c86c-40b6-8831-c4d0dc29ad04/image.JPG" width = 400 height = 500 >

<img src  = "https://velog.velcdn.com/images/physical-100/post/f00bf6d5-83f3-4f51-a8a3-b09ddbbf1c8d/image.JPG" width = 400 height = 500 >


<img src  = "https://velog.velcdn.com/images/physical-100/post/763ecc69-8e88-407e-82e9-e73c6b123e08/image.JPG" width = 500 >

<p>살자 .. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 18주차 기록]]></title>
            <link>https://velog.io/@physical-100/VEDA-18%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@physical-100/VEDA-18%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Mon, 02 Mar 2026 16:20:23 GMT</pubDate>
            <description><![CDATA[<p>18주차에는 QT 클라이언트와 서버 스피커 간의 실시간 음성 통신, 보행자 레이저 트래킹을 위한 기본 코드를 구현했습니다.</p>
<p>그렇다면 개발 간의 문제사항과 개발 내용을 정리해보는 시간을 가지도록 하겠습니다.!!!</p>
<hr>
<h3 id="audio-module">AUDIO module</h3>
<p>초기 목적은 오디오 라이브러리를 직접 구현해보는 것이었지만 사실상 프로젝트의 핵심 기능이 아닌 부가 기능이라 생각되어 개발 속도를 중점으로 완성했습니다.</p>
<h4 id="전체-구조-개요">전체 구조 개요</h4>
<p><strong>실시간 마이크 → 스피커</strong>오디오 경로는 다음과 같은 파이프라인으로 구현되어 있습니다.</p>
<ul>
<li><p>클라이언트(마이크)</p>
<ul>
<li>Qt 클라이언트의 <code>QAudioSource</code> 등에서 16 kHz, mono, 16-bit(S16_LE) 포맷으로 PCM을 뽑아 TCP로 전송 (5556 또는 테스트용 6000 포트).</li>
</ul>
</li>
<li><p>라즈베리 파이(스피커 유닛) – <code>Audio_Speaker_Unit</code></p>
<ul>
<li><code>main.cpp</code> 안에서 TCP 서버(6000 포트)를 열어 RAW/MP3 스트림을 받음.</li>
<li>RAW 모드에서는 받은 PCM을 링 버퍼 <code>AudioRingBuffer</code> 에 넣고,
별도 재생 스레드 <code>AudioPlayback</code> 이 링 버퍼에서 꺼내 <code>ALSA(libasound)</code>로 스피커 출력.</li>
</ul>
</li>
</ul>
<h4 id="사용-라이브러리기술">사용 라이브러리/기술</h4>
<ul>
<li><p>ALSA (libasound)</p>
<ul>
<li>헤더: #include &lt;alsa/asoundlib.h&gt;</li>
<li>주요 API:</li>
<li><code>snd_pcm_open(&quot;default&quot;, SND_PCM_STREAM_PLAYBACK, 0)</code></li>
<li><code>snd_pcm_set_params(..., SND_PCM_FORMAT_S16_LE, ..., 16000, 1, ...)</code></li>
<li><code>snd_pcm_writei()</code> 로 PCM 프레임을 계속 출력</li>
<li>XRUN 시 <code>snd_pcm_prepare()</code> 로 복구</li>
<li>역할: 실제 라즈베리 파이 오디오 디바이스에 PCM 데이터를 쓰는 드라이버 레벨 인터페이스</li>
</ul>
</li>
<li><p>POSIX 소켓 (TCP)</p>
<ul>
<li>헤더: arpa/inet.h, sys/socket.h, netinet/in.h, unistd.h</li>
</ul>
<blockquote>
<p>서버(audio_speaker_test): socket → bind → listen → accept → read 오디오 스트림 수신
클라이언트(send_audio): connect → send 오디오 바이트 전송</p>
</blockquote>
</li>
<li><p>멀티스레드 &amp; 동기화</p>
<ul>
<li><code>audio_ring_buffer.*</code>:<ul>
<li><code>AudioRingBuffer</code> 내부에서 생산자/소비자 패턴 구현</li>
<li>push() / pop() 에서 버퍼가 비었거나 꽉 찼을 때 condition_variable 로 block/wake</li>
</ul>
</li>
<li><code>audio_playback.*</code>:<ul>
<li><code>AudioPlayback</code> 가 별도 스레드(playbackThreadFunc)를 돌리며 링 버퍼를 소비</li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="실시간-음성-스트리밍-경로">실시간 음성 스트리밍 경로</h4>
<ol>
<li><p>공통 오디오 포맷 정의 (<code>audio_common.h</code>)</p>
<pre><code class="language-text">AUDIO_SAMPLE_RATE = 16000
AUDIO_CHANNELS = 1
AUDIO_FRAME_BYTES = 2 (Int16 * 1ch)</code></pre>
</li>
<li><p>링 버퍼 (audio_ring_buffer.h/.cpp)</p>
<p> 클래스: AudioRingBuffer</p>
<p> 내부: std::vector<char> + std::mutex + std::condition_variable</p>
<p> Producer(네트워크 수신 스레드):</p>
<ul>
<li>push(const char* data, std::size_t bytes)</li>
<li>버퍼가 꽉 차면 cv_not_full_ 대기 → 공간 생기면 다시 push
Consumer(Playback 스레드):</li>
<li>pop(char* out, std::size_t max_bytes)</li>
<li>데이터가 없으면 cv_not_empty_ 대기 → 데이터 들어오면 읽기</li>
</ul>
<p>역할: <u>네트워크 지터/속도 차이</u>와 재생 디바이스의 타이밍 차이를 수십~수백 ms 정도 완충.</p>
</li>
<li><p>재생 스레드 (audio_playback.h/.cpp) – ALSA 사용</p>
<p> 클래스: AudioPlayback</p>
<p> initPcm():</p>
<ul>
<li><p>snd_pcm_open(&quot;default&quot;, SND_PCM_STREAM_PLAYBACK, 0)</p>
</li>
<li><p>snd_pcm_set_params(..., SND_PCM_FORMAT_S16_LE, AUDIO_CHANNELS, AUDIO_SAMPLE_RATE, ...)</p>
</li>
<li><p>snd_pcm_get_params() 로 period/buffer 프레임 수 조회</p>
<p>start():</p>
</li>
<li><p>ALSA 초기화 뒤, std::thread 로 playbackThreadFunc() 시작</p>
<p>playbackThreadFunc():</p>
</li>
<li><p>한 번에 period_frames_ * AUDIO_FRAME_BYTES 만큼 ring.pop() 으로 읽어옴</p>
</li>
<li><p>읽어온 바이트를 프레임 수로 환산 후, 루프 안에서 snd_pcm_writei() 호출</p>
</li>
<li><p>EPIPE(XRUN) 발생 시 snd_pcm_prepare() 후 재시도</p>
</li>
</ul>
<p>역할: 링 버퍼에 쌓인 오디오를 끊김 없이 ALSA 디바이스로 밀어 넣는 소비자 스레드</p>
<p><a href="https://velog.io/@physical-100/Audio-Driver-XRUN">xrun이 무엇인가?</a>는 해당 블로그에 정리해두도록 하겠습니다. ^^😍</p>
</li>
</ol>
<ol start="4">
<li><p>TCP 수신 스레드 (main.cpp) – RAW 모드</p>
<p>   run_tcp_receiver_raw(AudioRingBuffer&amp; ring):</p>
<ul>
<li><p>포트 AUDIO_TEST_PORT(6000) 에 socket/bind/listen</p>
</li>
<li><p>accept() 후 루프에서 read() 로 4096 바이트씩 수신</p>
</li>
<li><p>수신된 바이트를 그대로 ring.push(buf, bytes) 호출</p>
<p>main():
AudioRingBuffer ring(RING_CAPACITY_BYTES) – 약 1초 분량 용량
AudioPlayback playback(ring); playback.start();</p>
</li>
</ul>
<p>이후 <code>run_tcp_receiver_raw(ring)</code> 호출 → 수신과 재생이 동시에 진행되는 스트리밍 구조</p>
</li>
</ol>
<h4 id="결과">결과</h4>
<p>클라이언트(마이크 또는 send_audio)가 RAW PCM을 보내면,
“TCP 수신 → 링 버퍼 push → Playback 스레드 pop → ALSA(snd_pcm_writei) → 스피커” 흐름으로 거의 실시간에 가깝게 재생된다.</p>
<pre><code>  “네트워크 → mpg123 → ALSA → 스피커” 직결 구조.</code></pre><hr>
<p>  이렇게 qt 클라이언트(윈도우)에서 라즈베리파이 서버 audio 통신이 곧바로 스피커로 재생되도록 하는 시스템을 구축했습니다. 비록 디지털 오디오 잭을 이용해 간단하게 구현했지만 전체적인 시스템을 파악할 수 있는 시간이었습니다.</p>
<p>그래도 직접 마이크에서 스피커로 소리가 흘러나옴을 확인한 순간은 보람을 가득 느낄 수 있었습니다. </p>
<h2 id="stm32-laser-tracking-system">STM32 Laser Tracking system</h2>
<p>  한화비전 카메라와 바로 레이저 트레킹 모듈을 연결하려는 시도를 했지만 보안상의 이슈로 이런 저런 접근을 시도했지만 실패했습니다. 그렇지만 유선으로 서버와 Laser 모듈을 연결하는 것은 하드웨어 구성상 어색해 별도의 ESP8266을 활용하여 wifi무선 통신을 구현하였습니다 .</p>
<p>하드웨어 연결 외에는 AT 펌웨어로 초기 세팅을 진행하고 나니 어려움은 없었습니다. </p>
<p>[ESP8266 &lt;-&gt; Raspi wifi connect] (<a href="https://velog.io/@physical-100/NucleoF401re-ESP8266-wifi-communication">https://velog.io/@physical-100/NucleoF401re-ESP8266-wifi-communication</a>) 에 관련된 내용은 해당 블로그에 정리해놓았습니다. ! </p>
<p>그렇다면 18주차에 마주친 임베디드 개발 issue 위주로 기록을 해보도록 하겠습니다. </p>
<h3 id="1-mcu--전체-개요">1. MCU / 전체 개요</h3>
<ul>
<li><strong>MCU</strong>: <code>STM32F401RE</code> (Nucleo-F401RE 보드 기준)</li>
<li><strong>주요 기능</strong><ul>
<li>TIM1 / TIM2 PWM 으로 <strong>2축 서보 모터 제어</strong> (레이저 방향 제어용)</li>
<li><code>USART1</code> + DMA 로 <strong>ESP-8266(WiFi 모듈)</strong> 과 통신 (AT 명령, TCP 브리지)</li>
<li><code>USART2</code> 로 <strong>PC 디버그/수동 제어 시리얼</strong> 제공</li>
<li><code>PC13</code> 버튼 / <code>PA5</code> LED 로 <strong>모드 전환(MANUAL/AUTO)</strong> 표시</li>
</ul>
</li>
</ul>
<hr>
<h3 id="2-핀-매핑-정리">2. 핀 매핑 정리</h3>
<h4 id="21-서보-모터-레이저-방향-제어">2.1 서보 모터 (레이저 방향 제어)</h4>
<ul>
<li><p><strong>Y축 (서보 1)</strong></p>
<ul>
<li><strong>STM32 핀</strong>: <code>PA8</code></li>
<li><strong>기능</strong>: <code>TIM1_CH1</code> (PWM 출력)</li>
<li><strong>Cube 설정</strong>: <code>S_TIM1_CH1</code> → PWM Generation CH1  </li>
<li><strong>코드 참조</strong><ul>
<li>PWM 초기화: <code>MX_TIM1_Init()</code> (<code>main.c</code>)</li>
<li>핀 설정: <code>HAL_TIM_MspPostInit()</code> → <code>GPIO_AF1_TIM1</code> </li>
</ul>
</li>
</ul>
</li>
<li><p><strong>X축 (서보 2)</strong></p>
<ul>
<li><strong>STM32 핀</strong>: <code>PA0</code> (WKUP)</li>
<li><strong>기능</strong>: <code>TIM2_CH1</code></li>
<li><strong>Cube 설정</strong>: <code>S_TIM2_CH1_ETR</code> → PWM Generation CH1  </li>
<li><strong>코드 참조</strong><ul>
<li>PWM 초기화: <code>MX_TIM2_Init()</code> (<code>main.c</code>)</li>
<li>핀 설정: <code>HAL_TIM_MspPostInit()</code> → <code>GPIO_AF1_TIM2</code> </li>
</ul>
</li>
</ul>
</li>
</ul>
<h4 id="22-esp-8266-wifi-모듈--usart1">2.2 ESP-8266 (WiFi 모듈) – <code>USART1</code></h4>
<ul>
<li><p><strong>UART 신호선</strong></p>
<ul>
<li><strong>ESP TX</strong> ↔ <strong>STM32 RX</strong><ul>
<li>STM32 핀: <strong><code>PA10</code></strong></li>
<li>기능: <code>USART1_RX</code></li>
<li>설정: <code>GPIO_AF7_USART1</code></li>
</ul>
</li>
<li><strong>ESP RX</strong> ↔ <strong>STM32 TX</strong><ul>
<li>STM32 핀: <strong><code>PA9</code></strong></li>
<li>기능: <code>USART1_TX</code></li>
<li>설정: <code>GPIO_AF7_USART1</code> </li>
</ul>
</li>
</ul>
</li>
<li><p><strong>DMA (ESP → STM32, RX 전용)</strong></p>
<ul>
<li><code>DMA2_Stream2</code>, Channel 4 (<code>USART1_RX</code>)</li>
<li>방향: <code>PERIPH_TO_MEMORY</code></li>
<li>모드: <code>NORMAL</code></li>
<li>PC 쪽 로그는 <code>wifi_rx_pending</code> 플래그를 통해 <code>main()</code> 루프에서 처리.</li>
</ul>
</li>
</ul>
<h4 id="23-pc-디버그-시리얼--usart2">2.3 PC 디버그 시리얼 – <code>USART2</code></h4>
<ul>
<li><strong>STM32 핀</strong><ul>
<li><code>PA2</code> → <code>USART2_TX</code> (ST-LINK VCP TX → PC RX)</li>
<li><code>PA3</code> → <code>USART2_RX</code> (ST-LINK VCP RX → PC TX, <code>USART_RX_Pin</code> 매크로)</li>
</ul>
</li>
<li><strong>용도</strong><ul>
<li>부트 메시지, 모드 변경 로그, 서보 제어 명령 입력, ESP AT 명령 프록시.</li>
</ul>
</li>
</ul>
<h4 id="24-버튼--led--디버그">2.4 버튼 / LED / 디버그</h4>
<ul>
<li><p><strong>B1 사용자 버튼 (모드 토글)</strong></p>
<ul>
<li>핀: <code>PC13</code></li>
<li>기능: <code>GPIO_EXTI13</code> (외부 인터럽트, Falling edge)</li>
<li>역할: 누를 때마다 <code>MODE_MANUAL</code> ↔ <code>MODE_AUTO</code> 토글 (<code>button_auto_pending</code> 플래그).</li>
</ul>
</li>
<li><p><strong>LD2 LED / 레이저 테스트 핀</strong></p>
<ul>
<li>핀: <code>PA5</code></li>
<li>기능: GPIO Output push-pull</li>
<li>역할:<ul>
<li>펌웨어 관점: AUTO 모드 여부를 표시 (<code>Led_SetAutoMode()</code>).</li>
<li><strong>하드웨어 구성</strong>: 실제 레이저 모듈의 전원/Enable 신호를 LD2 와 <strong>같이 묶어서</strong> 연결해 두었기 때문에,<br>PA5 를 토글하면 보드 LED 와 레이저가 함께 ON/OFF 되도록 테스트 중.</li>
</ul>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="3-클럭-설정-정리">3. 클럭 설정 정리</h3>
<h4 id="pwm-타이머-설정-및-펄스-폭-단위">PWM 타이머 설정 및 펄스 폭 단위</h4>
<p><code>MX_TIM1_Init()</code>, <code>MX_TIM2_Init()</code> (둘 다 <code>main.c</code>) 에서 설정:</p>
<ul>
<li><p><strong>TIM1 (PA8, 서보 Y축)</strong>, <strong>TIM2 (PA0, 서보 X축)</strong></p>
<ul>
<li><p>Prescaler = 83</p>
</li>
<li><p>Period(초기) = 19999</p>
</li>
<li><p>결과:  </p>
<ul>
<li>타이머 클럭 = 84 MHz / (83+1) = 1 MHz  </li>
<li>1 카운트 = 1 µs  </li>
<li>20,000 카운트 = 20 ms (50 Hz, 서보 표준)</li>
</ul>
</li>
<li><p>PWM 출력 모드: <code>TIM_OCMODE_PWM1</code>, <code>OCPolarity = HIGH</code> (서보 일반 규격에 맞게 수정됨).</p>
</li>
<li><p>따라서 두 타이머 모두 <strong>1 tick = 1 µs</strong>,  
<code>Servo_Set*Us(1500)</code> 이라면 <strong>1500 µs 펄스</strong>가 됨.</p>
</li>
</ul>
</li>
</ul>
<hr>
<h3 id="system-전체-flow">System 전체 Flow</h3>
<p><strong>전체 Flow (Closed-Loop Visual Servoing 중심)</strong></p>
<ol>
<li>CCTV 영상 (RTSP)</li>
<li>Wisenet AI (사람 detect → bbox center)</li>
<li>Laser Dot Detect (opencv) [  camera  or raspi ]</li>
<li>Error = dot_pos - bbox_center</li>
<li>PID → Pan/Tilt servo command</li>
<li>(Optional) Ground Plane Distance 계산 → 레이저 세기 조절 or 로그</li>
</ol>
<h4 id="카메라-레이저-탐지">카메라 레이저 탐지</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/f8344a4f-43a7-416f-b1ee-78f61a29d3c1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/61fdc3ce-7643-4d07-ba95-3fa718ba7059/image.png" alt=""></p>
<p>  위는 실제 카메라 영상이고 아래는 빨간 색영역을 기준으로 필터링을 진행한 이미지입니다. </p>
<p>레이저 포인터가 잡히기는 하나 다른 noise(책, 공구)등이 함께 탐지되었습니다.</p>
<p>이를 해결하기 위해서 HSV 이미지 변환 후 밝기 값을 중점으로 임계값을 더욱 세분화 하였고  한화 비전 카메라의 기능을 이용하여 노출 값을 낮춰 카메라에서 빛을 받아들이는 양을 줄였습니다. </p>
<p>  <img src="https://velog.velcdn.com/images/physical-100/post/440ffc3f-cd4a-4dc7-af5a-180d9b0806e8/image.png" alt="카메라 설정">
카메라 설정 </p>
<h4 id="결과-1">결과</h4>
<p>  <img src="https://velog.velcdn.com/images/physical-100/post/c831f0cf-0cf0-40d0-bd7a-89607ac13490/image.png" alt=""></p>
<p> 이는 실제 영상을 어둡게 만드는 단점이 있지만 초기 레이저 포인팅 캘리브레이션 작업은 당분간 해당 설정으로 진행할 예정입니다. </p>
<blockquote>
<p>전체 흐름을 따라 서모 모터 제어 그리고 카메라 영상 인식 및 레이저 탐지까지는 구현하는 과정 중 Issue가 발생했습니다. </p>
</blockquote>
<h3 id="span-stylecolor-red--issue-span"><span style="color: red">  ISSUE </span></h3>
<h4 id="모터-노이즈-문제">모터 노이즈 문제</h4>
<h4 id="1-증상">1. 증상</h4>
<ul>
<li>서보가 입력값을 바꾸지 않아도 <code>지지직</code> 소음을 내며 떨림.</li>
<li>Servo tester(하드웨어)에서는 정상 동작하고, STM32 PWM 출력에서만 이상 증상 발생.</li>
</ul>
<h4 id="2-원인-분석">2. 원인 분석</h4>
<ul>
<li><p>TIM PWM 채널 설정에서 출력 극성이 반대로 설정되어 있었음.</p>
</li>
<li><p>문제 설정:</p>
<pre><code class="language-c">sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;</code></pre>
</li>
<li><p>위 상태에서는 PWM이 반전되어, 예를 들어 1500us 명령이 실제로는
거의 전체 주기 High에 가까운 형태로 전달됨.</p>
</li>
<li><p>그 결과 서보 내부 제어 기준에서 비정상 펄스로 해석되어
엔드스톱 방향으로 과도하게 힘을 주면서 소음/발열/진동이 유발됨.</p>
</li>
</ul>
<h4 id="3-수정-내용">3. 수정 내용</h4>
<ul>
<li><p>TIM1/TIM2 PWM 채널의 극성을 서보 일반 규격에 맞게 정방향으로 조정:</p>
<pre><code class="language-c">sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;</code></pre>
</li>
<li><p>50Hz(20ms) 기준에서 1000~2000us 펄스 폭이 정상 의미로 전달되도록 정렬.</p>
</li>
</ul>
<p>해당 이슈는 PWM 신호 전압을 상승 시키기 위해서 PNP 트랜지스터를 시도해보며 극성을 바꾼 뒤 설정을 그대로 둔 채 개발을 진행하다 보니 발생하게 되었습니다. </p>
<p>처음에는 AI에게 물어봐도 전압이나 펄스 주기가 맞지 않아 소음이 발생한다는 등의 답변만 들을 수 있었습니다. 오실로스코프로와 같은 계측기가 없는 상황에서 해결하기란 정말 막막했습니다. 그래서 이것 저것 선과 모터를 바꿔끼워가며 테스트를 해보았지만 여전히 해결되지 않았습니다. 하지만 불과 며칠전까지는 진동이 발생하지 않았는데 무엇이 문제일까 고민하며 이틀 전 커밋의 코드와 현재 코드를 비교해본 결과 극성이 변경되어 있음을 확인할 수 있었습니다. </p>
<p>  전자 전기 관련 이론적 기반이 여실히 부족함을 느낄 수 있는 경험이었습니다 .
  하지만 문제가 해결된 지금 19주차는 다시 앞으로 달려나가 보도록 하겠습니다 !!!!</p>
<h3 id="파이팅">파이팅<del>~</del></h3>
<p>  <img src="https://velog.velcdn.com/images/physical-100/post/7625ca5c-094d-4175-82d5-a4529cad755c/image.JPG" alt=""></p>
<p>  그러면 나의 코딩 토템과 함께 18주차 기록을 마무리하겠습니다. 
  (피규어 겟또!!) </p>
<p>  후훗 ~ 준비됐지요 등? </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NucleoF401re-ESP8266 wifi communication]]></title>
            <link>https://velog.io/@physical-100/NucleoF401re-ESP8266-wifi-communication</link>
            <guid>https://velog.io/@physical-100/NucleoF401re-ESP8266-wifi-communication</guid>
            <pubDate>Mon, 02 Mar 2026 15:49:31 GMT</pubDate>
            <description><![CDATA[<h2 id="esp8266-↔-stm32-↔-pi-통신">ESP8266 ↔ STM32 ↔ Pi 통신</h2>
<h3 id="라즈베리-파이-ap-모드-설정">라즈베리 파이 AP 모드 설정</h3>
<p>STM32 Nucleo-F401RE에 ESP8266을 붙이고, 라즈베리 파이를 <strong>AP(공유기)</strong> 로 켜서 ESP8266이 Pi의 Wi‑Fi에 접속·통신할 수 있게 하는 구성입니다.</p>
<hr>
<h3 id="1-연결-개요">1. 연결 개요</h3>
<h4 id="11-esp8266-↔-nucleo-f401re">1.1 ESP8266 ↔ Nucleo-F401RE</h4>
<table>
<thead>
<tr>
<th>ESP8266 핀</th>
<th>Nucleo-F401RE 핀</th>
<th>비고</th>
</tr>
</thead>
<tbody><tr>
<td>VBUS (5V)</td>
<td>5V</td>
<td>전원 (또는 3.3V 사용 시 3V3)</td>
</tr>
<tr>
<td>GND</td>
<td>GND</td>
<td>공통 GND</td>
</tr>
<tr>
<td><strong>TX</strong></td>
<td><strong>D2 (PA10)</strong></td>
<td>Nucleo <strong>UART RX</strong> (ESP TX → PA10)</td>
</tr>
<tr>
<td><strong>RX</strong></td>
<td><strong>D8 (PA9)</strong></td>
<td>Nucleo <strong>UART TX</strong> (PA9 → ESP RX)</td>
</tr>
</tbody></table>
<ul>
<li>Nucleo 기준: <strong>PA9 = USART1_TX</strong>, <strong>PA10 = USART1_RX</strong> (STM32 UART1 사용).</li>
<li>ESP8266은 3.3V 논리이므로, Nucleo(3.3V)와 직접 연결 가능. 5V 전원만 쓰고 신호선은 3.3V 유지.</li>
</ul>
<h4 id="12-네트워크-구조">1.2 네트워크 구조</h4>
<pre><code>[인터넷] ←랜선(eth0)→ [라즈베리 파이] ←Wi‑Fi AP(wlan0)→ [ESP8266] ←UART→ [STM32 Nucleo]</code></pre><ul>
<li><strong>라즈베리 파이</strong>: 랜선(eth0)으로 외부 인터넷, <strong>wlan0를 AP</strong>로 켜서 ESP8266/STM32가 접속.</li>
<li><strong>ESP8266</strong>: Pi가 만든 AP에 Wi‑Fi로 연결 후, Pi 위에서 도는 TCP 서버 등과 통신.</li>
</ul>
<hr>
<h3 id="2-라즈베리-파이-ap-모드-구성">2. 라즈베리 파이 AP 모드 구성</h3>
<p>아래 두 가지 중 하나만 하면 됩니다.</p>
<hr>
<h4 id="방법-a-raspap으로-빠르게-구성-권장">방법 A: RaspAP으로 빠르게 구성 (권장)</h4>
<ol>
<li><p><strong>RaspAP 설치</strong></p>
<pre><code class="language-bash">sudo apt update
sudo apt install -y raspap-webgui</code></pre>
<p>설치 중 “Configure RaspAP”에서 <strong>Yes</strong> 선택 후, 필요하면 재부팅.</p>
</li>
<li><p><strong>웹 설정</strong></p>
<ul>
<li>Pi의 <strong>eth0 IP</strong>로 브라우저 접속 (예: <code>http://192.168.0.xxx</code>).</li>
<li>로그인: 계정 <code>admin</code>, 비밀번호 <code>changeme</code> (최초 로그인 후 반드시 변경).</li>
<li><strong>WiFi</strong> → <strong>Enable AP</strong> 켜기.</li>
<li><strong>SSID</strong>, <strong>비밀번호(WPA)</strong> 설정 후 저장.</li>
</ul>
</li>
<li><p><strong>동작 확인</strong></p>
<ul>
<li>스마트폰/PC로 해당 SSID 검색 후 연결해 보기.</li>
<li>ESP8266도 이 SSID/비밀번호로 연결하면 됨.</li>
</ul>
</li>
</ol>
<hr>
<h4 id="방법-b-hostapd--dnsmasq-로-수동-구성">방법 B: hostapd + dnsmasq 로 수동 구성</h4>
<h4 id="21-패키지-설치">2.1 패키지 설치</h4>
<pre><code class="language-bash">sudo apt update
sudo apt install -y hostapd dnsmasq
sudo systemctl stop hostapd
sudo systemctl stop dnsmasq</code></pre>
<h4 id="22-고정-ip-wlan0-ap용">2.2 고정 IP (wlan0, AP용)</h4>
<p><code>/etc/dhcpcd.conf</code> 끝에 추가:</p>
<pre><code class="language-bash"># AP용 wlan0 고정 IP (eth0는 기존대로 랜선 DHCP 유지)
interface wlan0
    static ip_address=192.168.4.1/24
    nohook wpa_supplicant</code></pre>
<p>적용:</p>
<pre><code class="language-bash">sudo systemctl restart dhcpcd</code></pre>
<h4 id="23-dnsmasq-ap-클라이언트에게-ip-배포">2.3 dnsmasq (AP 클라이언트에게 IP 배포)</h4>
<p>다른 설정과 겹치지 않도록 기존 설정 백업 후, AP 전용 설정만 사용:</p>
<pre><code class="language-bash">sudo mv /etc/dnsmasq.conf /etc/dnsmasq.conf.bak</code></pre>
<p><code>/etc/dnsmasq.conf</code> 새로 만들기:</p>
<pre><code class="language-ini">interface=wlan0
dhcp-range=192.168.4.2,192.168.4.20,255.255.255.0,24h
domain=local
address=/raspi.local/192.168.4.1</code></pre>
<h4 id="24-hostapd-ap-설정">2.4 hostapd (AP 설정)</h4>
<p><code>/etc/hostapd/hostapd.conf</code>:</p>
<pre><code class="language-ini">interface=wlan0
driver=nl80211
ssid=SFEPS_AP
hw_mode=g
channel=6
wmm_enabled=0
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=your_password_here
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP</code></pre>
<ul>
<li><code>ssid</code>: ESP8266/STM32가 접속할 AP 이름.</li>
<li><code>wpa_passphrase</code>: AP 비밀번호 (원하는 값으로 변경).
<span style="color: orange">-&gt; 최소 8자리 이상으로 설정해야한다 .!! </span></li>
</ul>
<p>hostapd가 이 파일을 쓰도록:</p>
<pre><code class="language-bash">sudo bash -c &#39;echo DAEMON_CONF=\&quot;/etc/hostapd/hostapd.conf\&quot; &gt;&gt; /etc/default/hostapd&#39;
sudo systemctl unmask hostapd
sudo systemctl enable hostapd
sudo systemctl start hostapd
sudo systemctl start dnsmasq</code></pre>
<h4 id="25-ip-포워딩-선택-ap-클라이언트가-인터넷-쓰게-할-때">2.5 IP 포워딩 (선택, AP 클라이언트가 인터넷 쓰게 할 때)</h4>
<p>AP 클라이언트(ESP8266 등)가 Pi를 통해 인터넷에 나가게 하려면:</p>
<pre><code class="language-bash">sudo sed -i &#39;s/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/&#39; /etc/sysctl.conf
sudo sh -c &quot;echo 1 &gt; /proc/sys/net/ipv4/ip_forward&quot;
sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i eth0 -o wlan0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i wlan0 -o eth0 -j ACCEPT</code></pre>
<p>재부팅 후에도 유지하려면 <code>iptables-persistent</code> 등으로 규칙 저장하는 것이 좋습니다.</p>
<hr>
<h3 id="3-통신-흐름-esp8266-↔-pi-↔-stm32">3. 통신 흐름 (ESP8266 ↔ Pi ↔ STM32)</h3>
<ol>
<li><strong>ESP8266</strong>: Pi의 AP(예: <code>SFEPS_AP</code>)에 연결 → DHCP로 <code>192.168.4.x</code> 대역 IP 획득.</li>
<li><strong>Pi</strong>: AP의 게이트웨이 = <code>192.168.4.1</code>. 이 IP에서 <strong>TCP 서버</strong>(또는 UDP)를 열어 두면 됨.<ul>
<li>예: <code>tmp_raspi_server/raspi_tcp_server</code> (좌표/텍스트 전송, RTT 측정 지원)</li>
</ul>
</li>
<li><strong>STM32</strong>: UART로 ESP8266에 AT 명령 또는 펌웨어에서 정의한 프로토콜로 “Pi의 192.168.4.1:포트”로 접속하라고 지시.</li>
<li><strong>Pi 서버</strong>: <code>tmp_raspi_server</code> 또는 기존 서버 코드에서 해당 포트 listen → STM32와 메시지 주고받기.</li>
</ol>
<p>예시 (Pi에서 테스트용 TCP 서버):</p>
<pre><code class="language-bash"># 192.168.4.1:5555 에서 대기 (실제 서비스는 Python/C 등으로 구현)
nc -lk 5555</code></pre>
<p>ESP8266/STM32는 <code>192.168.4.1</code> 포트 <code>5555</code>로 접속하면 됨.</p>
<hr>
<h3 id="4-정리">4. 정리</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>내용</th>
</tr>
</thead>
<tbody><tr>
<td><strong>연결</strong></td>
<td>ESP8266 TX→PA10(RX), RX→PA9(TX), GND, 5V(또는 3V3)</td>
</tr>
<tr>
<td><strong>Pi 역할</strong></td>
<td>랜선(eth0)=인터넷, wlan0=AP로 ESP8266/STM32 접속 허용 + TCP 서버 구동(<code>raspi_tcp_server</code>)</td>
</tr>
<tr>
<td><strong>AP 구성</strong></td>
<td>RaspAP(방법 A) 또는 hostapd+dnsmasq(방법 B)</td>
</tr>
<tr>
<td><strong>통신</strong></td>
<td>ESP8266이 Pi AP에 접속 → Pi의 192.168.4.1:원하는포트 로 TCP/UDP</td>
</tr>
</tbody></table>
<p>이후 STM32 쪽에서는 USART1(PA9/PA10)로 ESP8266 AT 명령 또는 커스텀 프로토콜을 구현하면 됩니다.</p>
<hr>
<h3 id="실제-test-확인">실제 test 확인</h3>
<p>stm에서 ESP8266에 전원이 공급되었을 때 주기적으로 connection을 검사하고 자동으로 Raspi에 연결될 수 있도록 구현했습니다.</p>
<h4 id="stm-↔-raspi-wifi-commuication">stm ↔ Raspi wifi commuication</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/39406bef-a3b1-4ec4-b1cb-bc503a9165a4/image.png" alt=""></p>
<p>AT 펌웨어 내 연결 설정 확인 . </p>
<h4 id="stm-내에서--bsp-값을-받아서-인식-완료">stm 내에서  bsp 값을 받아서 인식 완료.</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/465c608c-ffb1-4c4a-83a4-05549dc20899/image.png" alt="">
라즈베리에서 입력한 값을 ESP에서 수신하여 STM monitoring 확인 </p>
<hr>
<h3 id="at-펌웨어-명령어">AT 펌웨어 명령어</h3>
<h4 id="1-기본-및-설정-명령어">1. 기본 및 설정 명령어</h4>
<p>모듈의 상태를 확인하고 통신 환경을 설정하는 기초 단계입니다.</p>
<table>
<thead>
<tr>
<th><strong>명령어</strong></th>
<th><strong>설명</strong></th>
<th><strong>사용 예시 및 응답</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong><code>AT</code></strong></td>
<td>통신 상태 확인</td>
<td><code>AT</code> → <code>OK</code> (연결 정상)</td>
</tr>
<tr>
<td><strong><code>AT+RST</code></strong></td>
<td>모듈 재시작 (Reset)</td>
<td><code>AT+RST</code> → <code>OK</code></td>
</tr>
<tr>
<td><strong><code>AT+GMR</code></strong></td>
<td>펌웨어 버전 확인</td>
<td><code>AT+GMR</code> → SDK/Bin 버전 출력</td>
</tr>
<tr>
<td><strong><code>ATE0 / ATE1</code></strong></td>
<td>에코 모드 끄기/켜기</td>
<td><code>ATE0</code> (내가 보낸 명령어가 다시 안 보이게 함)</td>
</tr>
<tr>
<td><strong><code>AT+UART_DEF</code></strong></td>
<td>통신 속도(Baudrate) 영구 설정</td>
<td><code>AT+UART_DEF=115200,8,1,0,3</code></td>
</tr>
</tbody></table>
<hr>
<h4 id="2-wi-fi-연결-관련-명령어">2. Wi-Fi 연결 관련 명령어</h4>
<p>드론이나 임베디드 장비를 네트워크에 붙일 때 필수적인 명령어입니다.</p>
<ul>
<li><strong>모드 설정 (<code>AT+CWMODE</code>)</strong><ul>
<li><strong>1:</strong> Station 모드 (공유기에 접속)</li>
<li><strong>2:</strong> SoftAP 모드 (스스로 공유기가 됨)</li>
<li><strong>3:</strong> Station + SoftAP 혼합</li>
</ul>
</li>
</ul>
<p><strong>연결 프로세스 예시</strong></p>
<ol>
<li><strong>모드 설정:</strong> <code>AT+CWMODE=1</code></li>
<li><strong>주변 AP 검색:</strong> <code>AT+CWLAP</code> (주변 Wi-Fi 목록 출력)</li>
<li><strong>공유기 접속:</strong> <code>AT+CWJAP=&quot;SSID&quot;,&quot;Password&quot;</code></li>
<li><strong>IP 주소 확인:</strong> <code>AT+CIFSR</code> → 모듈의 IP 출력</li>
</ol>
<hr>
<h4 id="3-tcpudp-통신-명령어-데이터-송수신">3. TCP/UDP 통신 명령어 (데이터 송수신)</h4>
<p>실제 서버와 데이터를 주고받는 핵심 과정입니다.</p>
<h5 id="single-connection-단일-연결-예시"><strong>Single Connection (단일 연결) 예시</strong></h5>
<ol>
<li><strong>서버 연결 (TCP):</strong> <code>AT+CIPSTART=&quot;TCP&quot;,&quot;192.168.0.10&quot;,8080</code></li>
<li><strong>데이터 송신 준비:</strong> <code>AT+CIPSEND=4</code> (4바이트를 보내겠다고 선언)</li>
<li><strong>데이터 입력:</strong> <code>Test</code> (선언한 바이트만큼 입력) → <code>SEND OK</code> 응답</li>
<li><strong>연결 종료:</strong> <code>AT+CIPCLOSE</code></li>
</ol>
<h5 id="multiple-connection-다중-연결-설정"><strong>Multiple Connection (다중 연결 설정)</strong></h5>
<p>서버 모드로 동작하거나 여러 곳과 통신할 때 필요합니다.</p>
<ul>
<li><code>AT+CIPMUX=1</code> (다중 연결 활성화)</li>
<li><code>AT+CIPSERVER=1,80</code> (80번 포트로 서버 개설)</li>
</ul>
<hr>
<h3 id="rtt-시간-측정">rtt 시간 측정</h3>
<p>보행자 tracking을 위한 지연율을 확인하기 위해 RTT를 측정해본 결과 문제사항을 발견할 수 있었습니다. </p>
<pre><code class="language-bash">[TCP] 클라이언트 연결 대기 중...
[TCP] Client connected from 192.168.4.18:5853
[RTT] ---- PING/PONG RTT 테스트 시작 ----
[RTT] count=20, interval=200 ms
[RTT] seq=1 rtt=70 ms | line=&quot;PONG,1&quot;
[RTT] seq=2 rtt=97 ms | line=&quot;PONG,2&quot;
[RTT] seq=3 rtt=223 ms | line=&quot;PONG,3&quot;
[RTT] seq=4 rtt=197 ms | line=&quot;PONG,4&quot;
[RTT] seq=5 rtt=208 ms | line=&quot;PONG,5&quot;
[RTT] seq=6 rtt=240 ms | line=&quot;PONG,6&quot;
[RTT] seq=7 rtt=13 ms | line=&quot;PONG,7&quot;
[RTT] seq=8 rtt=22 ms | line=&quot;PONG,8&quot;
[RTT] seq=9 rtt=11 ms | line=&quot;PONG,9&quot;
[RTT] seq=10 rtt=12 ms | line=&quot;PONG,10&quot;
[RTT] seq=11 rtt=17 ms | line=&quot;PONG,11&quot;
[RTT] seq=12 rtt=12 ms | line=&quot;PONG,12&quot;
[RTT] seq=13 rtt=29 ms | line=&quot;PONG,13&quot;
[RTT] seq=14 rtt=12 ms | line=&quot;PONG,14&quot;
[RTT] seq=15 rtt=11 ms | line=&quot;PONG,15&quot;
[RTT] seq=16 rtt=15 ms | line=&quot;PONG,16&quot;
[RTT] seq=17 rtt=34 ms | line=&quot;PONG,17&quot;
[RTT] seq=18 rtt=23 ms | line=&quot;PONG,18&quot;
[RTT] seq=19 rtt=14 ms | line=&quot;PONG,19&quot;
[RTT] seq=20 rtt=27 ms | line=&quot;PONG,20&quot;
[RTT] ---- 완료 ----
[RTT] count=20, avg=64.35 ms, min=11 ms, max=240 ms
[RTT] 대략적인 편도 지연 ≈ avg/2 ≒ 32.175 ms</code></pre>
<hr>
<p>RTT 결과에서 <strong>값이 갑자기 240ms까지 튀는 현상(Jitter)</strong>의 주범이 바로 이 슬립 모드일 확률이 높음.</p>
<ul>
<li><strong>반응 속도 저하:</strong> 데이터가 들어올 때 잠들어 있던 모뎀이 깨어나기까지 수십에서 수백 밀리초(ms)</li>
<li><strong>패킷 유실 위험:</strong> 모뎀이 깨어나는 동안 들어온 데이터 패킷이 버퍼에서 밀리거나 유실될 수 있음 .</li>
<li><strong>연결 불안정:</strong> 라즈베리 파이 AP와의 연결을 유지하기 위한 비콘(Beacon) 신호를 놓쳐 연결이 아예 끊어지는 원인이 될 수 있다 .</li>
</ul>
<p><strong>해결 방법</strong></p>
<pre><code class="language-bash">AT+SLEEP=0
//모든 슬립 모드를 비활성화</code></pre>
<p>→ <strong>Result</strong></p>
<pre><code class="language-cpp">[TCP] Client connected from 192.168.4.18:18443
[RTT] ---- PING/PONG RTT 테스트 시작 ----
[RTT] count=20, interval=200 ms
[RTT] seq=1 rtt=11 ms | line=&quot;PONG,1&quot;
[RTT] seq=2 rtt=14 ms | line=&quot;PONG,2&quot;
[RTT] seq=3 rtt=12 ms | line=&quot;PONG,3&quot;
[RTT] seq=4 rtt=11 ms | line=&quot;PONG,4&quot;
[RTT] seq=5 rtt=12 ms | line=&quot;PONG,5&quot;
[RTT] seq=6 rtt=14 ms | line=&quot;PONG,6&quot;
[RTT] seq=7 rtt=48 ms | line=&quot;PONG,7&quot;
[RTT] seq=8 rtt=38 ms | line=&quot;PONG,8&quot;
[RTT] seq=9 rtt=18 ms | line=&quot;PONG,9&quot;
[RTT] seq=10 rtt=12 ms | line=&quot;PONG,10&quot;
[RTT] seq=11 rtt=13 ms | line=&quot;PONG,11&quot;
[RTT] seq=12 rtt=27 ms | line=&quot;PONG,12&quot;
[RTT] seq=13 rtt=30 ms | line=&quot;PONG,13&quot;
[RTT] seq=14 rtt=20 ms | line=&quot;PONG,14&quot;
[RTT] seq=15 rtt=11 ms | line=&quot;PONG,15&quot;
[RTT] seq=16 rtt=25 ms | line=&quot;PONG,16&quot;
[RTT] seq=17 rtt=13 ms | line=&quot;PONG,17&quot;
[RTT] seq=18 rtt=34 ms | line=&quot;PONG,18&quot;
[RTT] seq=19 rtt=17 ms | line=&quot;PONG,19&quot;
[RTT] seq=20 rtt=12 ms | line=&quot;PONG,20&quot;
[RTT] ---- 완료 ----
[RTT] count=20, avg=19.6 ms, min=11 ms, max=48 ms
[RTT] 대략적인 편도 지연 ≈ avg/2 ≒ 9.8 ms</code></pre>
<p>max 값이 240 → 48으로 확실히 줄어들었다 .</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Audio Driver- XRUN?]]></title>
            <link>https://velog.io/@physical-100/Audio-Driver-XRUN</link>
            <guid>https://velog.io/@physical-100/Audio-Driver-XRUN</guid>
            <pubDate>Mon, 02 Mar 2026 15:01:16 GMT</pubDate>
            <description><![CDATA[<h3 id="xrun이-무엇인가❓">XRUN이 무엇인가❓</h3>
<p>  <strong>&quot;컴퓨터가 오디오 데이터를 처리하는 속도가 실제 재생/녹음 속도를 따라가지 못해 소리가 끊기는 현상&quot;</strong></p>
<h4 id="1-두-가지-유형의-xrun">1. 두 가지 유형의 xrun</h4>
<p>① Underrun (언더런) - 주로 재생 시 발생</p>
<ul>
<li>상황: 스피커로 소리를 내보내야 하는데, 버퍼(데이터 임시 저장소)가 비어버린 상태입니다.</li>
<li>결과: 재생할 데이터가 없으므로 아주 짧은 순간 소리가 멈춥니다. 우리 귀에는 &#39;툭(Pop)&#39; 하는 잡음이나 &#39;지지직(Crackle)&#39; 거리는 소리로 들립니다.</li>
</ul>
<p>② Overrun (오버런) - 주로 녹음 시 발생</p>
<ul>
<li><p>상황: 마이크 등으로 들어온 데이터를 컴퓨터가 빨리 가져가서 처리해야 하는데, 버퍼가 이미 꽉 차서 새로 들어오는 데이터를 저장할 공간이 없는 상태입니다.</p>
</li>
<li><p>결과: 새로 들어온 데이터가 버려지게 되어 녹음된 결과물에 중간중간 구멍이 생깁니다.</p>
</li>
</ul>
<h4 id="2-왜-발생하나요">2. 왜 발생하나요?</h4>
<p>오디오는 끊김 없는 실시간성이 생명이다. 하지만 컴퓨터는 <u>다른 작업(백그라운드 프로세스, 네트워크 등)</u>도 함께 처리하기 때문에 오디오 처리가 뒤로 밀릴 수 있다.</p>
<ul>
<li><p>버퍼 사이즈가 너무 작을 때: <code>지연 시간(Latency)</code>을 줄이려고 버퍼를 너무 작게 설정하면, 컴퓨터가 데이터를 채워 넣을 시간이 부족해집니다.</p>
</li>
<li><p>CPU 부하가 높을 때: 다른 무거운 프로그램이 CPU를 점유하고 있으면 오디오 처리가 제때 이뤄지지 않습니다.</p>
</li>
<li><p><code>시스템 인터럽트(IRQ)</code> 충돌: 특정 하드웨어가 CPU의 관심을 독점하여 오디오 카드의 요청을 방해할 때 발생합니다.</p>
</li>
</ul>
<h4 id="3-해결-방법-최적화">3. 해결 방법 (최적화)</h4>
<p>실시간 영상 처리 와 같이, 오디오 역시 실시간성이 중요하다.</p>
<ul>
<li><p>버퍼 사이즈 조절: 지연 시간이 조금 늘어나더라도 버퍼 크기를 키우면 xrun을 방지할 수 있습니다.</p>
</li>
<li><p>실시간 커널(RT Kernel) 사용: 리눅스 환경이라면 오디오 프로세스에 최우선 순위를 부여하는 실시간 패치 커널을 사용합니다.</p>
</li>
<li><p>우선순위 설정: chrt 같은 명령어를 통해 오디오 관련 프로세스의 스케줄링 우선순위를 높입니다.</p>
</li>
<li><p>전력 관리 비활성화: CPU가 절전 모드로 들어가면서 클럭 속도가 변할 때 xrun이 발생하기 쉬우므로, &#39;High Performance&#39; 모드로 고정하는 것이 좋습니다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 17주차 기록 
-디바이스 드라이버]]></title>
            <link>https://velog.io/@physical-100/VEDA-17%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D-%EB%94%94%EB%B0%94%EC%9D%B4%EC%8A%A4-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84</link>
            <guid>https://velog.io/@physical-100/VEDA-17%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D-%EB%94%94%EB%B0%94%EC%9D%B4%EC%8A%A4-%EB%93%9C%EB%9D%BC%EC%9D%B4%EB%B2%84</guid>
            <pubDate>Sun, 22 Feb 2026 07:19:20 GMT</pubDate>
            <description><![CDATA[<p>오늘은 RFID를 활용한 디바이스 드라이버 구현에 대해 정리하는 시간을 가져보도록 하겠습니다 . 개인적으로는 stm을 활용한 모듈 , 라이브러리 제작 보다  리눅스 디바이스 드라이버를 만드는 과정이 더 어렵게 느껴졌습니다 .</p>
<p>순서 </p>
<ol>
<li>python  센서 동작 확인 </li>
<li>user space 동작 확인 </li>
<li>kernel space 디바이스 드라이버 구현 </li>
<li>데몬 프로세스 전환 및 통신 확인 . </li>
</ol>
<p>으로 개발을 진행했습니다. </p>
<h1 id="rc522-코드-구현-리뷰-데이터시트-근거-매핑">RC522 코드 구현 리뷰 (데이터시트 근거 매핑)</h1>
<h2 id="1-리뷰-목적">1. 리뷰 목적</h2>
<p><code>src/rc522_full_demo.c</code>와 <code>src/rc522_full.c</code>가 MFRC522 데이터시트의 어떤 동작/규칙을 근거로 구현되었는지 정리한다.</p>
<p>참고:</p>
<ul>
<li>워크스페이스에서 <code>SZH-EK0404.pdf</code> 파일은 현재 확인되지 않았다.</li>
<li>따라서 본 문서는 <strong>MFRC522 표준 데이터시트 규격(명령/레지스터/프레임 규칙)</strong> 기준으로 매핑했다.</li>
<li>PDF가 동기화되면 마지막 섹션의 &quot;페이지 매핑 표&quot;에 정확한 페이지/섹션 번호를 채우면 된다.</li>
</ul>
<hr>
<h2 id="2-대상-파일">2. 대상 파일</h2>
<ul>
<li><code>src/rc522_full.c</code> (핵심 프로토콜/레지스터 구현)</li>
<li><code>src/rc522_full_demo.c</code> (CLI 데모/사용자 인터페이스)</li>
<li><code>src/rc522_full.h</code> (공개 API)</li>
</ul>
<hr>
<h2 id="3-데이터시트-근거와-코드-매핑">3. 데이터시트 근거와 코드 매핑</h2>
<h3 id="31-spi-레지스터-readwrite-프레임">3.1 SPI 레지스터 Read/Write 프레임</h3>
<p>데이터시트 근거:</p>
<ul>
<li>주소 프레임에서 <code>addr</code>는 <code>(addr &lt;&lt; 1) &amp; 0x7E</code> 형태</li>
<li>Read는 MSB(0x80) set</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_write_reg()</code>에서 <code>(addr &lt;&lt; 1) &amp; 0x7E</code></li>
<li><code>rc522c_read_reg()</code>에서 <code>((addr &lt;&lt; 1) &amp; 0x7E) | 0x80</code></li>
</ul>
<p>검토 결과:</p>
<ul>
<li>데이터시트 SPI 접근 규칙과 일치.</li>
</ul>
<h3 id="32-리셋-및-초기화-시퀀스">3.2 리셋 및 초기화 시퀀스</h3>
<p>데이터시트 근거:</p>
<ul>
<li><code>CommandReg</code>에 <code>PCD_RESETPHASE(0x0F)</code>로 소프트리셋</li>
<li>타이머/모드/ASK/안테나 관련 레지스터 초기 설정 필요</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_reset()</code>:<ul>
<li>GPIO RST 토글(옵션)</li>
<li><code>CommandReg &lt;- PCD_RESETPHASE</code></li>
</ul>
</li>
<li><code>rc522c_init_chip()</code>:<ul>
<li><code>TModeReg=0x8D</code></li>
<li><code>TPrescalerReg=0x3E</code></li>
<li><code>TReloadRegL/H=30/0</code></li>
<li><code>TxAutoReg=0x40</code></li>
<li><code>ModeReg=0x3D</code></li>
<li><code>TxControlReg</code> bit0/1 set로 안테나 ON</li>
</ul>
</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>RC522 bring-up 시퀀스로 타당하며 Python <code>mfrc522</code> 계열 구현과도 정렬됨.</li>
</ul>
<h3 id="33-pcd_transceive-공통-루틴-tocard">3.3 PCD_TRANSCEIVE 공통 루틴 (<code>ToCard</code>)</h3>
<p>데이터시트 근거:</p>
<ul>
<li>IRQ enable 설정, FIFO clear, command 실행, <code>BitFramingReg</code> StartSend bit 제어</li>
<li><code>CommIrqReg</code>/<code>ErrorReg</code>로 완료/에러 판정</li>
<li><code>FIFOLevelReg</code>와 <code>ControlReg(lastBits)</code>로 수신 비트 길이 계산</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_to_card()</code>:<ul>
<li><code>CommIEnReg</code>, <code>CommIrqReg</code>, <code>FIFOLevelReg</code>, <code>CommandReg</code> 사용</li>
<li><code>PCD_TRANSCEIVE</code> 시 <code>BitFramingReg</code> bit7 set/clear</li>
<li><code>ErrorReg &amp; 0x1B</code> 검사</li>
<li><code>back_bits = (fifo-1)*8 + lastBits</code> 계산</li>
</ul>
</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>데이터시트 권장 처리 흐름과 부합.</li>
</ul>
<h3 id="34-reqawupa-카드-탐지">3.4 REQA/WUPA (카드 탐지)</h3>
<p>데이터시트 근거:</p>
<ul>
<li><code>PICC_REQIDL(0x26)</code> 전송</li>
<li>7-bit framing 요구 (<code>BitFramingReg=0x07</code>)</li>
<li>ATQA 응답 2바이트(16비트) 기대</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_request()</code>:<ul>
<li><code>BitFramingReg=0x07</code></li>
<li><code>req_mode</code> 1바이트 전송</li>
<li><code>back_bits == 0x10</code> 조건 확인</li>
</ul>
</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>REQA 처리 규칙을 정확히 반영.</li>
</ul>
<h3 id="35-anti-collision-uid-cl1">3.5 Anti-collision (UID CL1)</h3>
<p>데이터시트 근거:</p>
<ul>
<li><code>[0x93, 0x20]</code> 전송</li>
<li>UID 4바이트 + BCC 1바이트 = 총 40비트</li>
<li>BCC 검증 필요</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_anticoll()</code>:<ul>
<li><code>PICC_ANTICOLL</code>, <code>0x20</code> 전송</li>
<li><code>back_bits == 40</code> 확인</li>
<li><code>uid[0..3] XOR == uid[4]</code> BCC 검증</li>
</ul>
</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>데이터시트 anti-collision 규칙을 잘 반영.</li>
</ul>
<h3 id="36-select-tag-sak-획득">3.6 Select Tag (SAK 획득)</h3>
<p>데이터시트 근거:</p>
<ul>
<li>Select frame: <code>0x93 0x70 + UID(5) + CRC_A(2)</code></li>
<li>응답으로 SAK 수신</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_select_tag()</code>:<ul>
<li>위 프레임 구성</li>
<li><code>rc522c_calculate_crc()</code>로 CRC 생성</li>
<li>응답 비트 길이 <code>0x18</code> 확인 후 SAK 반환</li>
</ul>
</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>Select 프레임 구성 및 CRC 처리 타당.</li>
</ul>
<h3 id="37-mifare-classic-인증">3.7 MIFARE Classic 인증</h3>
<p>데이터시트 근거:</p>
<ul>
<li><code>PICC_AUTHENT1A(0x60)</code> 또는 <code>1B(0x61)</code></li>
<li>블록 주소 + 키6 + UID4 전송</li>
<li>성공 후 <code>Status2Reg.MFCrypto1On</code> 확인</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_authenticate()</code>:<ul>
<li>12바이트 인증 프레임 구성</li>
<li><code>PCD_AUTHENT</code> 실행</li>
<li><code>Status2Reg &amp; 0x08</code> 체크</li>
</ul>
</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>인증 시퀀스가 데이터시트와 정합.</li>
</ul>
<h3 id="38-블록-read">3.8 블록 READ</h3>
<p>데이터시트 근거:</p>
<ul>
<li><code>[PICC_READ(0x30), block] + CRC_A</code></li>
<li>응답은 16바이트 데이터(+CRC_A 2바이트)</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_read_block()</code>:<ul>
<li>READ 프레임 + CRC 전송</li>
<li><code>back_bits &gt;= 128</code> 최소 조건 확인</li>
<li>앞 16바이트를 데이터로 사용</li>
</ul>
</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>실장 관점에서 합리적(데이터 16바이트 중심 처리).</li>
</ul>
<h3 id="39-블록-write">3.9 블록 WRITE</h3>
<p>데이터시트 근거:</p>
<ul>
<li>1단계: <code>[PICC_WRITE(0xA0), block] + CRC_A</code></li>
<li>태그 ACK는 4-bit <code>0x0A</code></li>
<li>2단계: <code>16-byte data + CRC_A</code></li>
<li>재차 ACK(4-bit <code>0x0A</code>) 확인</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_write_block()</code>:<ul>
<li>2단계 전송 구현</li>
<li>각 단계마다 <code>back_bits == 4</code> 및 <code>(ack &amp; 0x0F) == 0x0A</code> 검사</li>
</ul>
</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>MIFARE write handshake를 정확히 구현.</li>
</ul>
<h3 id="310-crypto-종료">3.10 Crypto 종료</h3>
<p>데이터시트 근거:</p>
<ul>
<li>인증 종료 후 <code>MFCrypto1On</code> clear 필요</li>
</ul>
<p>코드 매핑:</p>
<ul>
<li><code>rc522c_stop_crypto1()</code>에서 <code>Status2Reg</code> bit3 clear</li>
</ul>
<p>검토 결과:</p>
<ul>
<li>인증 세션 정리 동작 정상.</li>
</ul>
<hr>
<h2 id="4-rc522_full_democ-리뷰">4. <code>rc522_full_demo.c</code> 리뷰</h2>
<p>구현 개요:</p>
<ul>
<li><code>--id</code>: UID만 출력 (<code>rc522c_read_id_blocking</code>)</li>
<li>기본: 섹터 텍스트 읽기 (<code>rc522c_read_text_sector_blocking</code>)</li>
<li><code>--write</code>: 섹터 텍스트 쓰기 (<code>rc522c_write_text_sector_blocking</code>)</li>
<li><code>--ch</code>, <code>--speed</code>, <code>--rst</code>로 환경 파라미터 조정 가능</li>
</ul>
<p>장점:</p>
<ul>
<li>데이터시트 레벨 저수준을 API로 캡슐화해서 사용성이 좋다.</li>
<li>bring-up/검증에 필요한 옵션이 CLI로 열려 있어 실험하기 편하다.</li>
</ul>
<p>주의:</p>
<ul>
<li>blocking 방식이라 태그가 없으면 계속 대기한다.</li>
<li><code>--trailer</code> 값 유효성은 라이브러리에서 추가 검증한다.</li>
</ul>
<hr>
<h2 id="5-코드-품질리스크-리뷰-개선-제안">5. 코드 품질/리스크 리뷰 (개선 제안)</h2>
<p>1) <strong>Select 결과 미검증</strong></p>
<ul>
<li>위치: <code>rc522c_read_text_sector_blocking()</code>, <code>rc522c_write_text_sector_blocking()</code></li>
<li>현재 <code>rc522c_select_tag(uid5)</code> 반환값(SAK)을 검사하지 않음</li>
<li>제안: <code>&lt;=0</code>이면 즉시 실패 처리</li>
</ul>
<p>2) <strong>무한 블로킹 정책</strong></p>
<ul>
<li>위치: <code>rc522c_read_id_blocking()</code>, read/write blocking 루프</li>
<li>장시간 태그 미접근 시 복귀 없음</li>
<li>제안: timeout 버전 API 추가 (<code>*_timeout_ms</code>)</li>
</ul>
<p>3) <strong>기본 키(A=FF..FF) 고정</strong></p>
<ul>
<li>보안상 취약하며 실카드에서 실패 빈도 증가 가능</li>
<li>제안: API로 Key A/Key B 주입 가능하도록 확장</li>
</ul>
<p>4) <strong>문자열 변환 단순 복사</strong></p>
<ul>
<li>위치: <code>rc522c_read_text_sector_blocking()</code></li>
<li>바이너리 데이터/중간 NUL 포함 시 문자열 해석이 깨질 수 있음</li>
<li>제안: raw 48-byte API 추가 + 상위에서 인코딩 처리</li>
</ul>
<p>5) <strong>응답 CRC 검증 생략</strong></p>
<ul>
<li>현재는 RC522 내부 CRC 계산 송신에는 사용하나, 수신 데이터 CRC 검증은 미실시</li>
<li>제안: 필요 시 수신 CRC 검증 옵션 추가</li>
</ul>
<hr>
<h2 id="6-pdf-페이지-매핑-템플릿-추후-채우기">6. PDF 페이지 매핑 템플릿 (추후 채우기)</h2>
<p><code>SZH-EK0404.pdf</code> 동기화 후 아래 표에 페이지/섹션 번호를 넣으면 문서 완성도가 높아진다.</p>
<table>
<thead>
<tr>
<th>코드 항목</th>
<th>데이터시트 키워드</th>
<th>PDF 페이지/섹션</th>
</tr>
</thead>
<tbody><tr>
<td>SPI read/write 프레임</td>
<td>SPI interface, address byte format</td>
<td>TODO</td>
</tr>
<tr>
<td><code>CommandReg</code> reset/init</td>
<td>PCD_RESETPHASE, initialization</td>
<td>TODO</td>
</tr>
<tr>
<td><code>rc522c_request</code></td>
<td>REQA/WUPA, 7-bit frame</td>
<td>TODO</td>
</tr>
<tr>
<td><code>rc522c_anticoll</code></td>
<td>Anti-collision CL1, BCC</td>
<td>TODO</td>
</tr>
<tr>
<td><code>rc522c_select_tag</code></td>
<td>Select command, SAK</td>
<td>TODO</td>
</tr>
<tr>
<td><code>rc522c_authenticate</code></td>
<td>MIFARE auth A/B, Crypto1</td>
<td>TODO</td>
</tr>
<tr>
<td><code>rc522c_read_block</code></td>
<td>MIFARE Read command</td>
<td>TODO</td>
</tr>
<tr>
<td><code>rc522c_write_block</code></td>
<td>MIFARE Write + 4-bit ACK</td>
<td>TODO</td>
</tr>
<tr>
<td><code>rc522c_stop_crypto1</code></td>
<td>MFCrypto1On bit clear</td>
<td>TODO</td>
</tr>
</tbody></table>
<hr>
<h2 id="7-결론">7. 결론</h2>
<ul>
<li>현재 <code>rc522_full.c</code> 구현은 MFRC522/MIFARE Classic 핵심 프로토콜(REQA, anticoll, select, auth, read/write, ACK 규칙)에 대체로 잘 맞는다.</li>
<li>특히 ACK를 4-bit로 처리하고 BCC 검증을 수행하는 점은 데이터시트 정합성 측면에서 중요하고 올바른 구현이다.</li>
<li>제품화 단계에서는 timeout/키 관리/SAK 검증/CRC 검증을 보강하면 안정성과 재현성이 더 좋아진다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2월 3주차 올데이프로젝트 Book Review ]]></title>
            <link>https://velog.io/@physical-100/2%EC%9B%94-3%EC%A3%BC%EC%B0%A8-%EC%98%AC%EB%8D%B0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Book-Review</link>
            <guid>https://velog.io/@physical-100/2%EC%9B%94-3%EC%A3%BC%EC%B0%A8-%EC%98%AC%EB%8D%B0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Book-Review</guid>
            <pubDate>Sun, 22 Feb 2026 07:15:25 GMT</pubDate>
            <description><![CDATA[<p>설에 부산으로 내려가는 ktx에서의 시간을 활용하여 <code>부의 전략 수업</code> 을 다 읽었습니다 ..</p>
<p>부를 쌓게 해주는 방법이 담긴 책이라기 보다는 자본을 바라보는 시각. 인생을 살아가며 지녀야할 태도에 대해 배울 수 있었습니다. </p>
<h3 id="돈과-삶의-원칙">돈과 삶의 원칙</h3>
<ol>
<li>돈은 우리를 옭아맬 수 있는 굴레이다. 돈과 함께 잘 살아가기 위해서는 전략이 필요하다. </li>
<li>우리는 돈을 통해 안정감을 얻고 싶어하지만 돈은 결코 안정감을 보장해주지 않는다 .<br><u><strong>통제할 수 없는 것에 매달리지 말고 통제할 수 있는 것,  즉 마인드셋에 집중하라.</strong></u></li>
</ol>
<h3 id="투자와-자산관리">투자와 자산관리</h3>
<ol>
<li><p>나쁜 상황은 언제든 벌어질 수 있다 .  따라서 여유있는 오차범위를 확보하고 &#39;위험이 없는 상태&#39;를 명확히 인지하라 .</p>
</li>
<li><p>부채는 도구다 .  잘 사용하면 유용하지만  잘못 쓰면 발목을 잡는다.</p>
</li>
<li><p>돈은 결국 중앙 은행에서 나온다. 중앙 은행의 통화 정책 변화는 곧바로 내 소득과 저축에 영향을 미친다. </p>
</li>
<li><p>저축은 현금 , 주식 , 채권 , 부동산으로 이루어지며 각각의 기본 원리를 이해해야한다. </p>
</li>
<li><p>포트폴리오는 여러 자산을 모아 놓은 것이며 위험을 가능한 균형있게 분산해야한다. </p>
</li>
<li><p>자신에게 맞는 투자 철학을 찾거나 스스로 구축하자 </p>
<pre><code> 나는 약간 개별 가치주에 투자를 하거나 사이클에 따라 균형을 맞출 수 있는 투자 전략을 수립하자 </code></pre></li>
</ol>
<h3 id="은퇴와-그-이후">은퇴와 그 이후</h3>
<ol>
<li>일을 그만 둘 수 있는 시점은 단순하다.  내가 가진돈 / 앞으로 살 날 이 예상 지출 보다 많을 때 가능하다. </li>
<li>건강이 곧 자산이다. </li>
<li>돈에 대한 조언을 맹신하지 말고 끝없이 의심하라 . </li>
</ol>
<hr>
<p>채권의 원리에 대해서 간략히 이해했지만 아직은 어렵다 조금더 공부하자. </p>
<pre><code>모든 시장에는 미래 기대 가치가 반영된 가격이 존재한다 </code></pre><p>   이를 알고 투자에 임하자 . </p>
<p>   나는 부채는 단순히 좋지 않은 것으로 생각했다 .
   하지만 <code>시중 금리</code>가 4%이고 <code>인플레이션</code>이 5%라면 돈을 빌리는 것이 이득이다 ..?? 흠 조금 더 알아보자 .</p>
<h3 id="레이달리오의-올웨더-투자전략">레이달리오의 올웨더 투자전략</h3>
<ul>
<li><p>미국 주식 : 25%</p>
</li>
<li><p>장기 인플레이션 연계 채권  : 25%</p>
</li>
<li><p>장기 명목 채권(20년 이상) :  25%</p>
</li>
<li><p>해외 주식 : 15%</p>
</li>
<li><p>원자재 : 10% </p>
<p>이는 예시일 뿐 상황에 맞게 전략적으로 구성할 것 !</p>
</li>
</ul>
<h4 id="명목-채권과-인플레이션-연계-채권의-차이가-무엇인가-">명목 채권과 인플레이션 연계 채권의 차이가 무엇인가 ?</h4>
<table>
<thead>
<tr>
<th>항목</th>
<th>명목 채권 (Nominal Bonds)</th>
<th>인플레이션 연계 채권 (Inflation-Linked Bonds)</th>
</tr>
</thead>
<tbody><tr>
<td><strong>정의</strong></td>
<td>원금과 이자가 고정된 명목 금액으로 지급되는 채권</td>
<td>원금과 이자가 실제 인플레이션(물가상승률)에 따라 조정되는 채권</td>
</tr>
<tr>
<td><strong>원금 지급 방식</strong></td>
<td>만기 시 고정된 명목 원금(예: 100만원) 그대로 지급</td>
<td>원금이 CPI(소비자물가지수) 등에 연동되어 인플레이션만큼 증가 (디플레이션 시 감소 가능)</td>
</tr>
<tr>
<td><strong>이자(쿠폰) 지급 방식</strong></td>
<td>고정된 명목 이자율 적용 (예: 연 3% → 매년 3만원)</td>
<td>고정된 <strong>실질 이자율</strong>을 인플레이션 조정된 원금에 적용 (이자도 물가 상승분만큼 증가)</td>
</tr>
<tr>
<td><strong>실질 수익률</strong></td>
<td>변동 (인플레이션이 높아지면 실질 구매력 ↓)</td>
<td>거의 고정 (인플레이션 영향 제거 → 실질 수익률 확정)</td>
</tr>
<tr>
<td><strong>명목 수익률</strong></td>
<td>고정</td>
<td>변동 (인플레이션 높을수록 명목 수익 ↑)</td>
</tr>
<tr>
<td><strong>인플레이션 위험</strong></td>
<td>있음 (예상보다 높은 인플레이션 → 실질 손실)</td>
<td>거의 없음 (인플레이션 위험 헷지 가능)</td>
</tr>
<tr>
<td><strong>인플레이션 발생 시 성과</strong></td>
<td>불리 (실질 가치 하락)</td>
<td>유리 (원금·이자 모두 증가)</td>
</tr>
<tr>
<td><strong>인플레이션 하락/디플레이션 시 성과</strong></td>
<td>유리 (실질 가치 상승)</td>
<td>불리 (원금·이자 감소 가능)</td>
</tr>
<tr>
<td><strong>발행 금리 비교</strong></td>
<td>높음 (기대 인플레이션 포함)</td>
<td>낮음 (실질 금리만 반영, 기대 인플레이션 제외)</td>
</tr>
<tr>
<td><strong>Break-even Inflation Rate</strong></td>
<td>—</td>
<td>명목 채권 수익률 - 연계 채권 실질 수익률 = 시장의 기대 인플레이션율</td>
</tr>
<tr>
<td><strong>주요 용도</strong></td>
<td>안정적 명목 수익 추구, 금리 하락 시 자본이득 기대</td>
<td>인플레이션 헷지, 실질 구매력 보장 (퇴직연금 등 장기 자산에 적합)</td>
</tr>
<tr>
<td><strong>대표 상품 예시</strong></td>
<td>일반 국고채, 회사채</td>
<td>미국 TIPS, 한국 물가연동국채, 영국 Index-Linked Gilts 등</td>
</tr>
<tr>
<td><strong>기타 특징</strong></td>
<td>유동성 높음, 시장 규모 큼</td>
<td>유동성 상대적으로 낮음, 디플레이션 시 원금 하한 설정 국가 있음 (한국은 보통 하한 100%)</td>
</tr>
</tbody></table>
<p>이것으로 부의 전략 수업 리뷰를 마치겠습니다!!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2월 2주차 올데이프로젝트 - Book Review]]></title>
            <link>https://velog.io/@physical-100/2%EC%9B%94-2%EC%A3%BC%EC%B0%A8-%EC%98%AC%EB%8D%B0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Book-Review</link>
            <guid>https://velog.io/@physical-100/2%EC%9B%94-2%EC%A3%BC%EC%B0%A8-%EC%98%AC%EB%8D%B0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Book-Review</guid>
            <pubDate>Sun, 15 Feb 2026 14:59:42 GMT</pubDate>
            <description><![CDATA[<p>이번주는 항공우주 취업 스터디 김지오 스터디장의 도움을 받아 <code>쎄트렉아이</code>를 읽고 리뷰를 작성하려고 했지만 80여 페이지를 읽은 가량에 반납 이슈로 책을 멈추어 두가지 책을 읽은 끄적 끄적 거린 내용을 작성해보도록 하겠습니다. </p>
<h3 id="쎄트렉아이">쎄트렉아이</h3>
<h4 id="-p--82">~ p- 82</h4>
<p>초반의 내용은  전반적으로 대한민국의 인공위성 개발 역사에 대한 내용이었다. 기존의 쎄트렉 아이 창업자의 인공 위성 개발 과정. </p>
<p>그렇지만 본격적인 개발 내용 보다는 고군분투기가 담겨있었다. 
불모지에서 해외 개발을 통해 첫 발사를 시작한 성공 이야기 . 그럼에도 국산화가 아니라는 이유로 해외의 기술이라 무시 받고 미약하게나마 정치, 시사적으로 얽힌 이야기들. </p>
<p>원래 우리가 아는 굵직한 대기업들에서도 항공 우주에 관심을 가지고 파이를 넓혀가고 있었다( 삼성, 현대 등등) </p>
<p>하지만 IMF의 위기를 맞으며 경영 리스크를 해소하기 위해서 기존의 연구 인력들과 사업체들은 한국 우주 항공 산업에 병합 되었다는 스토리를 들으며 IMF라는 사건이 아니었다면 지금 한국의 우주항공 기술은 더 발전하지 않았을까 하는 아쉬움을 가지게 되었다. 그리고 인공위성 연구센터와 한국 항공 우주 산업의 대립을 보며 기술의 발전을 막는 것은 의외로 기술의 한계가 아닐 수 있겠다는 생각도 하게 되었다 . </p>
<p>인공 위성의 기술 자체에 대한 내용보다는 저자의 일대기를 생생하게 들은 경험이라 아쉬움도 남지만 그래도 발사체, 그리고 테스트 과정에 대해 간략하게나마 체험을 할 수 있어 의미 있었던 시간이었다 . </p>
<p>추가적으로 불모지에서 희망을 가지고 나아가는 연구원들에게 역할자체는 크게 의미가 없고 다양한 role을 수행하며 본인의 한계 이상을 해내려는 태도를 다시금 배웠다. </p>
<h3 id="부의-전략-수업">부의 전략 수업</h3>
<p>지난 번에 이어서 마저 읽으며 조금이지만 정리를 한다. </p>
<blockquote>
<p>모든 시도는 하나의 도전이다 .</p>
</blockquote>
<ul>
<li>돈은 성공의 절대적인 척도가 아니다 . </li>
</ul>
<p>어떤 길을 선택하든 시스템이 어떻게 동작하는지 명확히 파악해야한다 .
어떤 형태로든 우리는  계층 속에 존재하고 어떤 계층에 존재할지는 선택하지만 계층에서 나를 받아줄지를 확인해야한다 .</p>
<ul>
<li><p>조직에서 살아남기</p>
<ul>
<li><p>정치 :  능숙한 사람은 전혀 개입하지 않는 듯해 보인다.</p>
</li>
<li><p><del>좋아하는 일을 하라</del></p>
<p>  ⇒ 남들이 반드시 필요로 하는 일을 하라 . 
  하지만 필요 정도는 주관적이기에 공정한 보상을 보장 받지는 못한다 .
인간은 어떻게든 계층에 속하며 어떤 계층에 존재할지는 본인이 선택할 수 있다.
는 내용이 인상 깊었다. 하지만 선택으로 계층에 남는 것이 아니라 계층의 이동에는 그에 따른 노력이 또한 필요하다. </p>
</li>
</ul>
</li>
</ul>
<p>가장 상위 계층에서 기존 사회의 시스템을 깨부수기 위해 항상 의심하고 탐구하는 사람이 되겠다고 다짐. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 16주차 기록 ]]></title>
            <link>https://velog.io/@physical-100/VEDA-16%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@physical-100/VEDA-16%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Sun, 15 Feb 2026 14:42:44 GMT</pubDate>
            <description><![CDATA[<h3 id="프로젝트-주제-">프로젝트 주제 ?</h3>
<p>본격적으로 개발이 시작되었습니다. 멘토링과 주제 회의를 거듭한 끝에
지하철 부정 승차 탐지를 위한 시스템 개발을 목표로 파이널 프로젝트를 시작했습니다. </p>
<p>유럽 및 북미 그리고 한국에서도 공통적으로 발생하는 문제이기도 했고 CCTV와 임베디드적으로 흥미로운 솔루션이 되리라 기대하고 있습니다. 
초기 회의에서 왜?라는 의문을 가지고 해결법에 대한 접근을 이어가다 보니 어느 정도 구현 기능 명세를 완성할 수 있었습니다. </p>
<h3 id="역할--디바이스-드라이버-및-시스템-아키텍처">역할 : 디바이스 드라이버 및 시스템 아키텍처</h3>
<p>역할 분담을 진행하며 저는 디바이스 드라이버 및 하드웨어 구현을 담당하게 되었습니다. </p>
<p>16주차에는 전체적인 하드웨어 &amp; 소프트웨어 동작 흐름을 설계하고 필요한 부품들을 주문했습니다. 
<img src="https://velog.velcdn.com/images/physical-100/post/9dc52582-3c09-41a8-9a5e-138fd715de67/image.png" alt=""></p>
<p>라즈베리 파이 4와 RFID, 스피커 모듈 구성도. </p>
<p>프로젝트 팀 별로 10만원의 부품 구매 비용이 지원되는데 구매에 여러 조건이 별도로 있어 대안을 찾고 가능성을 비교하다 보니 생각보다 주문에 시간이 걸렸습니다 . 
<del>( VEDA 4기 부터는 20만원으로 상향 되었다는 소문이 ... 제발 우리도 추가적으로 지원해다오 ... 😭😭)</del></p>
<p>RFID 모듈을 사용하여 카드의 정보를 파악하고 CCTV에서의 승객의 연령 추정을 통해 부정 승차자를 감지하는 초기 컨셉을 기반으로 개발을 시작했습니다. </p>
<h3 id="하지만--부품-도착-전-디바이스-드라이버-개발자는-무엇을-할-수-있을까">하지만 .. 부품 도착 전 디바이스 드라이버 개발자는 무엇을 할 수 있을까..?</h3>
<p>를 고민하며 QT UI를 앞서 완성하기로 결정했습니다. </p>
<p>클라이언트 초기 요구 사항을 기반으로 상세 화면들을 만들었습니다. </p>
<p>그렇다면 오늘은 AI를 활용한 Qt 디자인에 대한 내용을 다뤄보겠습니다. </p>
<h3 id="디자이너는-아니지만-가능하다">디자이너는 아니지만 가능하다!</h3>
<h4 id="ai를-이용한-qt-디자인">AI를 이용한 qt 디자인.</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/df42833e-5467-4567-bb61-b8b0c78aee5f/image.png" alt=""></p>
<p>이는 초기 회의에서 도출된 클라이언트 아키텍쳐입니다.( 해당 이미지는 <u>서형철 팀원</u>에 의해 작성되었습니다. professional expert of 그림판. ) </p>
<p>그러면 해당 이미지를 바탕으로 client 디자인을 뽑아내보도록 하겠습니다 .</p>
<h4 id="examples">Examples</h4>
<pre><code class="language-text">- 화면 A : 메인 모니터링 대시보드 (Main Monitoring)

실시간 CCTV 영상과 통계 요약을 한눈에 볼 수 있는 메인 화면

    - 실시간 스트리밍 뷰
        - 영상 조작 : 슬라이더를 이용한 실시간 밝기 조절, 마우스 휠을 이용한 디지털 줌(확대/축소) 기능.
        - 오버레이 : 부정 승차 의심자 감지 시 영상 위에 빨간색 바운딩 박스(Bounding Box)와 &quot;Warning&quot; 표시.
    - 퀵 통계 배너: 금일 총 태그 수, 부정 승차 적발 건수, 적발률 등을 상단에 배치.

- 화면 B : 부정 승차 로그 및 상세 팝업 (Log &amp; Detail View)

기록된 데이터를 관리하고 검토

    - 로그 리스트 (QListView/QTableView)
            - `타임스탬프 | 카드 번호 | 카드 구분(노인/장애인 등) | 의심 사유` 형태의 목록.
        - 미확인 로그는 굵은 글씨나 배경색으로 강조.
    - 상세 정보 팝업 (QDialog): 로그 클릭 시 발생.
        - 좌측:적발 당시 캡처된 사진 및 5초 내외의 영상 클립 무한 루프 재생.
        -우측: 카드 정보(등록된 나이/성별) vs AI 판독 정보(추정 나이/성별) 비교 표기.

화면 C : 통계 및 분석 (Statistics &amp; Analysis)

데이터를 시각화

    - 차트 위젯 (Qt Charts)
           - 시간대별 적발 건수: 어느 시간대에 부정 승차가 많은지 라인 차트로 표시.
        - 역사별/게이트별 순위: 어느 구역에서 자주 발생하는지 바 차트로 표시.</code></pre>
<p>이렇게 간단한 프롬프트와 디자인 컨셉 , 색을 지정해서 디자인을 뽑아내도록 해보겠습니다.</p>
<h3 id="1ai-design-초안-생성">1.AI Design (초안 생성)</h3>
<p><code>Uizard</code> 나  <code>Sitich</code>를 활용하여 1차적으로 디자인을 뽑아냅니다.</p>
<ul>
<li><a href="https://uizard.io">Uizard </a><ul>
<li>초기 스케치나 텍스트를 통해 이미지를 생성할 수 있습니다 .</li>
<li>장점 :  각 디자인 요소별로 접근 및 수정할 수 있습니다.</li>
<li>단점 :  Pro plan을 활용해야 svg export 및 figma로 내보내기 등의 기능이 가능합니다. </li>
</ul>
</li>
<li><a href="https://stitch.withgoogle.com/">Sitich</a> <ul>
<li>동일하게 스케치나 텍스트 기반의 디자인 생성 가능합니다.</li>
<li>단점 :  개별적인 요소에 대한 접근이 다소 어렵습니다. </li>
<li>장점 :  Google studio를 통해 데모 버전 생성이 빠르고 code 형식의 내보내기가 가능합니다 </li>
</ul>
</li>
</ul>
<p>실제로 뽑아낸 디자인을 확인해보겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/64bf97ce-d871-4877-a3a4-37e490e70aac/image.png" alt=""></p>
<p>만족할 만한 디자인을 금방 금방 뽑낼 수 있고 너무 예상외의 퀄리티에 qt로 전환 작업을 하면서 이미 높아져버린 팀원들의 눈높이를 맞추기 위해 꽤나 고생했습니다.. 이것은 예상치 못한 단점 ...쿄쿄..ㅎㅎ </p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/bd5ba258-09f8-4f3b-b649-a88307d0ebfc/image.png" alt=""></p>
<p>이후에 생성된 이미지를 실제로 웹 기반의 프로그램으로 동작을 확인해볼 수 있습니다. </p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/859a3314-0b03-447a-b357-ab03caf988fa/image.png" alt=""></p>
<p>또한 코드상으로 어떻게 정의되어있는지를 확인해볼 수 있는데요 이 html 기반의 react 코드를 활용해서 qt 클라이언트를 만들어보겠습니다. </p>
<h4 id="1-ui-qt-widgets-vs-qml-qt-quick-차이점">1. <code>.ui</code> (Qt Widgets) vs <code>.qml</code> (Qt Quick) 차이점</h4>
<table>
<thead>
<tr>
<th><strong>구분</strong></th>
<th><strong>.ui (Qt Widgets)</strong></th>
<th><strong>.qml (Qt Quick)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>기반 언어</strong></td>
<td>C++ / XML</td>
<td>QML (선언적 언어) + JavaScript</td>
</tr>
<tr>
<td><strong>렌더링 방식</strong></td>
<td>CPU 중심 (Raster Paint Engine)</td>
<td><strong>GPU 중심 (Scene Graph)</strong></td>
</tr>
<tr>
<td><strong>주요 타겟</strong></td>
<td>정적인 데스크톱 애플리케이션</td>
<td><strong>동적/애니메이션 중심, 임베디드, 모바일</strong></td>
</tr>
<tr>
<td><strong>디자인 유연성</strong></td>
<td>기본 OS 스타일을 따름 (커스텀이 어려움)</td>
<td><strong>매우 자유로움 (웹처럼 화려한 UI 가능)</strong></td>
</tr>
<tr>
<td><strong>데이터 바인딩</strong></td>
<td>Signal &amp; Slot (수동 연결)</td>
<td><strong>자동 속성 바인딩 (Property Binding)</strong></td>
</tr>
</tbody></table>
<h4 id="2-왜-qml을-선택했는가-">2. 왜 qml을 선택했는가 ?</h4>
<p>① 실시간 데이터 시각화의 최적화 (GPU 가속)</p>
<p>QML은 모든 UI 요소를 그래픽 카드(GPU)를 통해 직접 렌더링하므로, 실시간 영상 스트리밍과 3D 맵 오버레이를 동시에 처리해도 시스템 성능에 영향을 거의 주지 않는다. 
-&gt; 데스크탑 기반의 클라이언트 </p>
<p>② 현대적이고 직관적인 UI 구현 (Web-friendly)</p>
<p>C++의 강력한 연산 능력과 JavaScript의 유연한 UI 처리를 결합할 수 있다.
<code>.ui</code> 방식으로는 구현하기 매우 까다로운 부드러운 화면 전환, 투명도 조절, 입체적인 그래프 등을 단 몇 줄의 코드로 구현할 수 있다.</p>
<p>그래서 qml 기반의 클라이언트 UI 구현을 진행했습니다..</p>
<p>초기에 Qt를 교육 과정에서 배울 때는 Qt creator 내에서 ui 파일로 디자인을 바로 확인할 수 있었습니다. 하지만 qml로 클라이언트 개발을 진행하면서는 미리 확인을 하지 못하고 빌드 후 실행 파일 동작을 통해서 화면을 확인할 수 있었습니다. 단순히 디자인 변경을 확인하기 위해 빌드와 화면 전환을 위한 시퀀스를 진행하는 것은 너무 비효율적이라고 느껴졌고 방안을 찾았습니다 . </p>
<h4 id="qmlsceneexe-을-통한-디자인-확인">qmlscene.exe 을 통한 디자인 확인</h4>
<p>탐색 결과 Qt에 내장된 qmlscence.exe를 통해서 디자인을 바로 바로 확인해볼 수 있었습니다. </p>
<pre><code class="language-shell"> C:\Qt\6.10.0\mingw_64\bin\qmlscene.exe  ..\qt_client_ui\src\Main.qml</code></pre>
<p>이렇게 디자인 하나하나씩을 확인해볼 수 있었습니다. </p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/b76a6702-7496-4f5e-aa7c-9ea60df3af86/image.png" alt=""></p>
<p>초기 디자인의 퀄리티에는 아직 못 미치지만 추후 기능 구현을 완료한 이후 디자인 디테일을 수정하도록 계획을 세우고 있습니다. </p>
<p>16주차 VEDA기록은 여기서 마무리하며 .</p>
<p>17주차에는 본격적인 디바이스 드라이버 구현 및 문제 해결을  위주로 기록을 이어나가보겠습니다 ..</p>
<p>모두들 새해 복 많이 받으세요<del>~</del></p>
<p><img src="https://velog.velcdn.com/images/physical-100/post/36624435-a7ed-46d5-b342-e538a72b8f9a/image.gif" alt=""></p>
<h4 id="추가적으로--17주차-맛보기">추가적으로 .. 17주차 맛보기</h4>
<p><img src="https://velog.velcdn.com/images/physical-100/post/8a72ac43-7b6e-42cc-83c4-fc961766851a/image.JPG" alt=""></p>
<p>아차차... 부품 구매 실수 ... ㅎㅎㅎ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2월 1주차 올데이프로젝트 - Book Review]]></title>
            <link>https://velog.io/@physical-100/2%EC%9B%94-1%EC%A3%BC%EC%B0%A8-%EC%98%AC%EB%8D%B0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Book-Review</link>
            <guid>https://velog.io/@physical-100/2%EC%9B%94-1%EC%A3%BC%EC%B0%A8-%EC%98%AC%EB%8D%B0%EC%9D%B4%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-Book-Review</guid>
            <pubDate>Sun, 08 Feb 2026 14:40:00 GMT</pubDate>
            <description><![CDATA[<p>간만에 책을 읽겠다는 목표를 세우고 책을 읽기 시작했습니다 .</p>
<p>부자가 되겠다는 일념으로 구매해두고 방치하던 책 부의 전략 수업을 읽어 보았습니다. 전체 회독은 아니지만 일부분을 기록으로 남기며 느낀 점을 정리해보겠습니다 .</p>
<img src  = "https://velog.velcdn.com/images/physical-100/post/c16b7f6e-1221-4baf-be3a-f1c0b5c34f88/image.png" width = 500 height = 500 >

<p>음냐 ... 오랜만에 책을 읽었더니 20페이지를 남짓.  기절하기 일보 직전의 자신을 발견할 수 있었습니다.,, 흠냐  그래도 꾸준히 독서를 통해서 집중력과 AI로 인해서 생각하는 것을 멈춘 자신에게 스트레스를 주도록 하겠습니다.
이런 스트레스도 필요해 자기 전에 생각날 거야. </p>
<h3 id="1-레이-달리오와의-만남-월가의-원칙주의자로부터-배운-돈의-철학">1. 레이 달리오와의 만남: 월가의 &#39;원칙주의자&#39;로부터 배운 돈의 철학</h3>
<p>저자 폴 포돌스키가 세계 최대 헤지펀드인 브리지워터 어소시에이츠에서 일하며 작가로 일하던 때와는 달리 인생, 삶의 경험이 바뀌는 경험을 묘사하고 있습니다. 
특히 <code>레이 달리오</code>와의 만남으로 구체적인 깨달음이 다가왔다. 달리오는 &quot;원칙(Principles)&quot;으로 유명한데, 저자는 그를 통해 돈이 단순한 숫자가 아니라 &#39;시스템&#39;과 &#39;심리&#39;의 산물이라는 걸 깨달았다. </p>
<p>나는 돈을 어떻게 생각하는가? 에 대한 고민을 할 수 있었던 part . </p>
<p>달리오의 접근법은 불확실성을 인정하고, 데이터를 기반으로 한 &#39;기계적 사고&#39;를 강조한다. 저자는 이 만남을 통해 &quot;돈은 안정감을 주지 않는다&quot;는 불편한 진실을 직면했다. 내가 지금 가지고 있는 이 불안정? 혹은 위기감은 돈에서 오는 것이 아닌가? 취업을 해서 경제 활동을 하면 안정감이 생기는 것이 아닌가? 라는 의문을 자아내게 되었습니다. </p>
<h3 id="2-국가-간-계층-구조-돈이-만드는-글로벌-피라미드">2. 국가 간 계층 구조: 돈이 만드는 &#39;글로벌 피라미드&#39;</h3>
<p>국가 간 경제 계층 구조가 꽤 세세하게 언급되는데 이에 대륙간 에너지 사용량을 표로 확인하면서 북미와 아프리카가 얼마나 차이가 나고 국가가 돈의 흐름에서 어떻게 &#39;계층화&#39;되는지를 확인할 수 있었다. </p>
<p>부유한 국가(미국처럼)는 자본과 기술이 집중돼 &#39;상위 계층&#39;을 형성하고, 개발도상국은 자원 의존으로 &#39;하위 계층&#39;에 머무른다. </p>
<p>이 구조는 단순히 GDP 차이가 아니라, &#39;권력과 기회&#39;의 불평등에서 비롯된다고 해요. 단순히 기회의 차이도 있지만 이를 불평하기 보다는 계층을 이동하기 위해 직시하고 본인의 습관을 다듬어야한다는 의미로 들렸다. </p>
<h3 id="3-산업-간-현금-흐름-돈이-흐르는-길을-따라가라">3. 산업 간 현금 흐름: 돈이 &#39;흐르는&#39; 길을 따라가라</h3>
<p>기술 산업(테크)이 에너지나 제조 산업으로부터 현금을 빨아들이는 메커니즘을 들죠. 초반부에서 헤지펀드 경험을 바탕으로, &quot;현금 흐름을 추적하면 미래를 예측할 수 있다&quot; </p>
<p>특히, 산업의 &#39;라이프사이클&#39;을 언급하는데, 성장기 산업(예: AI)은 현금을 유입하지만, 쇠퇴기 산업(전통 제조)은 유출된다고 한다. 이 흐름을 무시하면 개인 재무가 위험해진다고는 하지만 아직까지 나에게 와닿는 내용은 아니었던 것 같다. 하지만 읽으면서 IT 쪽?은 어떻게 될지 잠시나마 상상해보는 시간이 되었다. 현금이 어디로 가는지 파악하고 도움이 될만한 커리어를 쌓을지 아니면 하고 싶은 분야로 도전을 이어갈지 고민하게 되었다.</p>
<h3 id="돈의-주인이-되는-시스템-구축">돈의 주인이 되는 &#39;시스템&#39; 구축</h3>
<p>개인 습관과 행동 전략 : 저자는 &quot;돈은 습관의 결과물&quot;이라고 단언한다. 
예를 들어, 저축이나 소비 패턴이 &#39;자동화&#39;되지 않으면, 감정적 충동에 휘말린다는 거죠. 달리오의 영향으로, &#39;스스로 생각하는 법&#39;을 강조하면서, 불확실성 속에서 &quot;움직이는&quot; 방법을 배울 수 있었다. 바로 적용하기는 쉽지 않겠지만 그럼에도 앞으로 나아가자 ..</p>
<hr>
<p>그러면 1주차 독서 기록은 여기서 마치도록 하겠습니다.</p>
<p>더 나은 리뷰와 생생한 본인의 생각을 가지고 돌아오도록 하겠습니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[VEDA 15주차 기록]]></title>
            <link>https://velog.io/@physical-100/VEDA-15%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</link>
            <guid>https://velog.io/@physical-100/VEDA-15%EC%A3%BC%EC%B0%A8-%EA%B8%B0%EB%A1%9D</guid>
            <pubDate>Sun, 08 Feb 2026 14:10:52 GMT</pubDate>
            <description><![CDATA[<p>15주차에는 본격적으로 프로젝트가 시작되었습니다. </p>
<h3 id="한화비전-체험관">한화비전 체험관</h3>
<p>월요일에는 최종 프로젝트 팀 발표와 함께 아이디어 구상을 위한 회의가 주어졌습니다!</p>
<p>처음 팀이 발표되었을때 살짝의 헤프닝이 있었는데요 .. 예상과 다른 팀으로 발표가 되었고 살짝 기쁠 뻔 했지만 얼굴이 허옇게 질린 정근 쨔응의 분주한 노력으로 인해 팀은 정상화되었습니다. </p>
<p>한화 비전 체험관에서는 현재 한화비전의 기술력과 타겟 국가 및 서비스를 위주로 체험해 볼 수 있었는데요 ... 주제를 정하면서 많은 도움이 되었던 것 같습니다. 상세한 체험기는 또 기밀이라 이게 암튼 크흠 ..ㅠ </p>
<h3 id="프로젝트">프로젝트.</h3>
<p>15주차에는 주로 기획 위주로 팀원들과 많은 얘기를 나누었습니다. 처음에는 그냥 해보고 싶은 아이디어 위주로 제가 많은 의견을 제시했지만 VEDA PM님께 피드백을 받으며 양쪽 어깨가 다 부서져버렸습니다.🤪🤪 </p>
<p>AI개발이 아니면서 한화 비전의 CCTV를 활용할 수 있는 프로젝트 . </p>
<p>그러면서 임베디드 교육 목적에 충실하게 임베디드 요소를 녹여낼 수 있는 무언가 .</p>
<p>사실상 6회차의 조들 중에서는 가장 주제를 늦게 선정한 팀이었습니다. </p>
<p>주제는 다음 주차 기록에 공개하겠으니 궁금한 사람은 1주일 기다리시라!!!</p>
<p>아무튼 재미있는 요소들과 조금은 구현이 힘들 것 같은 요소들을 섞어서 기획서를 제출하고 나니 이번주는 다소 내용이 빈약하다고 할 것 같습니다.  </p>
<p>그래서 협업을 위한 깃허브 사용법을 정리해보도록 하겠습니다.
반응이 좋다면 Jira 까지도 ... </p>
<h2 id="git으로-협업하기-">git으로 협업하기 .</h2>
<h3 id="1-monorepo-vs-multi-repo-→-우리는-umonorepo-u선택">1. Monorepo vs Multi-Repo? → 우리는 <u>Monorepo </u>선택</h3>
<p>처음에는 각자 repo를 따로 만들었습니다.
(QT Client repo, Server repo, STM32 repo…).
근데 실제로 코드를 통합 테스트하려면 repo 4개를 다 클론해야 하고, 공통 프로토콜 바뀌면 4개의 코드를 모두 변경해야한다는 문제가 발생할 수 있었습니다. </p>
<p><strong>그래서 결정했습니다.</strong></p>
<p>하나의 monorepo로 통합하자!
현재 repo 구조 예시:</p>
<pre><code class="language-text">Project/
├── hardware/
│   └── stm32-rfid-laser/          # STM32CubeIDE 프로젝트
├── server/                        # Raspberry Pi Python 서버 + OpenCV
├── client/                        # QT C++ 클라이언트
├── shared/                        # 공통 프로토콜, config, utils
├── docs/                          # 기획서, 아키텍처 다이어그램
├── tests/                         # 통합 테스트
└── .github/workflows/             # CI/CD</code></pre>
<p>하나의 repo에서 전체 시스템을 볼 수 있어서 디버깅도, 리팩토링도 훨씬 수월해졌습니다.</p>
<h3 id="2-브랜치-전략-github-flow-develop-브랜치-없음">2. 브랜치 전략: GitHub Flow (develop 브랜치 없음!)</h3>
<p>팀이 작아서 복잡한 브랜치 전략을 적용하기로 했습니다. </p>
<h4 id="규칙-요약">규칙 요약</h4>
<p>main 브랜치 = 항상 배포 가능 + protected (직접 push 금지)
모든 작업은 새 브랜치에서 시작</p>
<pre><code>브랜치 이름 형식: {type}/{이슈번호}-{짧은-설명}</code></pre><table>
<thead>
<tr>
<th>타입</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td>feature/</td>
<td>feature/123-camera-age-gender-analysis</td>
</tr>
<tr>
<td>fix/</td>
<td>fix/89-server-uart-timeout</td>
</tr>
<tr>
<td>refactor/</td>
<td>refactor/67-simplify-rtsp-handler</td>
</tr>
<tr>
<td>docs/</td>
<td>docs/112-update-architecture-diagram</td>
</tr>
<tr>
<td>chore/</td>
<td>chore/15-setup-github-actions</td>
</tr>
</tbody></table>
<h3 id="3-커밋-메시지-conventional-commits">3. 커밋 메시지: Conventional Commits</h3>
<p>커밋 메시를 통일해 팀원간의 원활한 git code 리뷰를 위해서 <code>Conventional Commits</code>를 도입했습니다.</p>
<h4 id="기본-형식">기본 형식:</h4>
<pre><code>&lt;type&gt;[scope]: &lt;짧은 설명&gt;


[본문 - 자세한 설명]

[footer - Closes #123 등]</code></pre><h4 id="주요-타입">주요 타입</h4>
<ul>
<li>feat : 새로운 기능</li>
<li>fix : 버그 수정</li>
<li>refactor : 코드 구조 개선</li>
<li>docs : 문서 수정</li>
<li>test : 테스트 추가</li>
<li>chore : 빌드/설정/잡일</li>
</ul>
<h4 id="예시">예시:</h4>
<pre><code class="language-text">feat(server): implement age-gender validation logic

- Load pre-trained AgeNet &amp; GenderNet models
- Compare RFID card type with camera result
- Add configurable threshold in config.yaml

Closes #123</code></pre>
<p>chore 예시 (monorepo 초기 세팅):</p>
<pre><code class="language-text">chore(repo): bootstrap SFEPS monorepo

Initialize directory structure for hardware, server, client, shared, docs, tests.
Add CONTRIBUTING.md with branch &amp; commit rules.
Create .github/workflows skeleton.</code></pre>
<h3 id="4-main-브랜치-보호-branch-protection-rule">4. main 브랜치 보호 (Branch Protection Rule)</h3>
<p>GitHub Settings → Branches → Add branch protection rule</p>
<ul>
<li>Branch name pattern: main</li>
<li>Require a pull request before merging → 체크 (직접 push 차단!)</li>
<li>Require approvals → 1명 이상</li>
<li>Dismiss stale approvals when new commits are pushed → 체크</li>
</ul>
<p>main은 최대한 보호호가 위해서 protection rule을 설정했습니다. </p>
<h3 id="5-pull-request--merge-규칙">5. Pull Request &amp; Merge 규칙</h3>
<ol>
<li>이슈 생성 → assignee 지정</li>
<li>브랜치 생성 → 작업</li>
<li>PR 생성 → 제목은 Conventional Commits 스타일로</li>
<li>최소 1명 리뷰 → Approve 후 Squash &amp; Merge 추천 (히스토리 깔끔)</li>
<li>브랜치 자동 삭제 체크</li>
</ol>
<hr>
<h4 id="이렇게-공통의-rule을-프로젝트를-본격적으로-시작하기-전에-합의했는데요">이렇게 공통의 rule을 프로젝트를 본격적으로 시작하기 전에 합의했는데요..</h4>
<p>앞으로 프로젝트를 진행해나가면서 어떤 어려움이 있는지 가장 어려운 것은 무엇인지 git으로 협업하는 방법을 더 업데이트하도록 하겠습니다. </p>
<img src  = "https://velog.velcdn.com/images/physical-100/post/56b1adfc-7619-4bd9-9667-be980c16b77c/image.JPG" width = 400 height = 500 >


<p>미우나 고우나 팀원이겠죠.....? 
프로젝트가 시작한지 2주차를 접어들어가는 이 시점에도 묵묵히 git을 공부하는 한 친구가 있습니다. .. 미운 놈 떡하나 더 준다고...
내일은 그에게 떡을 줘야겠어요. 😩😩</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Sentry Turret System -2]]></title>
            <link>https://velog.io/@physical-100/Sentry-Turret-System-2</link>
            <guid>https://velog.io/@physical-100/Sentry-Turret-System-2</guid>
            <pubDate>Sun, 08 Feb 2026 13:36:22 GMT</pubDate>
            <description><![CDATA[<p>STM32-Nucleo F-401re 보드에서 조이스틱(아날로그 2축)으로 서보 2개를 제어하는 기능을 구현하면서 만난 문제들과 해결 과정을 상세히 정리했습니다.</p>
<p>초보자분들이나 비슷한 프로젝트 하시는 분들께 조금이라도 도움이 되길 바랍니다.</p>
<p><a href="https://velog.io/@physical-100/Sentry-Turret-System-1">프로젝트 개요</a> &lt;-- 여기를 클릭하시면 기초적인 구현 내용을 확인할 수 있으니 확인 바랍니다. </p>
<h3 id="issue-adc-값-나오긴-하지만-고정됨-변하지-않음">Issue: ADC 값 나오긴 하지만 고정됨 (변하지 않음)</h3>
<pre><code class="language-text">X:2039 → 1500us | Y:2070 → 1500us  (계속 동일 값 반복)</code></pre>
<h4 id="원인">원인</h4>
<p>DMA 설정에서 <code>hadc1.Init.DMAContinuousRequests = DISABLE;</code>
→ DMA가 한 번만 전송하고 멈춤</p>
<h4 id="해결">해결</h4>
<pre><code class="language-c">hadc1.Init.DMAContinuousRequests = ENABLE;</code></pre>
<p>-&gt; CubeMX에서 다시 설정 후 재생성.</p>
<p>또한 Rank 2 채널에도 SamplingTime 명시:</p>
<pre><code class="language-c">sConfig.Channel = ADC_CHANNEL_9;
sConfig.Rank = 2;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;  // 명시적으로 설정</code></pre>
<p>DMA + 다중 채널일 때 ContinuousRequests는 거의 항상 ENABLE!</p>
<h3 id="issue2-hal_adc_start_dma-호출-후-시스템-완전-멈춤">Issue2: HAL_ADC_Start_DMA() 호출 후 시스템 완전 멈춤</h3>
<pre><code class="language-text">[4/4] ADC DMA 시작 중...
(여기서 무한 멈춤, 에러 핸들러도 안 나옴)</code></pre>
<h4 id="원인-1">원인</h4>
<p>DMA 인터럽트 핸들러에서 미묘한 문제 (버퍼 오버런, 우선순위 충돌, 또는 콜백에서 블로킹 동작) 발생 가능성 높음. 디버깅 어려움.</p>
<h4 id="해결-임시-ㅠㅠ">해결 (임시) ㅠㅠ</h4>
<p>DMA → 폴링 방식으로 전환</p>
<pre><code class="language-c">HAL_ADC_Start(&amp;hadc1);
HAL_ADC_PollForConversion(&amp;hadc1, 50);
adc_values[0] = HAL_ADC_GetValue(&amp;hadc1);
HAL_ADC_PollForConversion(&amp;hadc1, 50);
adc_values[1] = HAL_ADC_GetValue(&amp;hadc1);</code></pre>
<p>DMA 인터럽트 문제를 해결하지 못해 일단 Polling으로 먼저 동작 확인 후 DMA로 업그레이드 추천합니다. </p>
<p>하지만 폴링 방식으로 바꿨는데도 값이 여전히 고정되는 문제를 겪었습니다. </p>
<p><code>Continuous Mode + Scan Mode에서 HAL_ADC_Start()</code>를 한 번만 호출 → 같은 변환 결과만 반복 읽어오는 것을 확인했는데요 이를 해결하기 위해
매 루프마다 Stop → Start로 새로운 변환 사이클 강제 시작했습니다.</p>
<pre><code class="language-c">HAL_ADC_Stop(&amp;hadc1);
HAL_Delay(1);           // 안정화용 짧은 딜레이
HAL_ADC_Start(&amp;hadc1);

HAL_ADC_PollForConversion(&amp;hadc1, 50);
adc_values[0] = HAL_ADC_GetValue(&amp;hadc1);

HAL_ADC_PollForConversion(&amp;hadc1, 50);
adc_values[1] = HAL_ADC_GetValue(&amp;hadc1);</code></pre>
<p><code>Continuous</code>라도 매번 새로 시작하지 않으면 최신 값이 안 들어옴. <code>Scan</code> 모드에서는 채널 순서대로 Poll 두 번 필수!</p>
<h3 id="issue-3-인터럽트-콜백-안에서-printf-쓰면-시스템-멈춤">issue 3: 인터럽트 콜백 안에서 printf() 쓰면 시스템 멈춤</h3>
<p>버튼 누르면 한 번 메시지 나오고 완전 freeze</p>
<h4 id="원인-2">원인</h4>
<p>인터럽트 컨텍스트에서 블로킹 함수(printf → UART 전송 대기) 사용 → 다른 인터럽트(예: SysTick) 못 들어와 데드락이 발생했습니ㅏㄷ. </p>
<h4 id="해결-1">해결</h4>
<p>플래그 방식으로 변경</p>
<pre><code class="language-c">volatile uint8_t mode_changed = 0;
volatile uint8_t control_mode = 0;  // 0: manual, 1: auto

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) {
    if (GPIO_Pin == B1_Pin) {
        control_mode = !control_mode;
        mode_changed = 1;
</code></pre>
<p><strong><em>최종적으로 폴링 방식 + 플래그 인터럽트로 안정화 성공</em></strong></p>
<p>앞으로 DMA 인터럽트 방식 재도전 (HAL_ADC_ConvCpltCallback() 활용)하겠습니다. </p>
<p>이 글 읽으시는 분들, 비슷한 문제 겪으시면 댓글로 공유해주세요~
다음엔 <u>DMA + 서보 smooth 제어</u>까지 완성해서 올리겠습니다!
화이팅! 🚀</p>
]]></description>
        </item>
    </channel>
</rss>