2019년 7월 14일 일요일

세상을 바꾸는 코딩 책 소개

안녕하세요. 대디 메이커입니다.

이 글은 세상을 바꾸는 코딩(넥서스 출판)이란 책을 소개하고, 어떻게 만들었는 지 공유합니다. 이 책은 코딩을 처음 접하는 사람들을 위해 만든 책이예요. 이 책은 코딩에 대한 개념을 삽화를 통해 쉽게 이야기하고. 사례, 역사 등 배경 토막지식을 챕터별로 공유하고 있어요. 관심만 있으면 비싼 곳에 가지 않아도 코딩을 배우고 사용할 수 있는 무료도구나 방법을 알려줍니다. 아울러, 메이커 활동을 통해 얻은 경험을 가감없이 담았습니다.
세바코 소개 영상^^

이 책은 평소 가족 메이커로써 활동한 경험을 살려 온 가족이 모여 만든 책입니다. 책도 메이커 활동이라 생각해, 책을 만드는 과정을 틈틈히 기록했었어요. 그 과정도 함께 공개합니다.

책의 구성
제목은 출판사에서 결정했어요. 제목 아이디어는 평소 메이커 활동을 통해 사물 인터넷 등 다양한 것을 만들어나가는 모습을 보고 영감을 받은 것 같아요. 사실 우리가 사용하는 많은 사물은 전기로 움직이는 것이 많죠. 이 안에는 코딩된 프로그램이 돌아가고 있거든요. 출판사에 여러개의 제목을 제안했었는 데, 이런 이유로 세바코란 제목이 결정된거예요.

표지가 예쁜 세바코 책

이 책은 지난번 키즈 메이커(전파과학사, 2016) 이후 코딩, 메이커 관련해 두번째 책입니다. 2014년 부터 꾸준히 메이커페어에 참여한 가족들과 함께 경험하고 고민했던 코딩, 무료 코딩 도구와 메이커 교육에 대한 생각을 가감없이 담았습니다.

코딩을 접해 본적이 없는 사람들도 쉽게 읽히고 이해되는 책을 만들기 위해 노력했어요.
책 머리말에는 이 책이 어떻게 나왔는 지 설명하고 있어요

이 책은 경기도 융합과학원 원장님, 과학관 유만선 박사님, 홍영길 서울대 행복연구센터 박사님, 우용만 영재발굴단 피디님이 추천사를 써 주셨어요^^

책 목차는 코딩이 세상을 바꾸는 사례, 컴퓨터적 사고, 알고리즘 등 기본 개념을 설명하고 있고, 실제 프로그램이 어떻게 만들어지는 지 사례가 포함되어 있어요. 아울러, 사물인터넷, 인공지능, 로봇, 블록체인, 가상현실, 스마트시티, 우주 등에 사용되는 코딩 사례를 설명하고 있지요.

책은 가족이 대화식으로 실생활의 문제와 코딩을 주제로 서로 이야기하는 식으로 구성되어 있어요. 이 내용은 실제 작품을 아이들이 만들면서 했던 대화를 담은 것들이 많답니다.

무료로 코딩 공부하는 방법
굳이 학원에 가지 않아도 코딩을 할 수 있도록 무료 코딩 도구를 담았어요. 실제 선우와 연수도 코딩 학원에 가지 않고 필요할 때 유튜브나 구글 찾아보면서 코딩을 하고 작품을 만들었어요. QR코드가 있어 쉽게 스마트폰으로 실행할 수 있습니다. 이렇게 가족이 코딩을 큰 돈 안들이고 할 수 있는 방법을 경험을 바탕으로 제공하고 있답니다. 

책 내용 중간에 그림으로 내용을 재미있게 전달하기 위해 삽화를 넣었어요. 이 그림도 선우가 직접 메이크한 거예요.

