PX4에서 앱을 만들고 SITL 상에서 실행시키는 'Hello World' 수행 예시를 정리하고자 하는 목적으로 작성한다. PX4에서 새로운 앱을 만들어 구동시키고자 한다면 PX4-Autopilot/src/ 폴더에서 수행해야 한다. 본 예제를 위해서는 새 디렉토리 'px4_simple_app'을 PX4-Autopilot/src/examples 하위에 생성한다. 이후 폴더와 동일한 이름의 px4_simple_app.c를 생성하고 아래 Hello World가 수행되는 코드를 붙여준다.

 

1. px4_simple_app.c 파일 생성

#include <px4_platform_common/log.h>

__EXPORT int px4_simple_app_main(int argc, char *argv[]);

int px4_simple_app_main(int argc, char *argv[])
{
   PX4_INFO("Hello roytravel!");
   return 0;
}

 

코드를 간단히 설명하자면 #include <px4_platform_common/log.h>를 통해 C언어의 printf와 같은 PX4의 출력 함수인 PX4_INFO를 실행할 수 있도록 라이브러리를 불러온다. 그리고 main 함수를 만들어주되 main 앞에 추후 PX4 상에서 사용할 모듈 이름을 함께 사용해준다. 이후 위 .c 파일과 마찬가지로 PX4-Autopilot/src/examples/px4_simple_app/ 하위에 CMakeLists.txt 파일을 만들어준다.

 

2. CMakeLists.txt 파일 생성

px4_add_module(
 MODULE examples__px4_simple_app
 MAIN px4_simple_app
 SRCS
     px4_simple_app.c
 DEPENDS
 )

 

MODULE은 PX4-Autopilot/src 하위의 examples에서 '/'를 '__'로 치환한 다음 모듈 이름을 적어주는 것 같다.

MAIN은 PX4 셸 또는 SITL 콘솔에서 호출할 수 있도록 NuttX에 명령을 등록하는 모듈의 진입점이라고 한다.

SRCS는 말그대로 빌드할 소스코드들을 기술한다. DEPENDS는 의존 라이브러리가 없으므로 널 값으로 보인다.

 

3. Kconfig 파일 생성

마찬가지로 PX4-Autopilot/src/examples/px4_simple_app/ 하위에 별도 확장자 없이 Kconfig 파일을 생성해주고 아래와 같이 값을 추가해준다.

 bool "PX4 Simple app"
 default n
 ---help---
     Enable PX4 simple app

 

4. boardconfig 설정

 

이후 PX4-Autopilot/ 경로에서 make px4_sitl_default boardconfig 명령을 통해 examples에 들어가 px4_simple_app을 추가해준다. 이는 px4_simple_app 모듈이 펌웨어로 컴파일 될 수 있도록 설정하는 것이다.

 

 

 

 

 

 

5. px4_simple_app 실행

PX4-Autopilot/ 디렉터리에서 make px4_sitl_default gazebo 명령을 수행한 뒤 pxh 셸에서 help를 수행해보면 다음과 같이 px4_simple_app 모듈이 명령어로써 사용가능 하도록 추가되어 있다.

 

이후 px4_simple_app 명령을 수행하면 다음과 같이 모듈이 구동되는 것을 확인할 수 있다.

 

Reference

[1] https://docs.px4.io/main/ko/modules/hello_sky.html

'Computer Science > 로봇공학' 카테고리의 다른 글

TIL (230626)  (0) 2023.06.26
Gazebo 환경변수 목록  (0) 2023.06.24
[PX4] Lockstep이란?  (0) 2023.06.19
uXRCE-DDS 미들웨어와 드론 비행제어  (0) 2023.06.19
ROS2 커스텀 interface 생성하기  (0) 2023.06.11

PX4에서 lockstep이란 PX4와 시뮬레이터(ex: Gazebo) 간 동기화/비동기화 여부를 의미한다. Lockstep이 설정되어 있을 경우 PX4와 시뮬레이터는 자체 속도로 실행되지 않고 센서와 액츄에이터 메시지를 서로 기다리게 된다. 만약 설정되어 있지 않을 경우 PX4와 시뮬레이터는 각자의 속도로 수행된다. 이를 설정하기 위한 두 방법이 있다. 첫 번째는 PX4에서 설정하는 것이고 두 번째는 시뮬레이션 관련 파일에서 설정하는 것이다. 

 

