/etc/dphys–swapfile 파일을 편집기로 열고 CONF_SWAPSIZE 부분의 값을 수정하고 저장한다.
# set size to absolute value, leaving empty (default) then uses computed value # you most likely don't want this, unless you have an special disk situation # CONF_SWAPSIZE=100 CONF_SWAPSIZE=1024
이 기체는 날개 폭 840mm 정도로 소형으로 가격이 저렴하면서 개조가 용이하고 비행 안정성도 어느정도 확보되어있다. 다만 일부 부분에 보강등이 필요하다. 자세한 내용은 아래 VTOL 개조하기 부분을 참조한다.
그림: miniSkywalker 기체
1. VTOL 에 관하여
VTOL 은 Vertical Take Off and Landing의 약자로 "수직으로 이착륙한다" 라는 의미이지만 통상적으로는 날개를 가지고 비행하는 항공기인데 이착륙을 헬기처럼 하는 비행기를 통칭한다. 대표적으로는 AV-8 헤리어나 MV-22 오스프리 같은 항공기가 있다.
하지만 이러한 비행기는 VTOL을 위해서 설계된 비행기이고 그 구조도 매우 복잡하므로 기존 기체를 개조하는 방식으로 접근하도록 한다.
사실 VTOL 비행기를 만드는 가장 간단한 방법은 기존의 고정익 비행기의 무게중심 부분에 4개의 날개를 가진 쿼드콥터를 얹는 방식이다. 대표적으로는 아래 그림과 같은 기체가 있는데 Funcup 이라는 고정익 비행기의 날개에 4개의 프로펠러를 장착할 수 있는 구조물을 만들고 수직비행 상태에는 드론처럼 비행하고 수평비행 상태에는 앞쪽의 프로펠러만 사용하여 비행하는 단순한 방식이다.
이러한 구조는 구현하기 쉬운 반면 수평비행 상태에서는 4개의 모터가 모두 놀게 되어 비행기에서 가장 꺼리는 죽은 하중(Dead weight)이 되고 만다. 그리고 비행중에 멈춰있는 프로펠러가 큰 항력을 발생시키므로 비행성능에도 악영향을 끼친다.
이러한 문제점을 해결하기 위해 나온 방식이 프로펠러를 수직과 수평 모든 상태에서 사용할 수 있도록 한 Tilt rotor형 항공기이다.
Tilt Rotor형 항공기(이하 틸트로터)는 비행기의 추력을 만드는 로터를 수직<-->수평 방향으로 변경하여 헬기와 같이 이/착륙 하며 수평상태로 변환 시 일반 비행기처럼 비행이 가능한 항공기로 대표적으로 MV-22 Osprey 혹은 한국항공우주연구원에서 개발한 스마트 무인기가 이에 해당한다.
이러한 방식의 항공기들은 공통적으로 프로펠러를 구동하는 엔진이 날개 끝에서 회전할 수 있다는 점을 확인할 수 있다.
RC 비행기로 상용 제품으로 구현된 기체는 E-Flite의 Convergence가 대표적이다.
이번에 제작한 기체는 바로 이 Convergence라는 기체에서 영감을 얻어 멀티로터 항공기처럼 모터의 회전수로 롤/피치 안정성을 확보하고 이 로터를 앞/뒤로 틸팅할 수 있는 틸트 서보를 장착하여 Yaw방향 안정성을 확보하는 방식이다. 자세한 내용은 아래 문서를 참고하면 된다.
PX4는 비행제어를 위한 소프트웨어로 쿼드콥터, 헥사콥터, 고정익 비행기 등 다양한 형태의 무인 비행기를 지원하나 이번에 제작하는 VTOL같은 형태의 경우에는 비행 모드에 따라 다른 서보 출력, 모터 출력을 만들어야하므로 이에 해당하는 설정 파일을 작성해야한다.
이 과정은 px4 프로젝트에 대한 이해를 필요로 하는데 바로 Build 후 업로드하여 설치하고싶다면 다음 git 저장소에서 https://github.com/kyuhyong/Firmware 프로젝트를 다운받고 "vtol_skywalker" 브렌치로 Checkout 하면 된다.
A. Airframe 추가하기
PX4 는 다양한 기체 형태를 지원하기 위해 각각의 설정을 개별적으로 수정하는 대신 하나의 파일로 만들어서 Booting과정에서 해당 파일을 읽어드려 설정하는 방식을 사용하고 있다. 이렇게 하면 기체 설정 파일만 있으면 px4가 탑재된 보드에 쉽게 설정을 옮기고 업로드할 수 있게 된다.
해당 파일들은 Firmware/ROMFS/px4fmu_common/init.d 에 존재한다.
Firmware/ROMFS/px4fmu_common/init.d/13014_vtol_mini_skywalker 내용 추가
# @output MAIN1 Motor right # @output MAIN2 Motor left # @output MAIN3 Motor back # @output MAIN4 Tilt servo right # @output MAIN5 Tilt servo left # @output AUX1 Aileron # @output AUX2 Elevator # @output AUX3 Rudder param set VT_MOT_COUNT 3 #엔진 혹은 모터의 갯수 param set VT_FW_MOT_OFFID 3 #수평 비행상태일때 반드시 꺼져야하는 모터의 위치 param set VT_IDLE_PWM_MC 1200 param set VT_TYPE 1 # VTOL 타입. 0=Tailsitter (꼬리로 이착륙 하는 형태), 1=틸트로터형, 2=Standard 형태 param set VT_B_TRANS_DUR 1.0 # 이착륙 모드로 전환할 때 걸리는 시간(초) param set VT_FW_DIFTHR_EN 1 # 전진방향 비행시 출력 디퍼렌셜 적용 여부 param set VT_FW_DIFTHR_SC 0.17 # 디퍼렌셜 출력의 스케일 게인: 러더 입력에 대한 출력 변화율 param set VT_FW_PERM_STAB 0 # 전진방향 비행시 Stabilization 적용 여부: 1로 설정하면 전진 비행시 무조건 Stabilize가 적용됨 param set VT_F_TRANS_DUR 1.2 # 전진방향 전환 시간(초) (최대 20초) param set VT_F_TR_OL_TM 4.0 # 대기속도 센서가 없을 경우 전진방향 전환 시간(초) (최대 30초) param set VT_TILT_FW 1.0 # 전진비행 시 틸트 서보의 위치 (0~1.0) param set VT_TILT_MC 0.0 # 수직비행 시 틸트 서보의 위치(0~1.0) param set VT_TILT_TRANS 0.45 # 전환 시 틸트 서보의 위치(0~1.0) param set VT_TRANS_MIN_TM 1.2 # 전진방향 전환 최소 시간(초) (0~20.0) param set VT_TRANS_P2_DUR 1.3 # 전진비행 2단계 전환 시간(초) (0.1~5.0) : 충분한 대기속도를 확보하여 고정익 항공기로 # 비행이 가능해질때까지 로터가 완전히 전진 방향으로 회전하는데 걸리는 시간 param set FW_ARSP_MODE 0 # 대기속도 모드: 0=노멀(가능하면 대기속도 사용), 1=대기속도 사용 안함 ... 이하 생략
그리고 이렇게 추가한 설정 파일을 Build과정에 추가하기 위해
Firmware/ROMFS/px4fmu_common/init.d/CMakeList.txt에 위에서 편집한 파일명을 추가한다.
13014_vtol_mini_skywalker
B.Mixer 파일 추가하기
위에서 만든 파일은 기체 설정, 제어 파라미터에 대한 설정일 뿐 실제 출력은 기체 형태와 서보의 배치, 구성에 따라 달라지므로 각각의 출력을 Mixing하는 과정이 필요하다. PX4에는 main과 aux 채널 각각에 대해 별도의 mixing을 적용할 수 있다. 자세한 방법은 https://dev.px4.io/en/concept/mixing.html 에 있는 문서를 참조한다.
Firmware/ROMFS/px4fmu_common/mixers/ 에서
메인 핀에 연결된 3개의 모터, 2개의 틸트 서보 출력을 위한 vtol_mini_skywalker.main.mix 파일을 추가하여 아래와 같이 편집한다.
복잡한 소프트웨어 프로젝트는 다른 프로젝트, 라이브러리 또는 프레임워크에 의존하게 되는 경우가 많다. Git(깃) 은 submodule(서브모듈)을 제공하여 이러한 과정을 돕는다. 서브모듈은 다른 repository(저장소)를 하나의 sub-folder로 추가할 수 있도록 한다.
Git 에서 Submodule을 사용하면 재사용되는 제네릭한 프로젝트들을 부모 프로젝트에서 분리해서 관리하기 쉽고 다른 프로젝트에 적용하기 쉽지만 사용하기가 번잡스러운 부분이 있다. 그래서 아래의 예를 통해 이해해보자.
서브모듈 추가하기
예를 들어 Slingshot(새총) 이라는 프로젝트를 개발중이라고 해보자. 이 프로젝트에는 y-shaped stick 과 rubber-band라는 코드가 있다.
이 시점에서 slingshot 폴더 안에 rock이라는 폴더가 생성되지만 사실 그 안에는 아무것도 존재하지 않는다.
새로운 버전의 깃 에서는 자동으로 내용물을 채우지만 이전 버전에서는 깃에서 rock의 내용을 명시적으로 다운로드해야 한다:
git submodule update --init --recursive
모든것이 잘 되었다면 이 변경점을 커밋하고 rock 폴더를 slingshot 저장소에 추가하게 된다.
깃허브에서는 rock 폴더 아이콘에 작은 표시를 붙여 이것이 서브모듈임을 나타낸다:
rock 폴더를 클릭하면 rock 저장소로 이동하게 된다.
이제 rock 저장소를 slingshot 저장소에 추가하였고 rock의 모든 내용들을 slingshot에 포함된 것처럼 사용할 수 있다.
slingshot 저장소에서 실행한 깃 명령어는 "부모 저장소"에서 동작한다. 그리고 rock 폴더 안에서 실행한 명령어는 단지 rock 저장소에서 동작한다.
cd ~/projects/slingshot
git log # log shows commits from Project Slingshot
cd ~/projects/slingshot/rubber-band
git log # still commits from Project Slingshot
cd ~/projects/slingshot/rock
git log # commits from Rock
서브모듈을 사용하는 프로젝트에 참가하기
이제 여러분이 Slingshot 프로젝트에 참가하는 협업자라고 가정해보자. git clone을 사용하여 slingshot 의 내용물을 다운로드하기 시작한다. 이 시점에서 rock 폴더를 들여다보면 아무것도 없는것을 확인할 수 있다.
다시 말하지만 깃은 명시적으로 서브모듈을 다운로드할것을 기대한다. 여기서 git submodule update --init --recursive를 사용할 수도 있지만 아래와 같이 clone 명령어를 변경하여 서브모듈 내용물을 포함하여 다운로드할 수 있다.
git clone --recursive <project url>
서브모듈로 변경
이미 존재하는 서브폴더를 외부에 의존적인 폴더로 변경하는 것은 약간 복잡하다. 다음 예를 보자.
magic roll-back can 이라는 새로운 프로젝트를 시작하기로 했는데 여기에는 rubber-band가 유용하다고 가정하자. slingshot 을 위해 만든 rubber-band를 독립적인 저장소로 분리하고 이것을 두개의 프로젝트에 서브모듈로 추가해야 한다.
먼저 rubber-band 폴더의 내용물을 slingshot에서 추출한다. git filter-branch 명령을 사용하여 rubber-band와 관련된 커밋만을 남겨둘 수 있다. git filter-branch 명령어는 우리의 저장소 이력을 재작성 하여 마치 rubber-band 폴더가 원래 저장소에 포함되지 않은것처럼 보이게 한다. git filter-branch명령어에 대해 더 자세히 알아보려면 다음 글을 참조한다.
slingshot안에 있는 rubber-band 를 자체적인 저장소로 동작하게 하기 위해서 slingshot 의 복사본을 만든다. cp -r 명령어를 사용하여 slingshot의 전체 폴더를 rubber-band 라는 폴더로 재귀 복사 한다.
cd ..
cp -r slingshot rubber-band
이 rubber-band는 또 다른 slingshot과 동일하지만 이제부터 rubber-band 저장소로부터 git filter-branch 명령어를 실행한다.
cd rubber-band
pwd # (double check before proceeding!)
git filter-branch --subdirectory-filter rubber-band -- --all
이 시점에서 rubber-band 라는 폴더는 slingshot 프로젝트와 유사하게 보이지만 rubber-band 폴더의 파일과 커밋 히스토리만을 갖게 된다.
이 폴더를 slingshot에서 복사하였기때문에 새 저장소는 여전히 slingshot에서 설정한 리모트 트래킹 브랜치(remote tracking branch)를 갖고있다. rubber-band 를 slingshot 에 푸시(push)하면 안되고 새로운 저장소에 푸시해야한다.
이제 깃허브에서 rubber-band라는 새로운 저장소를 만들고 리모트(remote)를 rubber-band로 업데이트한다. remote origin 이라고 가정하면 아래와 같이 입력한다.
rock을 추가할 때와 같이 저장소 안의 저장소를 갖게 되었다. 부모 저장소인 slingshot 그리고 두개의 "서브" 저장소인 rock 과 rubber-band를 포함하여 세개의 저장소가 되었다.
게다가 slingshot의 히스토리를 들여다보면 rubber-band가 폴더일때 만들었던 커밋들을 재발견 할 수 있다. folder를 삭제하더라도 히스토리가 삭제되는것은 아니다. 이것은 때때로 혼란스러울 수 있는데, rubber-band "자식" 저장소가 기존의 slingshot 커밋의 복사되고 변경된 버전의 사본을 갖고있기 때문이다.
불행하게도 이 시점에 협업자들이 slingshot을 pull 하게 되면 rubber-band 비어있게 된다. 협업자들이 아래 명령어를 실행하여 서브모듈의 모든 내용물을 다운로드하도록 해야한다.
git submodule update --init --recursive
rubber-band를 magic roll-back can에 서브모듈로 추가하고 싶다면 slingshot 에 rock을 추가한것처럼 반복하면 된다.