코딩과 관련된 다양한 사례와 컴퓨터 역사를 토막 지식으로 요약해 담았어요. 그래서, 배경 지식을 알고 싶은 독자는 이 부분을 읽으면 되고, 빨리 읽고 싶은 사람들은 내용만 읽으면 되도록 했어요.

컴퓨터적 사고란
쉽게 컴퓨터적 사고를 배울 수 있는 방법을 경험을 반영해 소개하고 있으며, 코딩을 접할 때 막막한 문제인 '코딩 배울려면 처음에 무엇부터 해야지'란 질문에 대한 손쉽게 접근할 수 있는 웹사이트나 방법을 각 챕터별로 소개하고 있습니다.
컴퓨터적 사고

다양한 역사를 담고 있어

컴퓨터적 사고를 키우기 위한 다양한 방법을 담고 있는 데, 언플러그드 코딩 같은 내용도 소개하고 집에서 쉽게 할 수 있는 방법도 알려주고 있습니다.
아빠 로봇으로 코딩하기

코딩 로봇으로 피자 만들기

실제로 구글과 같은 개발회사에서 개발자가 하는 코딩은 더 명확하게 프로그램 요구사항을 정리하고 사용자 화면을 디자인해요. 이를 경험해 볼 수 있도록 피구 게임 만들기를 통해 게임 요구사항, 시나리오를 조사하고, 화면을 디자인한 후 코딩하는 과정을 담았어요.

코딩이 세상을 바꾸는 사례와 방법
이렇게 코딩의 ABC 기본기를 알려주고, 코딩으로 할 수 있는 예술, 로봇, 스마트시티, 블록체인 등 다양한 사례를 이야기합니다.
코딩으로 하는 미디어아트

사물인터넷과 오픈소스

가상현실과 무료도구

인터넷과 앱 만들기

블록체인

인공지능과 무료 도구

드론, 인간형 로봇, 무인자율차, 3D프린터에도 코딩이 있죠^^

스마트시티 안에도 코딩은 중요한 역할을 차지하고 있어요

우주를 탐구할 때도 코딩은 필수예요. 얼마전 블랙홀 사진을 세계 최초로 찍은 것도 코딩의 힘이 있었어요.

이런 다양한 사례와 더불어 우리 주변에 있는 문제를 발견하고, 해결하는 좋은 방법들을 알려주고 있어요. 메이커 운동, 유엔에서 발표한 SDG(Sustainable Development Goals) 등이 그것입니다.
메이커 운동
유엔 SDG

코딩과 관련된 경험, 사례, 지식, 도구 등 방대한 양을 하나의 책으로 축약해 넣기 위해, 온 가족이 대략 1년 이상 함께 정리했던 것 같습니다. 저희들이 경험한 코딩을 세바코에 그대로 담았어요. 잘 활용하시면 굳이 학원에 가지 않고도 무료로 코딩 교육이 가능하게끔 책을 만들었습니다. 단, 코딩에 대한 열정과 관심이 있어야겠죠.

코딩과 메이커에 관심있는 분들의 많은 사랑 부탁합니다~^^


참고 - 책 만들기 과정
책 만들기 과정은 대략 1년이 걸렸습니다. 책 만들기가 가족 이벤트였고, 추억도 남길겸 그 과정을 기록했지요. 이 책은 선우는 본인이 직접 경험한 사례를 책에 녹여 넣고, 그래픽 디자인 프로그램을 이용해 재미있는 삽화를 그렸고, 연수는 인터넷에서 사례들을 조사해서 정리해 넣는 방식으로 만들어졌어요. 엄마는 책 전체적인 흐름을 이해하기 쉽도록 내용 보완을 하고 꼼꼼히 수정을 했어요. 아빠인 저는 공학적인 지식을 좀 더 쉽게 전달하는 데 노력했습니다. 


선우가 그려넣은 삽화

코딩과 관련해 경험한 메이커 작품도 녹여 넣었어요