PX4에서 Lockstep을 해제하기 위해서는 make px4_sitl_default boardconfig 명령을 통해 보드 설정으로 접속하면 다음과 같은 화면을 볼 수 있다.

 

위 화면에서 방향키를 이용해 Toolchain에 들어가면 아래와 같이 “Force disable lockstep”이 있다.

 

기본값으로 활성화로 설정되어 있고 비활성화를 원할경우 엔터를 통해 비활성화 설정이 가능하다.

 

만약 시뮬레이션(Gazebo)에서 Lockstep을 해제하기 위해서는 SDF 파일 수정이 필요하며 아래 요소를 .sdf 파일에 추가해준다.

<enable_lockstep>false</enable_lockstep>

ROS에서 명령을 실행하는 방법은 두 가지로 run과 launch가 있다. run은 단일한 명령이고 launch는 run의 집합이다. 만약 두 개의 ros 명령을 수행하려면 터미널 두 개를 띄우거나 실행하려는 두 명령을 다 입력해주어야 한다. ROS를 다루다보면 여러 ROS 명령을 수행해야 하므로 효율성을 위해 사실상 launch를 실질적으로 더 많이 사용한다. 파이썬을 이용해 launch 파일을 만들고 gazebo와 rviz를 띄우는 일종의 hello world를 수행해보자.

 

이를 위해 가장 먼저 작업 디렉터리를 생성하고 작업 디렉터리로 들어간다.

mkdir -p test_ws/src
cd test_ws/src

 

ROS는 패키지 단위로 프로그래밍이 이뤄지므로 아래 ROS 명령을 통해 패키지를 생성한다.

ros2 pkg create gazebo_pkg --build-type ament_python

 

“gazebo_pkg”는 생성할 패키지 명이다. --buile-type은 사용할 빌드 시스템을 의미한다. ROS1에서는 catkin이 사용되었으나 ROS2에서는 catkin의 업그레이드 버전인 ament를 사용한다. 여기서 ament_python은 파이썬 전용 ament 빌드 시스템이다. 위 명령어를 수행하면 다음과 같이 패키지 폴더가 생성되며 폴더로 들어가면 아래와 같은 파일이 자동으로 생성된다.

 

 

목표는 시뮬레이션을 위한 gazebo와 시각화를 위한 rviz를 같이 띄우는 것이다. 이를 위해 launch 파일을 만들어야 하며 이러한 launch 파일이 담길 폴더를 ‘launch’로 생성해준다. 이는 ROS 개발에 있어 컨벤션으로 가급적 지켜주면 좋다. 이후 test.launch.py를 만들어 준다.

 

 

이후 gazebo와 rviz2를 실행하는 아래 코드를 test.launch.py 파일에 작성해준다

from launch import LaunchDescription
from launch.actions import ExecuteProcess

def generate_launch_description():
    
    return LaunchDescription([
        ExecuteProcess(
            cmd=["gazebo"], output="screen"
        ),

        ExecuteProcess(
            cmd=["ros2", "run", "rviz2", "rviz2"], output="screen"
        ),
    ])


코드를 살펴보자면 launch 파일이 실행되기 위해 반드시 generate_launch_description 함수를 만들어야 한다. 이후 LaunchDescription에 수행할 명령을 리스트로 담아주면 된다. LaunchDescription은 해당 launch 파일이 실행해야 할 목록을 기술하는 클래스다. 안을 살펴보면 ExecuteProcess 클래스가 두 개 있다. 사용법이 매우 간단한 형태로 수행할 명령을 cmd 인자에 입력해주고 output 인자를 통해 로그를 터미널에 출력해줄 수 있도록 screen을 입력한다.

 

cd ~/test_ws

 

