[{"content":"안녕하세요, IFAC Roboracer 2026에 처음 출전했던 성균관대학교 인공지능학회 SKKAI 모빌리티팀 소속 SKKUDERIA_SKKAI 팀 입니다.\n지난 글에서는 100만 원이라는 제한된 예산으로 제작한 저희 차량의 하드웨어를 소개해 드렸습니다. 이번 글에서는 그 차량을 실제로 달리게 만들기 위해 저희가 소프트웨어를 구현한 과정을 설명하고자 합니다.\n0. 어떻게 시작할지 막막하다면 차를 제작하고 굴리기까지 전 과정이 꽤 방대하기 때문에 막막할 수 있습니다.\n우선 대회 공식 자료로 소개되는 Penn의 유튜브 강의와 학습 자료로 기초 이론을 익히며, Perception-Planning-Control 전체 구조를 파악하시길 바랍니다.\nhttps://roboracer.ai/learn 1. 우리 팀의 base code 저희 팀은 ForzaETH 팀의 논문과 오픈코드를 베이스로 삼아 시작했습니다.\n논문: https://arxiv.org/pdf/2403.11784 코드: https://github.com/ForzaETH/race_stack ROS 2 Humble / Ubuntu 환경에서 코드 작업을 했습니다.\n2. SOSLAB GL5 LiDAR 연결 기존 ForzaETH 스택은 Hokuyo LiDAR를 기준으로 구성되어 있습니다. Hokuyo는 드라이버(urg_node)가 /scan 토픽으로 LaserScan 메시지를 직접 발행하고, 스택의 모든 모듈(cartographer, detection, FTG 등)이 이 LaserScan을 그대로 소비하는 구조입니다.\n저희가 사용한 GL5도 Hokuyo와 같은 2D 스캐닝 라이다입니다(270° FOV, 0.18°/빔, 40Hz). 다만 SOSLAB SDK의 드라이버는 2D 센서인데도 출력을 LaserScan이 아니라 PointCloud2(x, y, z — z는 사실상 0)로 내보냅니다.\n즉 센서가 3D여서가 아니라 드라이버의 메시지 타입 차이 때문에, PointCloud2를 LaserScan으로 도로 눌러주는 변환 브리지 구조를 새로 짜야 합니다.\n2.1 SDK 빌드와 pre-built 드라이버 패키지 SOSLAB SDK는 공식 저장소를 클론해 CMake로 빌드하면 됩니다.\nhttps://github.com/SOSLAB-github/SOSLAB_SDK 빌드하면 shared library(libLidar_x64_release.so)와 헤더가 나오는데, 이걸 스택 빌드 때마다 다시 컴파일할 이유는 없습니다. 저희는 SDK 빌드 산출물과 드라이버 노드 바이너리를 prebuilt/에 담은 별도 패키지를 만들었습니다.\nsensors/soslab_gl5_driver_prebuilt/ ├─ prebuilt/ # libLidar_x64_release.so + 드라이버 노드 바이너리 └─ CMakeLists.txt # 빌드 없이 install만 수행 colcon 빌드 시 이 패키지의 CMakeLists.txt는 컴파일을 전혀 하지 않고 pre-built 바이너리를 install 경로에 복사하는 역할만 합니다. SDK 빌드 환경과 스택 빌드가 완전히 분리되어, 팀원 누구나 SDK 의존성 없이 스택을 빌드할 수 있습니다.\n2.2 bringup 배선: 드라이버부터 scan토픽까지 토픽 연결은 f1tenth_system(저희는 포크해서 서브모듈로 사용)의 bringup_launch.py에서 이루어집니다. 원본에서 urg_node를 빼고 다음 네 가지를 넣었습니다.\nGL5 드라이버 노드 — sensors.yaml에서 파라미터를 로드해 /soslab/pointcloud 발행 static TF laser → laser_raw — GL5 좌표계 보정 (아래 2.3) pointcloud_to_laserscan 노드 — /soslab/pointcloud → /scan. cartographer, FTG 등 기존 스택이 소비하는 메인 스캔 intensity 필터를 거친 두 번째 pointcloud_to_laserscan — → /scan_obs. detection 전용 스캔으로, 반사 강도 기준으로 걸러낸 포인트만 사용 이렇게 하면 기존 스택 입장에서는 여전히 /scan이 들어오므로, 그 뒤 모듈들은 손댈 필요가 없습니다.\n2.3 좌표계 90° yaw 보정 저희가 받은 GL5가 발행하는 포인트클라우드의 프레임은 광학 중심 기준으로 90° 돌아가 있었습니다. 그대로 쓰면 차가 보고 있는 방향과 맵에 찍히는 방향이 어긋납니다.\n저희는 드라이버 출력을 laser_raw 프레임으로 발행하고, static TF laser → laser_raw로 90° yaw를 되돌려 사용했습니다.\n2.4 FOV 경계는 ±135°로 \u0026lsquo;정확히\u0026rsquo; 맞추기 GL5의 실제 FOV는 270°(±135°)입니다. 범위를 ±π로 넓히면 후방 90° 블라인드 섹터가 측정값 없이 inf로 채워지는데, cartographer는 inf를 \u0026ldquo;레이저가 그 방향으로 나갔는데 아무것도 안 맞았다(MISS)\u0026ldquo;로 해석합니다.\n이를 방지하기 위해 FOV와 정확히 맞추어줍니다.\n3. 결국 가장 중요한 것은, Perception Perception, Planning, Control 가운데 무엇이 가장 중요할까요?\n저희가 직접 차량을 구현하고 테스트하며 내린 결론은 ⭐️ Perception ⭐️ 이었습니다.\nPerception은 다시 다음과 같이 나눌 수 있습니다.\nMapping: 센서 데이터로 주행 환경의 지도를 생성합니다. Localization: 만들어진 지도 안에서 차량의 현재 위치와 자세를 추정합니다. Detection \u0026amp; Tracking: 장애물을 탐지하고 움직임을 추적합니다. 3.1 Mapping mapping 및 localization 알고리즘으로는 cartographer를 사용했습니다.\n저희 차의 시야거리는 9m였기 때문에, 9m 이상의 특징 없는 직선 벽 트랙을 매핑할 때는 차가 현재 위치가 아까 지나온 위치라고 착각해 맵을 접어버리는 일명 맵 접힘 이슈가 있었습니다.\n이럴 때는 loop-closure를 쉽게 채택하지 못하도록 matching score threshold를 높이거나, 매핑 시에만 트랙에 특징을 주는 식으로 해결할 수 있습니다.\n또 라이다가 수평으로 잘 장착되어 있는지 확인해야 합니다. 라이다가 약간 아래를 보고 있으면 일정 거리 떨어진 바닥에 라이다 스캔이 찍혀 장애물이 앞에 있다고 생각할 수 있습니다. 또 라이다가 약간 위를 보면 라이다 스캔이 실제 거리보다 멀리 찍히거나 맵 밖을 보게 될 수 있습니다.\n차에 눈을 똑바로 달아줍시다.\n3.2 Localization Perception 중 가장 중요한 것은 바로 이 ⭐️ Localization ⭐️ 입니다.\n차가 자신의 위치와 상태를 정확히 알고 있어야 합니다! Planner는 \u0026ldquo;차량이 지도 위 어디에 있는지를 기준으로\u0026rdquo; 경로를 만들거나 선택하고, Controller 역시 \u0026ldquo;현재 위치\u0026quot;와 목표 경로 사이의 오차를 바탕으로 명령을 계산하기 때문입니다.\n차가 이상하게 움직일 때 겉으로는 Planner나 Controller 문제처럼 보여도 출발점은 localization 오류일 수 있습니다.\n예를 들어 차가 랩 수가 늘어남에 따라 점점 안쪽으로 도는 문제가 있을 때, 차량 무게 중심이 한쪽으로 쏠려 있거나 controller 문제로 진짜 차가 안쪽으로 도는 문제일 수 있지만, pose가 바깥으로 밀려서 제어기가 안쪽으로 당기는 것일 수도 있습니다.\nCartographer나 SynPF처럼 대표적인 Localization 알고리즘의 장단점을 비교해보고, EKF를 raw IMU, LiDAR, ERPM 등의 센서 정보를 퓨징하는 단계에 쓸지 혹은 car state를 최종적으로 추정할 때 쓸지 (혹은 두 군데 모두에 쓸지) 등 car state estimation 파이프라인을 정교하게 설계하시길 권합니다.\n3.3 Detection \u0026amp; Tracking 너무 단순하지만.. 차가 자기 자신을 장애물로 인식하지 않도록 해주어야 합니다. 그렇지 않으면 차가 움직일 때마다 장애물도 따라오고, 사방이 막혔다고 생각해 옴짝달싹 못하는 기묘한 광경을 보게 됩니다.\n후술하겠지만 Detection 및 Tracking은 CPU 부담이 꽤 있는 작업입니다. 저희는 연산 부담을 줄이기 위해 기존 코드를 C++로 전환했습니다.\n그 외에도 detect에서 latest scan을 언제 비워주는 것이 적당한지, 지난 랩에서 장애물을 봤다면 규정상 다음 랩에서도 같은 위치에 장애물이 있을 확률이 높기 때문에 다시 돌아와서 없음을 확인하기 전까지는 있다고 생각하고 주행하도록 하는 등 소소한 수정이 있었습니다.\n주행 중 차량이 트랙 경계와 충돌하면서 트랙의 형태가 달라지는 상황도 고려해야 합니다. 이때 변형된 경계를 모두 새로운 장애물로 인식해서는 안 됩니다.\n저희는 트랙이 밖으로 나간 경우는 무시하고, 안으로 들어온 경우 기존 벽에 붙어 있고 여러 랩에 걸쳐 같은 위치이면 track boundary로 흡수하게 해주었습니다.\n4. CPU 자원 배분 CPU 부하 문제 역시 반드시 신경 써야 하는 부분입니다.\n저희 차량의 컴퓨팅 플랫폼은 Jetson Orin Nano Super로, CPU 코어가 6개뿐입니다. 이 6개 코어를 perception, planner, controller는 물론 cartographer, 드라이버, 시각화까지 전부 나눠 쓰기 때문에 한 모듈이 CPU를 과점하면 다른 모듈이 바로 밀립니다.\nCPU 부하로 /scan, /tf, localization 업데이트가 밀리면 오래된 라이다 스캔이 현재 시각의 차량 pose와 잘못 결합됩니다. 그 결과 과거 위치에서 관측한 장애물이 현재 scan에 남는, 일명 Phantom 문제가 발생합니다.\n각 모듈의 정확도뿐 아니라 연산 주기, callback 지연, CPU 점유율도 함께 지켜봐야 합니다.\n저희 팀의 발단은 이랬습니다. detect 노드를 40Hz로 설정했는데 실측 주기는 19.3Hz로 포화되어 있었고, 콜백 스레드가 CPU를 독점하면서 TF listener가 굶어 \u0026ldquo;extrapolation into the future\u0026rdquo; lookup 실패가 속출했습니다.\n여기서부터 시도한 것들을 순서대로 공유합니다.\n4.1 완화책 ① Python 벡터화. detect의 adaptive-breakpoint segmentation 루프를 numpy로 벡터화했습니다. 흥미로운 건 속도 자체보다, numpy 연산 중에는 GIL이 풀려서 TF 스레드가 살아난다는 점이 핵심이었다는 것입니다. Python 노드에서 특정 스레드가 굶는 증상이 있다면 참고하세요.\n② 노드 주기 하향 (40→20Hz). detect·tracking·controller를 달성 가능한 주기로 낮췄습니다 (Python detect는 40Hz 설정에서 CPU 약 44%). 이때 Kalman filter의 dt, waypoint-safety timeout처럼 주기에 묶여 있는 파라미터들도 함께 스케일해야 합니다.\n욕심내서 10Hz까지 내려봤다가 부작용을 발견했는데, tracking(20Hz)이 같은 detection을 두 번 소비하면서 상대속도 추정이 0.67x~1.33x로 진동하고 KF가 재초기화되는 문제였습니다. 주기를 조정할 때는 모듈 간 주기 비율까지 봐야 한다는 교훈을 얻고 20Hz로 복귀했습니다.\n③ 시각화 부하 제거. TF staleness의 근본 원인으로 지목된 것이 의외로 RViz 마커였습니다. 구독자가 있을 때만 마커를 빌드/발행하도록 바꾸고 5Hz로 스로틀했으며, 실제 local waypoint를 마커 작업보다 먼저 발행하도록 순서를 바꿔 마커가 스킵돼도 플래너 공급은 끊기지 않게 했습니다. RViz 기본 설정에서도 디버그 표시와 raw scan을 off로 두었습니다.\n디버깅용 시각화가 디버깅 대상인 부하를 만들고 있지 않은지 꼭 확인해보세요.\n4.2 구조적 해법 — 핫패스 C++ 포팅 완화책으로 버티는 데는 한계가 있었습니다.\n모듈별 CPU 점유율을 분석해보니 detect, tracking, controller, spline planner 같은 핫패스(perception → planner → controller) 노드들이 부하의 대부분을 차지하고 있었고, 이 노드들을 C++로 전환하는 것으로 결론지었습니다.\ndetect → controller(Pure Pursuit + FTG) → tracking → spline_planner 순서로 옮겼습니다.\n그래서 스택을 다시 짠다면? 돌이켜보면 화려한 Planning이나 Control 알고리즘보다 정확하고 안정적인 Perception이 먼저였습니다. 특히 Localization이 안정적이어야 이후 모듈의 문제도 올바르게 진단할 수 있었습니다.\n처음 준비하는 팀이라면 모든 기능을 한꺼번에 완성하려 하기보다, 센서 입력부터 차량 출력까지 한 단계씩 검증하는 것을 추천드립니다.\n실차 테스트를 해가며 발견되는 문제를 해결해나가신다면 어느새 똑똑해진 차를 만나실 수 있을 것입니다.\nCookie ","permalink":"https://churrosboy.github.io/SKKUDERIA_SKKAI_blog/posts/software-build/","summary":"\u003cp\u003e안녕하세요, IFAC Roboracer 2026에 처음 출전했던 성균관대학교 인공지능학회 SKKAI 모빌리티팀 소속 SKKUDERIA_SKKAI 팀 입니다.\u003c/p\u003e\n\u003cp\u003e지난 글에서는 100만 원이라는 제한된 예산으로 제작한 저희 차량의 하드웨어를 소개해 드렸습니다. 이번 글에서는 그 차량을 실제로 달리게 만들기 위해 저희가 소프트웨어를 구현한 과정을 설명하고자 합니다.\u003c/p\u003e\n\u003ch2 id=\"0-어떻게-시작할지-막막하다면\"\u003e0. 어떻게 시작할지 막막하다면\u003c/h2\u003e\n\u003cp\u003e차를 제작하고 굴리기까지 전 과정이 꽤 방대하기 때문에 막막할 수 있습니다.\u003c/p\u003e\n\u003cp\u003e우선 대회 공식 자료로 소개되는 Penn의 유튜브 강의와 학습 자료로 기초 이론을 익히며, Perception-Planning-Control 전체 구조를 파악하시길 바랍니다.\u003c/p\u003e","tags":["software","roboracer","lidar","ros2","IFAC","soslab","에스오에스랩"],"title":"우리 아이, 이제 혼자서도 잘 달려요"},{"content":"안녕하세요, 저희는 이번 IFAC Roboracer 2026에 처음 출전했던 성균관대학교 인공지능학회 SKKAI 모빌리티팀 소속 SKKUDERIA_SKKAI 팀 입니다.\n대회장에서는 저희의 하드웨어를 소개하는게 맞나 싶을 정도로 완성도 높은 차량들이 많았지만, 저희처럼 대회를 처음 준비하는 분들께 조금이나마 도움이 되고자 초라한 저희 차량의 하드웨어를 소개드립니다.\n하드웨어 부품 리스트 LiDAR: SOSLAB GL5 (2D) Chassis: Traxxas Slash 2wd Onboard PC: NVIDIA Jetson Orin Nano Super(6 core, 8gb VRAM) Motor: Traxxas Velineon Brushless 3500 Servo: Highest B210 ESC: VESC6 MKVI Wheels: VR Pro Friction1/10 4WD Elec. Offroad Buggy Rear Rubber Tyre Unglued UBEC: Hobbywing-5A-V2-Air Battery: VEGA 3300 4s LiPo 저희는 기존 보유 장비와 중고 부품을 적극적으로 활용했기 때문에 100만원으로 참여가 가능했습니다. 특히 가장 고가의 부품인 LiDAR는 SOSLAB의 지원을 받아 참여했습니다.\n0. LiDAR: SOSLAB GL5 저희 차량의 핵심 부품입니다.\n보통 이 대회에서는 Hokuyo라는 일본 회사의 2D 라이다나, Livox라는 중국 회사의 3D라이다를 사용합니다.\n하지만 저희는 ⭐️⭐️100프로 대한민국산⭐️⭐️ 라이다를 달고 출전하였습니다.\n이름하여 SOSLAB의 GL5라는 라이다 입니다.\nGL5는 9m의 가시거리와 40Hz의 Scan Rate, 270도 FOV를 가진 2D 라이다입니다.\n저희는 약 10m/s까지 테스트 했으며, 해당 속도에서도 Localization이 잘 될만큼, 안정적인 라이다입니다.\n또한 매우 컴팩트한 사이즈의 라이다인데, 얼마나 컴팩트 하냐면,\n라이다가 밥숟가락 만하다면 믿어지십니까?\nRoboracer는 1:10 스케일의 차량을 사용합니다. 물론 차량 크기 규정에만 맞게 차량을 크게 만드는 것을 추천드리지만, 저희가 사용한 샤시는 작았기 때문에 컴팩트한 사이즈의 센서가 필요했습니다.\n이 제품은 아직 출시 전의 제품이지만, 운 좋게도 SOSLAB에서 양산 전 테스트제품을 보내주셔서 써볼 수 있게 되었습니다.\n출시 예정 가격도 200만원이 넘는 Hokuyo보다 훨씬 저렴하다고 하니, 앞으로 더 많은 팀이 부담 없이 사용할 수 있을 것 같습니다. 이번 대회에서는 56개 팀 중 유일하게 SOSLAB 라이다를 사용했는데, 앞으로 더 많은 팀이 국산 라이다를 달고 달리는 모습을 볼 수 있으면 좋겠습니다.\nSOSLAB은 GL5 외에도 많은 2D, 3D라이다를 양산하고 있습니다. 국제 대회에서는 평면이 아닌 길도 달린다고 하니, 3D라이다를 고려하고 계신 분들도, 고려해보시면 좋을 것 같습니다.\n1. Chassis: Traxxas Slash 2wd 우선, ⭐️⭐️절대 저희처럼 후륜구동 샤시를 쓰지 마십시오.\n저희는 예산 부족으로 인해 동아리방에 있던 유물을 살려서 써야해서 어쩔 수 없이 썼지만, 56개의 팀 중 후륜구동 샤시를 쓰는팀은 저희 포함 2팀 남짓이었습니다.\n게다가 이번 대회는 노면이 미끄러워서, 속도를 조금만 올려도 차가 돌았습니다.\n저희는 순정 샤시에 LCG 키트를 구해서 장착했습니다. 지상고와 무게중심을 낮추기 위함이었는데, 이또한 추천드리지 않습니다. 저희보다 차체가 낮은 팀이 없었습니다. 또한 후술할 휠 크기와도 연관되어있습니다.\n아무튼 저희는 이랬던 유물 샤시를, 3d프린터로 덱을 뽑아 이렇게 바꾸어 주었습니다.\n전 후 2. Onboard PC: NVIDIA Jetson Orin Nano Super GPU를 사용하려고 샀는데, 저희는 LiDAR 기반의 알고리즘을 사용했기 때문에 GPU 연산을 거의 사용하지 않았습니다.\n결과적으로 Jetson Orin Nano Super의 GPU 성능을 충분히 활용하지 못했습니다. 만약 LiDAR 기반 classical algorithm을 사용할 예정이라면 GPU 성능보다는 CPU 성능과 I/O 등을 우선적으로 고려하는 것을 추천드립니다.\n또한 대회 환경에서는 수백명이 한 공간에 있으므로, 원격으로 차량을 작동시키고 시각화 툴을 보실 예정이라면 온보드 PC와, 원격으로 사용하실 PC 모두 통신모듈의 성능을 잘 보고 준비하시는 것을 추천드립니다.\n그리고 무조건! 그에 맞는 공유기를 미리 구매해서, 사설망을 만들어 두시는걸 추천드립니다.\n4. Servo: Highest B210 처음에는 저렴하고 토크가 약한 서보를 사용했는데, 해상도가 좋지 않아서 해당 서보를 추가구매 하였습니다.\n처음부터 토크가 높고 속도가 빠른 서보를 구매해서 이중투자가 없도록 하시는 것을 추천드립니다.\n해당 서보는 VESC에서 인가해 줄 수 있는 전압보다 더 높은 전압을 필요로 합니다.\n따라서 커스텀 배선 제작 및 UBEC 구매가 필요할 수 있습니다.\n6. Wheels: VR Pro Friction1/10 4WD Elec. Offroad Buggy Rear Rubber Tyre Unglued 이 또한 차체를 낮추고자, 작은 사이즈의 휠을 장착했습니다.\n하지만 작은 사이즈의 휠은 폭이 좁아 접지력이 오히려 좋지 않은 것 같습니다.\n차체를 낮추기보다는, 1:8 스케일 RC카에 사용되는 광폭 휠타이어를 구매하셔서 접지력을 높이는 것을 추천드립니다.\n그래서 차를 다시 만든다면? 만약 다시 처음부터 차량을 제작한다면 저희는 다음과 같이 구성할 것 같습니다.\nChassis: 4WD 기반 1:8급 Onboard PC: CPU 성능이 높은 보드(NUC 등) Servo: 처음부터 고토크·고속 제품 Wheel: 넓은 접지면을 가진 타이어 저희가 뛰어난 성과를 보인 팀은 아니었지만, 저희의 글이 준비를 하시는데 미약하게나마 도움이 되기를 바라며, 다음에는 저희 팀의 소프트웨어 구현기로 돌아오겠습니다.\nCookie 무조건 범퍼를 처음부터 달아두세요. 이유는.. 저희도 알고싶지 않았습니다..\n","permalink":"https://churrosboy.github.io/SKKUDERIA_SKKAI_blog/posts/hardware-build/","summary":"\u003cp\u003e안녕하세요, 저희는 이번 IFAC Roboracer 2026에 처음 출전했던 성균관대학교 인공지능학회 SKKAI 모빌리티팀 소속 SKKUDERIA_SKKAI 팀 입니다.\u003c/p\u003e\n\u003cp\u003e대회장에서는 저희의 하드웨어를 소개하는게 맞나 싶을 정도로 완성도 높은 차량들이 많았지만, 저희처럼 대회를 처음 준비하는 분들께 조금이나마 도움이 되고자 초라한 저희 차량의 하드웨어를 소개드립니다.\u003c/p\u003e\n\u003ch2 id=\"하드웨어-부품-리스트\"\u003e하드웨어 부품 리스트\u003c/h2\u003e\n\u003col start=\"0\"\u003e\n\u003cli\u003eLiDAR: SOSLAB GL5 (2D)\u003c/li\u003e\n\u003cli\u003eChassis: Traxxas Slash 2wd\u003c/li\u003e\n\u003cli\u003eOnboard PC: NVIDIA Jetson Orin Nano Super(6 core, 8gb VRAM)\u003c/li\u003e\n\u003cli\u003eMotor: Traxxas Velineon Brushless 3500\u003c/li\u003e\n\u003cli\u003eServo: Highest B210\u003c/li\u003e\n\u003cli\u003eESC: VESC6 MKVI\u003c/li\u003e\n\u003cli\u003eWheels: VR Pro Friction1/10 4WD Elec. Offroad Buggy Rear Rubber Tyre Unglued\u003c/li\u003e\n\u003cli\u003eUBEC: Hobbywing-5A-V2-Air\u003c/li\u003e\n\u003cli\u003eBattery: VEGA 3300 4s LiPo\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e저희는 기존 보유 장비와 중고 부품을 적극적으로 활용했기 때문에 100만원으로 참여가 가능했습니다. 특히 가장 고가의 부품인 LiDAR는 SOSLAB의 지원을 받아 참여했습니다.\u003c/p\u003e","tags":["hardware","roboracer","lidar","IFAC","soslab","에스오에스랩"],"title":"100만원으로 Roboracer에 참가한 팀이 있다?"}]