코딩을 이해하는 데 도움을 주는 사례는 연수가 조사해 정리한거죠


엄마는 이 많은 원고를 직접 검수하고 잘못된 부분들을 수정했어요.

이렇게 책도 메이크 활동하는 식으로 만들었담니다

책을 만드는 동안은 주말이나 주중에 남는 시간을 각자 최대한 활용했어요. 코딩이 무엇인지 개념부터, 방법, 도구 및 사례까지 방대한 내용을 쉽게 담으려 노력했는 데, 내용을 쉽게 담기 위한 과정이 많은 시간을 차지하더군요.^^  책에 대해서 궁금한 점이 있으면 언제든 출판사(넥서스)나 저자들에게 연락 주시길 바랍니다.



로봇의 눈으로 보는 세상

이 작품은 로봇이 어떤 방식으로 세상을 보고 행동을 하는 지에 대한 것을 시연합니다. 

로봇은 다양한 센서로 구성되어 있고, 센서를 이용해 주변 환경을 인식합니다. 센서는 디지털값으로 데이터화되고 이 데이터는 로봇이 동작하는 데 필요한 정보를 생성하는 데 사용되죠. 
인식 영상 예시
카메라 센서로 인식된 사물들(딥렌즈)

카메라 센서를 이용하면, 픽셀로 구성된 이미지로 데이터를 얻을 수 있습니다. 요즘에는 인공지능 기술을 이용해 이미지에서 사물을 인식할 수 있습니다.

이 작품은 로봇의 센서 중 눈으로 보고 판단하는 것과 관련된 비전(VISION) 센서의 동작을 좀 더 자세히 보여줍니다. 비전 센서는 카메라, 레이저 스캐너 등이 될 수 있습니다. 

이 중 레이저 스캐너는 거리와 위치를 정확히 측정할 수 있는 장치를 포함하고 있습니다. 
라이다를 이용한 주위 사물 스캔

레이저 스캐너는 라이다(LiDAR)라고도 하는 데, 무인 자율 자동차에도 필수적인 센서죠. 레이저 스캐너를 이용하면, 레이저에서 발사되어 사물에 반사되어온 시간을 이용해 정확한 거리와 위치를 알 수 있습니다. 수많은 레이저를 발사에 얻은 데이터는 수많은 점들로 표현됩니다. 이 점들에는 무인 자율차가 주행할 때 피해야 할 사람이나 주변의 차들도 포함되어 있는 것입니다. 이런 장애물을 요즘에는 인공지능 기술을 이용해 알아냅니다.
실시간 3차원 지도 생성

이외에 로봇은 다양한 센서를 내장하고 있습니다. 기울기 센서 등이 그것입니다. 이런 센서는 사물인터넷(IoT. Internet of Things)와 비슷하게 동작되고, 로봇 각 부분에 설치된 센서 데이터를 얻어 행동을 예측하는 데 사용합니다. 
사물인터넷 센서 데이터(노드레드)

이런 정보를 모두 모아 로봇이 어떤 행동을 할지 결정하는 것입니다. 사실, 이 모든 정보를 얻는 데는 수많은 개발자가 기여한 오픈소스가 사용됩니다. 오픈소스는 함께 문제를 공유하고 해결하려는 사람들이 모여 만들어 나갑니다. 오픈소스는 문화로 확산되어 많은 사람들이 동참하고 있습니다. 우리나라도 이런 문화가 많이 확산되면 좋겠습니다. 이 작품은 이와 관련된 내용을 교육적 목적으로 보여주는 것입니다.


2019년 6월 23일 일요일

우분투 USB 부팅 이미지 리사이즈 방법

이 글은 우분투 USB 부팅 이미지를 리사이즈 방법을 간략히 공유한다.
보통, 테스트용으로 우분투 등 리눅스 부팅 이미지를 만든 후, 좀 더 큰 메모리 SD 카드(256, 512 GB)로 이미지를 복사해 옮겨가고 싶을 때 사용한다. 이 글은 다음 레퍼런스를 참고하였다.