source /opt/ros/humble/local_setup.bash

  • ROS2 환경을 현재 셸 세션에 로드하여 ROS2 실행에 필요한 실행파일, 라이브러리, 환경변수 등에 접근할 수 있도록 하는 명령어다.
  • 터미널이 새로 열릴 때 마다 새로운 세션이 생성되므로 매번 입력해주어야 한다. 귀찮다면 .bashrc에 해당 명령어를 입력해두면 터미널이 생성될 때 마다 자동으로 실행된다.
  • 참고로 setup.bash가 있고 local_setup.bash가 있다. 둘 간의 차이점은 전자는 전역적으로 설치된 패키지 설정이고 후자는 지역적으로 설치된 패키지에 대한 설정을 수행한다. setup.bash를 수행하면 전역적으로 수행되어 간편하지만 다른 패키지와 충돌(?)이 발생할 수 있으므로 가급적(?) local_setup.bash를 사용한다.

만약 위 명령을 수행하지 않고 launch 파일을 실행하면 다음과 같이 만들어주었던 패키지 폴더를 찾지 못했다는 에러를 확인할 수 있다.

 

 

위 명령을 수행하고 다시 실행해보자. 이번엔 다른 에러가 발생했다. gazebo_pkg 폴더 안에 test.launch.py가 없다고 한다.

 

이렇게 에러가 발생하는 이유는 빌드 당시 setup.py를 제대로 설정해주지 않아서 발생한다.

 