2019년 6월 18일 화요일

고정밀 GNSS IMU와 ROS 연동하기

이 글은 고정밀 GNSS(Global Navigation Satellite System), IMU(Inertial Measurement Unit)와 ROS(Robot Operating System)를 연동하는 것에 대한 내용을 간단히 요약한 것이다. 여기서 사용한 GNSS센서는 3DM GX5이다.
3DM-GX5-45(high performance integrated multi-constellation GNSS receiver)

임베디드 보드는 ODROID(오드로이드. 설치 참고) UX4를 사용하였으나, 라떼판다(윈도우에서 운용됨), NVIDIA TK 등 다른 임베디드 보드를 사용하더라도 큰 관계는 없다.

이 제품은 GPS, GLONASS, DeiDou, Galileo를 활용한 GNSS receiver이며, 정밀한 AHRS(Attitude and Heading Reference System) 값을 얻을 수 있다.
AHRS data

이 센서는 가격이 3~400백만원 수준이며, 드론, 로봇틱스 등 다양한 분야에 활용되고 있다. 이 센서는 가격이 상대적으로 저렴한? 편이라 한다. 다만, ROS 우부투, 리눅스 기반 작업을 할 때는 문서화가 잘 안되어 있어, 삽질이 좀 필요하다. 윈도우 버전은 설치 프로그램도 함께 제공하는 등 상대적으로 작업이 쉽다.
GNSS 사용 사례

이 글은 다음 링크를 참고하였다.
머리말
제품 제조사는 ROS 드라이버 패키지를 다음 링크에서 제공하고 있다.
이 패키지는 인터페이스 드라이버, ROS node가 제공되며, MIP SDK(Software Development Kit)를 통해 GNSS 장치와 연결해 사용한다. 

ROS 패키지 빌드 및 실행 
현재 ROS 버전이 HYDRO, INDIGO 일 경우에는 다음과 같이 3DM-GX5-45 ROS 패키지를 다운로드하고 설치해보자. 

DISTRO={hydro|indigo}
cd ~/catkin_ws
rosdep update
rosdep check --from-paths src/microstrain_3dm_gx5_45/ --rosdistro=$DISRO
rosdep install --from-paths src/microstrain_3dm_gx5_45/ --ignore-src --rosdistro=$DISTRO --simulate
rosdep install --from-paths src/microstrain_3dm_gx5_45/ --ignore-src --rosdistro=$DISTRO
catkin_make
source devel/setup.bash

만약, ROS가 최신 MELODIC 버전이라면 github에서 소스코드를 다운로드한 후 다음과 같이 빌드해서 ROS 패키지를 설치해야 한다.
cd ~/catkin_ws/src
git clone https://github.com/ros-drivers/microstrain_mips.git
cd ..
catkin_make -j1

참고로, 패키지 정보는 다음과 같이 정의되어 있다.

제대로 빌드되었다면, 패키지가 설치되며, 다음 명령을 통해 microstrain_mips 패키지를 확인할 수 있다.
rospack list-names
ROS 패키지 리스트

이제 센서와 컴퓨터를 USB로 연결해 본다. 센서와 USB에 연결된 포트 이름은 상황에 따라 동적으로 할당되므로, 다음 명령을 이용해 센서에 연결된 USB serial port 이름 리스트를 먼저 확인하고 적절한 포트 이름을 지정해야 한다. 
dmesg | grep tty

연결된 포트는 아래 명령으로 좀 더 자세한 정보를 확인할 수 있다.
ls -l /dev/ttyACM0

센서 정보는 다음 명령을 통해 확인할 수 있다.
cd ~/catkin_ws/devel/lib/microstrain_mips
./GX4-45_Test /dev/ttyACM0 115200

GNSS 센서와 연결상태 확인

이제 다음과 같이 ROS node를 실행해 본다. 참고로, 아래 글의 파라메터를 확인해 적절한 값을 입력해야 동작한다. 예를 들어, 포트이름을 정확히 입력하지 않으면 센서의 ROS node는 실행되지 않을 것이다.
rosrun microstrain_mips microstrain_mips_node _port:=/dev/ttyACM0 _device_setup:=true

이렇게 실행된 결과 다음과 같은 토픽 데이터를 얻을 수 있다. 
각 topic data 를 살펴보면 다음과 같다.
  • rostopic echo /imu/data
microstrain_mips_node가 생성한 ROS 토픽
참고로, IMU 데이터 구조는 ROS IMU Sensor Driver 에 설명되어 있다. Accelerometers, Gyroscopes, Magnetometers, Orientation로 구성되어 있으며, IMU데이터에서 많이 사용하는 Orientation은 quaternion 형태로 출력된다.
imu/data (sensor_msgs/Imu) 토픽은 quaternion orientation 추정값을 포함하고, imu/data_raw (sensor_msgs/Imu) 토픽은 accelerometer, gyroscope 데이터를 포함한다. imu/msg (sensormsgs/MagneticField)는 magnetometer 데이터를 포함한다.  
  • rostopic echo /gps/fix

  • rostopic echo /nav/odom
  • rostopic echo /nav/status

ROS node 에서 생성된 데이터가 제대로 출력되는 것을 확인할 수 있다.