~/test_ws/src/gazebo_pkg/setup.py에 들어가서 아래 15번째 줄에 있는 os.path.join(’share’, package_name, ‘launch’), glob(’launch/*.launch.py’))를 추가해주자. (import os, from glob import glob도 함께)

 

 

 

이후 다시 colcon build --symlink-install --packages-select gazebo_pkg 명령을 통해 빌드를 다시 수행한 뒤, launch 파일 실행을 위해 ros2 launch gazebo_pkg test.launch.py를 수행해주면 아래와 같이 gazebo와 rviz2가 함께 실행되는 것을 확인할 수 있다.

 

 

만약 gazebo를 실행할 때 시뮬레이션 환경이 구성되어 있는 world 파일을 넣고자 한다면 test.launch.py와 setup.py를 아래와 같이 살짝만 코드를 바꿔 world 파일 경로 인자를 추가해주는 방식으로 gazebo 실행 시 이미 만들어진 시뮬레이션 환경을 구성할 수 있다. (world 파일이 없다면 이전 포스팅 참고)

 

import os
from glob import glob
from setuptools import setup

package_name = 'gazebo_pkg'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages', ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join('share/', package_name, 'launch'), glob('launch/*.launch.py')),
        (os.path.join('share/', package_name, 'worlds'), glob('worlds/*.world'))
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='roytravel',
    maintainer_email='roytravel@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
        ],
    },
)

참고로 리스트 data_files에 담긴 튜플 인자 두 개를 사용해 폴더와 파일을 복사한다. 두 번째 인자의 폴더와 파일을 복사해 첫 번째 인자에 있는 경로로 복사한다.

 

setup.py

import os
from launch import LaunchDescription
from launch.actions import ExecuteProcess
from ament_index_python.packages import get_package_share_directory

def generate_launch_description():
    package_name = 'gazebo_pkg'
    world_filename = 'test.world'
    packge_path = os.path.join(get_package_share_directory(package_name))
    world_path = os.path.join(packge_path, "worlds", world_filename)
    
    return LaunchDescription([
        ExecuteProcess(
            cmd=["gazebo", world_path], output="screen"
        ),

        ExecuteProcess(
            cmd=["ros2", "run", "rviz2", "rviz2"], output="screen"
        ),
    ])

 

위와 같이 작성해주고 재빌드를 해준 뒤 launch 파일을 실행하면 gazebo를 실행할 때 직접 만들어 두었던 world 파일을 적용하여 gazebo를 실행시킬 수 있다.

 

 

 

Gazebo를 통해 시뮬레이션을 수행하기 위해선 시뮬레이션 환경구성에 필요한 모델을 추가해야 한다. 가령 자율주행이라면 모델은 차, 버스, 신호등, 횡단보도 등이 될 수 있다. 이러한 모델을 통해 구성한 시뮬레이션 환경은 반복해서 사용하기 때문에 Gazebo를 실행할 때 마다 이미 만들었던 모델을 불러올 수 있어야 한다. 이를 불러오기 위해서는 모델들을 담은 .world 파일이 필요하다. gazebo에서 모델을 만든 다음 .world 파일로 저장함으로써 생성할 수 있다.

 

gazebo 실행

gazebo --verbose


gazebo가 실행되면 위와 같이 아무 것도 없는 plane world가 나타난다. 이후 Insert 탭을 통해 모델을 추가하여 world를 구성할 수 있다.

 

 

로컬에 저장해둔 모델이 있다면 이를 사용할 수도 있지만 서버에서 제공해주는 모델을 사용해서 world를 구성할 수 있다. 맨 아래 http://models.gazebosim.org를 클릭해보면 해당 서버에서 제공해주는 모델 리스트를 아래와 같이 확인할 수 있다.

 

 

간단한 예시로 Bus와 SUV를 다음과 같이 불러올 수 있다.

 

 

world 파일로 저장하는 단축키인 Ctrl + Shift + S를 통해 저장할 수 있다. test.world 파일로 다음과 같이 저장하고 gazebo를 종료한다.

 

 

두 모델이 담긴 world 파일을 불러오기 위해 gazebo가 실행될 때 아래와 같이 명령어를 입력해주면 구성했던 시뮬레이션 환경을 다시 로딩할 수 있다.

 

gazebo test.world

 

 

1. PX4 소스코드 설치 및 Bash 스크립트 실행

git clone https://github.com/PX4/PX4-Autopilot.git --recursive
cd PX4-Autopilot
bash ./Tools/setup/ubuntu.sh

 

2. Gazebo 시뮬레이터 설치

sudo apt-get install gazebo

 

3. Gazeo SITL 시뮬레이터 실행

make px4_sitl gazebo
  • gazebo가 지원하는 기체 전체목록은 make list_config_targets 명령시 확인 가능
  • 만약 위 명령을 수행했을 때 에러가 발생한다면 sudo apt-get upgrade gazebo 명령 필요

 

4. 드론 이륙 및 착륙 명령 실행

pxh> commander takeoff
pxh > commander land

 

5. QGroundControl 설치

5.1 명령어 실행

sudo usermod -a -G dialout $USER
sudo apt-get remove modemmanager -y
sudo apt install gstreamer1.0-plugins-bad gstreamer1.0-libav gstreamer1.0-gl -y
sudo apt install libqt5gui5 -y
sudo apt install libfuse2 -y

 

5.2 QGC 바이너리 다운로드

 

5.3 QGC 바이너리 실행

chmod +x ./QGroundControl.AppImage
./QGroundControl.AppImage

 

 

PX4와 QGC가 mavlink로 연결됨을 확인: INFO [mavlink] partner IP: 127.0.0.1

 

 

6. QGC의 시작 좌표 변경

  • 아래 위치(석촌호수)를 .bashrc에 저장하여 터미널을 실행할 때 마다 설정되도록 내용 추가
export PX4_HOME_LAT=37.506700 #위도
export PX4_HOME_LON=127.097598 #경도
export PX4_HOME_ALT=15 # 고도

 

 

7. 시뮬레이션 속도 변경

  • 실제 시간 대비 시뮬레이션 속도 증감 가능 (아래는 2배)
export PX4_SIM_SPEED_FACTOR=2

 

 

8. GUI 없이 Gazebo 실행

  • 더 빠른 시뮬레이터 실행과 더 적은 리소스 사용
HEADLESS=1 make px4_sitl gazebo
  • 환경변수로 등록하고 싶을 경우 아래은 내용을 .bashrc에 추가
export HEADLESS=1

 

Reference

[1] https://docs.qgroundcontrol.com/master/ko/getting_started/download_and_install.html

[2] https://kwangpil.tistory.com/100

+ Recent posts