3DM-GX5-45 패키지 기능 및 파라메터
다음은 센서 ROS 패키지에서 제공하는 서비스이다.
이 패키지에서 사용하는 파라메터 중 주요한것을 살펴보면 다음과 같다. 이 파라메터는 ROS node 실행 시 _parameter:=value 형식으로 설정할 수 있다.
  • port (string, default: /dev/ttyACM0): Serial port - Linux only
  • baud_rate (int, default: 115200): Baud rate of serial connection
  • device_setup (bool, default: true): If true, puts device in idle mode and configures the device.If false, skips configuration. Important: the configuration parameters below are not effective unless this flag is true.
  • dynamics_mode (int, default: 1): Vehicle dynamics mode 0x01=Portable, 0x02=Automotive, 0x03=Airborne
  • declination_source (int, default: 2): Possible declination sources: 0x01=Node, device reports magnetic north, 0x02=Internal World Magnetic Model, 0x03=Manual (see declination parameter)
  • gps_frame_id (string, default: wgs84): Value for the frame_id field in the header of the NavSatFix message published on the gps/fix topic
  • imu_frame_id (string, default: base_link): Value of the frame_id field in the header of the Imu message publised in the imu/data topic
  • odom_frame_id (string, default: wgs84): Value of the frame_id field in the header of the Odometry message published on the nav/odom topic
  • odom_child_frame_id (string, default: base_link): Value of the child_frame_id field in the Odometry message published on the nav/odom topic.
  • publish_gps (bool, default: true): Sets if ~gps/fix should be advertised/published or not. Note - to maximize performance you may want to only publish the Odometry messages
  • gps_rate (int, default: 1): Target update (publishing) rate for gps/fix messages. See update [[#rates] Update Rates] below.
  • imu_rate (int, default: 10): Target update (publishing) rate for imu/data messages. See update [[#rates] Update Rates] below.
  • odom_rate (int, default: 10): Target update (publishing) rate for nav/odom messages. See update [[#rates] Update Rates] below.
여기서 data update rate는 Hz 단위이다. 데이터 packet rate는 base_rate/decimation 이다. 3DM-GX4-45의 경우, 다음 rate에서 테스트되었다.
  • GPS - base rate = 4 Hz
  • IMU - base rate = 500 Hz
  • Filter - base rate = 500 Hz
Odometry 메시지는 현재 pos.position인 longitude(x), latitude(y)와 ellipsoid height(z)값을 리턴해 준다. pose.covariance와 twist.covariance는 position와 attitude의 대각성분(diagonal element)를 포함하고 있다.

Nav Status 메시지 통신 프로토콜은 다음과 같다. 
  • filter_state
    • 0x00 – Startup
    • 0x01 – Initialization (see status flags)
    • 0x02 – Running, Solution Valid
    • 0x03 – Running, Solution Error (see status flags)
  • dynamics mode
    • 0x01 – Portable (device default)
    • 0x02 – Automotive
    • 0x03 – Airborne
  • status_flags
    • See device documentation
Nav Sat Fix 메시지는 다음과 같다. Position co-variance는 수평, 수직 정확도를 기반으로 대각성분을 채운다. status.status 필드는 LLH() position data "valid flag"-1이다.
  • 0x0001 – Latitude and Longitude Valid
  • 0x0002 – Ellipsoid Height Valid
  • 0x0004 – MSL Height Valid
  • 0x0008 – Horizontal Accuracy Valid
  • 0x0010 – Vertical Accuracy Valid
  • E.g., if all valid, then the status.status field should be 30.
함께 제공되는 mip_sdk_user_functions은 C함수 API로 RS232를 통해 센서와 명령+데이터를 입출력할 때 사용한다.

IMU 데이터 이용한 각도와 위치 예측
IMU 데이터에서 각도와 위치를 예측할 수 있으면, INS(Inertial Navigation System. 관성항법 장치)를 개발할 수 있다. 이 글에서 각도는 앞서 설명한 ROS 노드에서 이미 계산되어 제공한다. 각도는 각속도를 적분해 얻는 데, 칼만 필터 등을 이용해 잡음을 제거한다. 좀 더 상세한 계산 방법은 다음을 참고한다.
단순하게는 다음과 같이 중력 가속도를 제거하고, 적분하면 된다. 하지만, 적분 시간이 길어지면, 노이즈가 누적되어 발산되는 경향이 있다.
Ax = (Ax - 9.81 sin pi) cos pi
Ay = (Ay - 9.81 sin pi) cos pi
Vx = Ax * timeDelta
Vy = Ay * timeDelta
Dx = Dx + Vx * timeDelta
Dy = Dy + Vy * timeDelta

노이즈 제거를 고려한 IMU 데이터에서 위치 예측은 좀 더 복잡하다. 여기서는 Mike Koch가 정리한 알고리즘을 참고해 설명한다.
  • 현재 시간의 각속도 ax, ay, az, 가속도 accX, accY, accZ를 획득한다.
  • 가속도 크기 magnitute = sqrt(accX ^ 2 + accY ^ 2 + accZ ^ 2)
  • 노이즈 제거를 위해 high-pass filter 사용
    • 가속도 데이터에서 특정 범위 이외 값은 제거함
    • butterworth 필터 적용. cutoff frequency n = 1이며, Wn = (2 * cutoff) / (1 / samplePeriod). samplePeroid는 읽기 사이의 시간 간격임. 필터 타입 ftype = 'high'임
    • zero-phase 디지털 필터 수행
  • 필터된 값의 절대값 취함
  • low-pass filter 이용해 노이즈 제거
  • 자이로 데이터로부터 방향 취득
  • 가속도를 m/s^2 으로 변환
  • 가속도에서 속도를 계산
  • 속도로 부터 위치 적분
  • 앞의 로직 반복
다음은 IMU 기반 각도 및 위치 계산 알고리즘 소스코드(matlab) 설명이다. 

% IMU 값 읽기
samplePeriod = 1/256;   % sampling 간격
xIMUdata = xIMUdataClass(filePath, 'InertialMagneticSampleRate', 1/samplePeriod);  % IMU 데이터 획득
time = xIMUdata.CalInertialAndMagneticData.Time;                   % 시간
gyrX = xIMUdata.CalInertialAndMagneticData.Gyroscope.X;         % 각속도
gyrY = xIMUdata.CalInertialAndMagneticData.Gyroscope.Y;
gyrZ = xIMUdata.CalInertialAndMagneticData.Gyroscope.Z;
accX = xIMUdata.CalInertialAndMagneticData.Accelerometer.X;    % 가속도
accY = xIMUdata.CalInertialAndMagneticData.Accelerometer.Y;
accZ = xIMUdata.CalInertialAndMagneticData.Accelerometer.Z;

acc_mag = sqrt(accX.*accX + accY.*accY + accZ.*accZ);     % 가속도 크기 

% 필터 적용
filtCutOff = 0.001;                                                     % cut off 설정
[b, a] = butter(1, (2*filtCutOff)/(1/samplePeriod), 'high');    % butter worth filter 계산
acc_magFilt = filtfilt(b, a, acc_mag);
acc_magFilt = abs(acc_magFilt);                                    % 가속도 절대값 획득

filtCutOff = 5;
[b, a] = butter(1, (2*filtCutOff)/(1/samplePeriod), 'low');      % low 필터 적용
acc_magFilt = filtfilt(b, a, acc_magFilt);
stationary = acc_magFilt < 0.05;                                

% 방향 계산
quat = zeros(length(time), 4);
AHRSalgorithm = AHRS('SamplePeriod', 1/256, 'Kp', 1, 'KpInit', 1);
initPeriod = 2;
indexSel = 1 : find(sign(time-(time(1)+initPeriod))+1, 1);
for i = 1:2000
    AHRSalgorithm.UpdateIMU([0 0 0], [mean(accX(indexSel)) mean(accY(indexSel)) mean(accZ(indexSel))]);
end
for t = 1:length(time)
    if(stationary(t))
        AHRSalgorithm.Kp = 0.5;
    else
        AHRSalgorithm.Kp = 0;
    end
    AHRSalgorithm.UpdateIMU(deg2rad([gyrX(t) gyrY(t) gyrZ(t)]), [accX(t) accY(t) accZ(t)]);
    quat(t,:) = AHRSalgorithm.Quaternion;
end
acc = quaternRotate([accX accY accZ], quaternConj(quat));
acc = acc * 9.81;   % 방향 계산

% 이동량 계산
acc(:,3) = acc(:,3) - 9.81;   
vel = zeros(size(acc));
for t = 2:length(vel)
    vel(t,:) = vel(t-1,:) + acc(t,:) * samplePeriod;
    if(stationary(t) == 1)
        vel(t,:) = [0 0 0];     % force zero velocity when foot stationary
    end
end

velDrift = zeros(size(vel));
stationaryStart = find([0; diff(stationary)] == -1);
stationaryEnd = find([0; diff(stationary)] == 1);
for i = 1:numel(stationaryEnd)
    driftRate = vel(stationaryEnd(i)-1, :) / (stationaryEnd(i) - stationaryStart(i));
    enum = 1:(stationaryEnd(i) - stationaryStart(i));
    drift = [enum'*driftRate(1) enum'*driftRate(2) enum'*driftRate(3)];
    velDrift(stationaryStart(i):stationaryEnd(i)-1, :) = drift;
end

vel = vel - velDrift;

% 이동 위치 계산
pos = zeros(size(vel));
for t = 2:length(pos)
    pos(t,:) = pos(t-1,:) + vel(t,:) * samplePeriod;    % integrate velocity to yield position
end

마무리
이 글에서는 고정밀 GNSS와 ROS를 연동하는 방법을 간단히 소개하였다. GNSS와 LiDAR 데이터를 연계하면, 실시간으로 하나의 좌표계안에 정합된 스캔 데이터 점군을 획득할 수 있다. 이는 로보틱스, 자율주행차와 같이 실시간으로 공간정보를 획득해야 할 때 매우 유용한 기술이다. 

레퍼런스