2020년 9월 23일 수요일

LIO SAM 기반 SLAM 기술 소개, 빌드 및 활용

이 글은 LIO SAM 기반 SLAM 기술 소개 및 활용에 대해 간략히 설명한다.

개요

LIO SAM은 LOAM개발자가 기존 방법을 개선해 개발한 슬램 기술이다. 

LIO-SAM은 라이더 관성 주행 거리 측정법을 개발해, 루프 폐쇄를 포함한 다양한 상대 및 절대 포인트 측정을 여러 소스에서 통합한다. 관성 측정 장치 (IMU) 통합에서 추정된 모션은 포인트 클라우드의 왜곡을 제거하고 라이더 주행 거리 측정 최적화를 위한 초기 추측 데이터를 생성한다. 라이더 주행 거리 측정 솔루션은 IMU의 편향을 추정하는 데 사용된다. 이 결과로 다음과 같이 기존 LOAM보다 좋은 결과를 얻을 수 있다.

시스템 아키텍처는 다음과 같다. 

이 기술은 다음과 같이 IMU, LiDAR가 미리 준비되어 있어야 한다.

소스 빌드 및 실행

다음과 같이 실행해 소스코드를 빌드한다.

sudo apt-get install -y ros-kinetic-navigation
sudo apt-get install -y ros-kinetic-robot-localization
sudo apt-get install -y ros-kinetic-robot-state-publisher
wget -O ~/Downloads/gtsam.zip https://github.com/borglab/gtsam/archive/4.0.2.zip
cd ~/Downloads/ && unzip gtsam.zip -d ~/Downloads/
cd ~/Downloads/gtsam-4.0.2/
mkdir build && cd build
cmake -DGTSAM_BUILD_WITH_MARCH_NATIVE=OFF ..
sudo make install -j8
cd ~/catkin_ws/src
cd ..
catkin_make

실행은 다음과 같다. 

roslaunch lio_sam run.launch

미리 준비된 데이터로 스캔 데이터를 시뮬레이션할 수 있다.

rosbag play your-bag.bag -r 3

결과는 다음과 같다. 

마무리

LIO SAM은 LOAM과 유사한 방식(참고)으로 개발되었다. 특징점을 계산하기 위해, GSTAM 패키지를 사용한다. 성능에 대한 설명은 여기를 참고한다.

레퍼런스



2020년 9월 22일 화요일

ROS기반 로봇 다중 좌표 프레임 개념 및 사용 방법

이 글은 ROS 좌표 프레임 개념 및 사용 방법에 대해 간략히 정리한다. 

머리말

로봇 시스템은 다양한 로컬 좌표계 프레임으로 구성된다. 다음 그림과 같이 로봇의 각 파트가 움직일 때 하위 부분은 같이 움직어야 한다. 이들의 위치나 방향을 각각 계산하면 매우 복잡할 것이다. 그러므로, 상위 파트가 움직이면, 해당되는 좌표 그래프부터 부속된 하위 노드까지 좌표변환행렬을 계산 및 적파한다. 이를 scene graph라 한다.

scene graph

씬 그래프는 컴퓨터 그래픽에서 고전적인 솔류션이다.

다중 좌표 프레임(ROS)

ROS는 분산 처리 방식이라 메시지를 퍼블리쉬하는 방식으로 좀 복잡하게 처리된다. 

좌표계 프레임 정의
다음 그림은 로봇이 거친 표면을 이동할 때, 로봇 플렛폼의 좌표계와 roll, pitch 모션 등을 보여준다.  

맵, odom, base_link 프레임은 Coordinate Frames for Mobile Platforms ROS (REP 0120)문서에 기술되어 있다. 다음은 프레임 각 구성요소 설명이다.
  • map: world fixed frame(세계 고정 좌표 프레임)이다. Z축은 위를 향한다. 모바일 플랫폼 위치는 map 프레임에서 상대적이고, 시간에 따라 이동하지 말아야 한다. map 프레임은 연속적이지 않고, 맵 프레임 내 모바일 플랫폼 위치는 변화될 수 있다. 일반적 설정에서, 맵 프레임에서 센서 관찰 지점 기반 로봇 위치는 재계산된다. 맵 프레임은 장기간 전역 참조로써 유용하다. 맵 프레임의 z위치는 해발 고도와 동일하다. 
  • odom: odom은 world fixed frame이다. odom 프레임에서 모바일 플랫폼 위치는 시간에 따라 이동될 수 있다. odom 프레임 안에서 로봇 위치는 연속적이다. 일반적 설정에서 odom 프레임은 odometry(주행계) 소스를 기반으로 계산된다. 소스의 예는 휠 주행계(wheel odometry), 비쥬얼 오도메트리(visual odometry), IMU(inertial measurement unit) 센서 등이 된다. odom 프레임은 단기적 지역 참조에 유용하다.
  • base_footprint: base_footprint는 바닥에 대한 로봇 위치를 나타낸다. 바닥은 보통 다리를 지지한느 수평 지반을 말한다. 프레임 변환 요소는 
  • base_link: base_link는 모바일 로봇 베이스에 부착된다. base_link는 임의 위치 및 방향을 가진다. 모든 로봇 하드웨어는 서로 다른 base_link를 가진다. odom 프레임에 상대적이며, 롤 및 피치 각도는 0이고, yaw 각도는 base_link yaw각도와 일치한다. 이 좌표계는 인간형 로봇 이동시 안정적인 평면 정보를 제공한다.
  • gaze: head 위치 및 방향을 정의한 좌표 프레임이다. 카메라같은 센서와 관련해 보는 방향을 정의한다.
  • earth: ECEF의 원점이다. 이 프레임은 서로 다른 맵 프레임에서 여러 로봇의 상호 작용을 허용하도록 설계되었다. 
지구 같은 전역 참조와 관련해 좌표 프레임을 정의할 때, x축은 동쪽, y축은 북쪽, z축은 위로 정렬된다. 건물 실내와 같이 구조화된 환경에서는 건물 레이아웃 지도와 좌표계를 정렬하는 것이 좋다. 여러 층에서 작업하는 경우, 각 층에 좌표 프레임이 있는 것이 합리적일 수 있다. 

각 프레임요소는 다음과 같은 연결관계를 가진다. 참고로, 드론과 같은 로봇은 pressure_altitude 를 추가해 고도 좌표 프레임을 삽입할 수 있다.

다음 프레임 그래프는 earth에 기반한 다중 로봇의 좌표계 그래프를 보여준다.

참고로, 로봇이 원거리 이동하는 경우, map 을 전환해야 할 수도 있다.

이 SLAM에서는 odom, base_link 두 프레임을 사용한다. base_footprint는 높이 정보는 없으며, 2D pose 정보만 제공한다(position, orientation), base_stabilized는 로봇 높이에 대한 추가 정보를 제공한다. 로봇에 대한 AHRS, INS에서 얻은 로봇 자세(attitude. roll/pitch)를 추정하여 사용할 수 있다(hector_imu_attitute_to_tf 노드). base_link에서 laser_link로 변환은 static transform publisher와 robot state publisher에서 제공한다. 

ROS TF(Tranformation) 정의
hector_mapping와 같은 SLAM에서 tf는 스캔 데이터 변환을 위해 사용한다. tf는 다중 좌표 프레임을 유지하기위한 역할을 한다. tf는 특정 시점에서 두 좌표 프레임간의 점, 벡터 등을 계산한다. tf2는 tf를 개선한 것이다. 로봇 시스템은 월드 프레임, 기본 프레임 등과 같이 시간이 지만에 따라 변경되는 3차원 좌표 프레임이 있다. tf는 시간 경과에 따라 이런 모든 프레임을 추적하여 다음과 같은 계산을 할 수 있다. 
  • Where was the head frame relative to the world frame, 5 seconds ago?
  • What is the pose of the object in my gripper relative to my base?
  • What is the current pose of the base frame in the map frame?
tf는 분산 시스템에서 작동할 수 있어, 각 로봇 파트가 개별 컴퓨터에서 네트웍을 통해 통합된 좌표 변환 기반 동작을 수행할 수 있다(참고. tf 데모).

좌표 프레임 설정 예
좌표 프레임은 odom을 사용하지 않는다면, 다음과 같이 설정된다. 
    <param name="pub_map_odom_transform" value="true"/>
    <param name="map_frame" value="map" />
    <param name="base_frame" value="base_frame" />
    <param name="odom_frame" value="base_frame" />

이 경우, 퍼블리쉬 설정을 다음과 같이 처리한다.
    <param name="pub_map_odom_transform" value="false"/>

마무리 
이 글에서는 ROS 다중 좌표 프레임에 대해 간략히 정리해 보았다.

2020년 9월 20일 일요일

Flask, mysql, 파이썬 기반 Open API 서버 개발 방법

 이 글은 Flask, mysql, 파이썬 기반 Open API 서버 개발 방법을 간략히 정리한다. 이 방법은 Open API를 쉽게 만드는 기술 중 하나로, 파이썬 기반 오픈 API 개발 시 가장 많이 사용되는 구조이다.

구글 Open Restful API 서버 구조

머리말
본 개방형 API 서버는 다음과 같은 구조를 가지게 되다.

환경 준비

다음과 같이 관련 환경을 설정한다.

 sudo apt-get install mysql-server
 sudo ufw allow mysql
 sudo systemctl start mysql
 sudo systemctl enable mysql
 sudo /usr/bin/mysql -u root -p

 SHOW VARIABLES LIKE "%version%";

SELECT User, Host, authentication_string FROM mysql.user;
ALTER USER 'root'@'localhost' IDENTIFIED BY 'password';

create database study;
show databases;

SET GLOBAL validate_password_policy=LOW;

CREATE USER 'ktw'@'localhost' IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
GRANT ALL PRIVILEGES ON study.* to ktw@localhost;
FLUSH PRIVILEGES;
 
 만약, mysql 서버를 다른 PC에서 제한없이 접속하고자 한다면 다음 명령을 입력한다.
CREATE USER 'root'@'%' IDENTIFIED BY 'mac2008';
GRANT ALL PRIVILEGES ON * . * TO 'root'@'%' WITH GRANT OPTION;
FLUSH PRIVILEGES;

간단한 Flask 기반 Open API 서버 개발

다음과 같이 실행해 본다. 

pip install Flask flask-mysql

다음과 같이 코딩한다.

from flask import Flask, jsonify
from flaskext.mysql import MySQL

app = Flask(__name__)
mysql = MySQL()

# MySQL configurations
app.config['MYSQL_DATABASE_USER'] = 'my_user'
app.config['MYSQL_DATABASE_PASSWORD'] = 'my_password'
app.config['MYSQL_DATABASE_DB'] = 'my_database'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'

mysql.init_app(app)

@app.route('/')
def get():
    cur = mysql.connect().cursor()
    cur.execute('''select * from my_database.my_table''')
    r = [dict((cur.description[i][0], value)
                for i, value in enumerate(row)) for row in cur.fetchall()]
    return jsonify({'myCollection' : r})

if __name__ == '__main__':
    app.run()

다음과 같이 실행한다.

python my_app.py

그리고, http://127.0.0.1:5000 링크를 브라우저로 열어 본다.


레퍼런스

2020년 9월 18일 금요일

우분투에서 그래픽 기반 통합 개발환경 Eclipse, Sublime 설치 및 ROS 환경 설정

이 글은 우분투에서 그래픽 기반 통합 개발환경 설치하는 방법을 간단히 정리한다. 

이클립스 설치

Java를 설치한다.

sudo apt-get install default-jre
java -version

이 링크(www.eclipse.org/downloads/)에서 이클립스 설치 파일을 다운로드하고, 압축을 푼 후, 각 버전별로 설치한다.

 
다음과 같이 설치된 이클립스를 실행하고, 튜토리얼을 확인해 본다. 그리고, 프로젝트를 생성해 빌드해본다. 

이제 다음 링크를 참고해 ROS 개발환경을 설정한다.

http://wiki.ros.org/IDEs#Eclipse

서브라임 설치

sublime 편집기 설치 방법은 다음과 같다.

wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add -
sudo apt-add-repository "deb https://download.sublimetext.com/ apt/stable/"
sudo apt install sublime-text

subl

서브라임은 다양한 플러그인이 있어 이를 설치하면 개발에 필요한 거의 대부분의 작업을 편리하게 할 수 있다.

ctrl + shift + P 키를 클릭해 패키지 설치를 위해 package install 을 입력한다.

이제 다음 패키지를 입력해 각각 설치한다.

SlideBarEnhancements
Open folder

그리고, 편집기 메뉴의 view > side bar > show 클릭 후 왼쪽 사이트 뷰에, 편집하고자하는 파일들이 포함된 폴더를 드래그&드롭한다. 그럼 다음과 같이 편리하게 개발할 수 있다.


 

2020년 9월 17일 목요일

우분투 서버 원격 접속 시 필수적인 편집기 VIM 사용 방법

이 글은 우분투 서버 원격 제어를 위한 SSH에서 편집기 VIM 사용 방법을 간략히 정리한다. 

머리말

SSH는 윈도우 같은 클라이언트 컴퓨터에서 원격으로 같은 네트웍으로 묶여 있는 리눅스 서버를 제어하는 데 매우 편리하다. 하지만, GUI를 지원하지 않아, gedit 같은 편집기를 사용하기 어렵다(이 경우, x-server 에뮬레이션을 설치해야 한다). 

리눅스 서버에 원격으로 코딩을 하거나, 설정을 하는 경우, 편집기가 필수적인데, GUI가 없이 편리하게 사용할 수 있는 프로그램이 없으면 작업할 수가 없다. 이 경우 VI나 VIM을 사용한다.

VIM을 이용하면 왠만한 편집기 이상의 기능을 제공하여 편리하게 코딩이나 설정파일을 편집할  수 있다(VI보다 편리하다). 다만, 사용을 위해 몇가지 설정이 필요하다. 

설치 및 설정

다음 명령으로 VIM을 우분투에 설치한다.

sudo apt-get update
sudo apt-get install vim

편집기 컬러 설정을 다음과 같이 다운로드 받는다.
mkdir -p ~/.vim/colors
cd ~/.vim/colors
curl -O https://raw.githubusercontent.com/nanotech/jellybeans.vim/master/colors/jellybeans.vim

다음과 같이 편집기를 이용해 VIM 에디터를 설정한다. 참고로 "는 주석 표시이다.
sudo gedit ~/.vimrc
set number    " show line 
set ai            " auto indent
set si            " smart indent
set cindent           " c style indent
set shiftwidth=4    " auto indent space  4 column
set tabstop=4       " convert tab to 4 spaces
set expandtab 
set et
set ignorecase      " ignore case character
set hlsearch         " highlight for searching
set nocompatible   " enable arrow keys
set fileencodings=utf-8,euc-kr    " file save encoding as utf-8, euc-kr
set fencs=ucs-bom,utf-8,euc-kr   " korea text encoding as euc-kr, unicode
set bs=indent,eol,start    " enable backspace
set ruler                " show cursor on status line
set title                 " show title
set showmatch       " show match () {}
set wmnu              " enable auto complate when tab 
syntax on              " enable grammar highlight
filetype indent on   " highlight depending on file format
set mouse=a         " enable mouse position as cursor
colorscheme jellybeans

.vimrc를 저장한 후 다음과 같이 vim을 실행해보자. 코딩 전용 편집기처럼 문법에 따른 컬러와 각종 기능이 활성화될 것이다.
vim test.py

사용

vim 사용은 일반 편집기와는 다르다. 이는 원격에서도 사용할 수 있고, 그래픽이 없는 최소한의 자원에서도 사용할 수 있도록 단축키를 이용하도록 설계되었기 때문이다. 

vim은 편집기 명령 상태와 파일 편집 상태를 구분해 동작한다. 

vim을 실행하면 명령 상태이며, 이때 다음 명령을 실행해 파일을 저장, 종료, 라인 복사, 라인 붙여넣기, 라인 삭제 등을 수행할 수 있다. 

종료
:q

저장
:w

저장/종료
:wq

커서 이동
화살표 키 입력

커서있는 줄 복사
yy

블럭 복사 시작
v

블럭 복사 끝
y

커서 다음에 붙여 넣기
p

앞에서 문자열 찾기
/문자열

뒤에서 문자열 찾기
?문자열

뒤로 검색
n

앞으로 검색
N

문자열 old를 new로 변경
:%s/old/new

모든 문자열 old를 new로 변경
:%s/old/new/g

되돌리기(undo)
u

되돌린것 재 실행
ctrl + r

현재 폴더 출력
:cd

다음 명령을 입력하면 그때 편집상태가 된다. 이때는 텍스트를 입력, 수정할 수 있다. 

커서 앞에서 글자 입력 모드 전환
i
행 처음부터 입력 모드 전환
l

다시 명령 상태로 복귀하려면 ESC 키를 입력하면 된다.

마무리

이 글은 리눅서 서버에서 텔넷이나 SSH로 원격 접속 시 사용하는 대표적 편집기인 VIM에 대해 이야기해보았다. 이 프로그램은 Bram Moolenaar가 개발한 것으로 1991년에 발표되어 지금까지 널리 사용되는 오픈소스이다. VIM은 VI Improved의 약자로 최초는 1988년 아미가 커뮤터에서 개발하다 발전된 것이다. VIM은 VI에 비해 정규 표현식, 마우스, 맞춤법 검사, 문법 강조 등 기능이 있어 편리하다. 뿐만 아니라, 다음과 같은 스크립트를 지원해 편집을 자동화할 수 있다.

let i = 1
while i < 5
  echo "count is" i
  let i += 1
endwhile

서버를 원격으로 설정하거나 코딩할 경우, VIM은 필수 도구이다. 

2020년 9월 15일 화요일

우분투 서버 원격 제어를 위한 SSH 설치 및 윈도우 클라이언트 PowerShell 접속

이 글은 우분투 SSH 설치 및 윈도우 PowerShell 원격 접속에 관한 글이다. 

가끔 리눅스 서버를 만들다보면, 원격으로 서버 명령을 실행하고, 프로그램을 설치하고 싶을 때가 있다. 이러한 유지관리를 위해 보통 SSH, Telnet 등을 설치한다. 

머리말

SSH는 Secure Shell의 약자로, 암호화된 네트워크 프로토콜이다. 일반적으로 명령행에서 서버에 로그인해 원격으로 서버를 조작할 수 있다. 물론, 서버는 SSH 서버가 실행되고 있어야 한다.

SSH는 1995년 헬싱키 대학 연구자 Tatu Ylonen이 개발하였다. SSH의 목적은 TELNET, FTP 를 대치하는 것이었다. SSH는 오픈소스로 릴리즈되었고, 2006년 IETF(Internet Engineering Task Force)에서 SSH-2로 리비전되었다. SSH-2는 보안성이 더 강화된다. 1999년 OpenSSH가 개발되고, 2005년에는 운영체제 기본 기능으로 지원된다. 

SSH는 login, 호스트 리모트 컨트롤(Telnet기능), 명령 실행(rsh기능), 암호 인증, 터널링(tunneling), VPN, 서버 원격 모니터링, SFTP(SSH File Transfer Protocol) 등을 지원한다.

서버 SSH 설치

다음 명령을 리눅스 서버에서 입력해 ssh를 설치한다.
sudo apt-get install openssh-server
sudo apt-get install ssh
sudo systemctl enable ssh
sudo systemctl start ssh

다음 명령으로 설정을 변경할 수 있다. 파일안에는 사용 포트(기본 22번), 접속 주소, 공개키, 관리자 계정 루트 로그인 허용 옵션 등이 포함되어 있다. 설정 후 sudo service ssh restart를 한다.
sudo gedit /etc/ssh/sshd_config

방화벽에서 22번 포트를 허용한다.
sudo ufw enable
sudo ufw allow 22

ssh 설치 및 설정 후 테스트를 위해, 다음과 같이 ifconfig 명령 실행 후, 서버 IP를 확인한다.

클라이언트 윈도우 SSH 설치

다음 명령을 파워셀에서 입력해 ssh를 설치한다(참고).

Get-WindowsCapability -Online | ? Name -like 'OpenSSH*'
# This should return the following output:
Name  : OpenSSH.Client~~~~0.0.1.0
State : NotPresent
Name  : OpenSSH.Server~~~~0.0.1.0
State : NotPresent

# Install the OpenSSH Client
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
# Install the OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

# Both of these should return the following output:
Path          :
Online        : True
RestartNeeded : False

작동여부는 다음 명령으로 확인한다.

Test-NetConnection 128.30.1.1 -Port 22

만약 파워셀이 불편하다면, PUTTY 프로그램을 설치하여 SSH를 접속한다.

이제, 다음 메뉴에서 윈도우 방화벽에 SSH포트 22번을 열어준다.

시작-윈도우 시스템-제어판-시스템및보안-윈도우즈 방화벽-고급설정

고급설정에서 인바운드 규칙 선택 후, 작업 패널에서 새규칙을 선택해, 규칙 종류를 포트로 선택한다. 그리고, 허용할 포트번호를 다음과 같이 설정한다.

예) 22, 23, 80

클라이언트 접속 및 사용

윈도우즈에서 파워샐을 실행하고, ssh 계정@서버IP주소 를 다음과 같이 입력한다.

예) ssh ktw@172.30.1.24


sudo apt-get install 같은 명령을 입력해 보자. 잘 실행되는 것을 확인할 수 있다.

다만, 그래픽이 사용되는 프로그램 실행 시 QXcbConnection 에러가 발생한다. 이 경우는 X-server 에뮬레이션 윈도우 프로그램(VcXsrv, Xming 등)을 설치해야 한다. 

마무리
이 글에서는 SSH에 대해 정리하고, 예제를 설명하였다. 사실 전세계에서 사용되는 많은 서버는 리눅스를 기반으로 하고 있고 SSH는 기본으로 설치되어 있는 경우가 많다. SSH를 이용해 서버를 관리할 수도 있고, 해킹에 사용할 수도 있다는 것을 참고해야 한다. 
SSH 개발자는 이 기술을 이용해 많은 컨설팅과 사업을 하였고, 전세계에서 좋은 평판과 가치를 얻었다. 앞으로 오픈소스 기술은 더욱 확장될 것이고, SSH와 같은 도구의 사용 사례는 더욱 많아질 것이다.

Tatu Ylonen

레퍼런스

부록: Telnet설치

Telnet을 서버에 설치하는 순서는 다음과 같다.

sudo apt-get install xinetd telnetd
sudo gedit /etc/xinetd.conf

service telnet
{
    disable = no
    flags = REUSE
    socket_type = stream
    wait = no
    user = root
    server = /usr/sbin/in.telnetd
    log_on_failure = USERID
}

sudo gedit /etc/hosts.allow
in.telnetd: ALL

sudo /etc/init.d/xinetd restart

윈도우에서는 윈조우 기능 켜기/끄기 메뉴에서 텔넷 클라이언트 옵션을 체크하면 설치 된다. 그럼 파워셀에서 다음과 같이 텔넷 실행이 가능하다.

부록: 원격 파일 전송을 위한 ftp 설치 및 사용
리눅스 서버에서 원격으로 클라이언트에 파일을 다운로드, 업로드 하고 싶다면, ftp를 설치하거나 scp를 사용해야 한다. ftp설치는 다음과 같다.
sudo apt-get update
sudo apt-get install vsftpd
sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig

다음과 같이 방화벽을 설치, 설정한다.
sudo apt-get install ufw
sudo ufw allow 20/tcp
sudo ufw allow 21/tcp
sudo ufw enable
sudo ufw status verbose

다음과 같이 설정 파일을 열어 수정한다.
sudo vim /etc/vsftpd.conf
...
anonymous_enable=NO
local_enable=YES
write_enable=YES
chroot_local_user=YES
...

$ sudo systemctl restart vsftpd

다음과 같이 원격으로 접속해 사용한다. 참고로, 명령어는 get(파일 다운로드), mget(다중파일 다운로드), put(파일 업로드), ls(폴더 검색), cd(폴더 이동)이다.
$ ftp -p 172.30.10.3
ftp> prompt
interactive mode off
ftp> cd folder
ftp> get test.txt
ftp> put test.txt upload.txt
ftp> mget *
ftp> bye

2020년 9월 12일 토요일

웹서버에서 프로세스 실행 완료하면 이메일 보내기

이 글은 웹서버에서 프로세스 실행 완료하면 이메일 보내는 방법을 간략히 설명한다. 

프로세스 호출

우선 웹서버에서 특정 이벤트가 발생했을 때, 이멜을 보낼려면 프로세스 호출에 대해 이해해야 한다. 

 
 

 

프로세스 시그널

프로세스가 종료할 때 등 이벤트가 발생하면, 시그널 콜백 함수에서 이를 확인할 수 있다.

signal.signal(signal.SIGHUP,CloseAll)
signal.signal(signal.SIGCHLD,CloseAll)
signal.signal(signal.SIGALRM,CloseAll)
 

다음은 간단한 시그널 예제이다.
from time import sleep
import signal
import sys

def sigterm_handler(_signo, _stack_frame):
    # Raises SystemExit(0):
    sys.exit(0)

if sys.argv[1] == "handle_signal":
    signal.signal(signal.SIGTERM, sigterm_handler)

try:
    print "Hello"
    i = 0
    while True:
        i += 1
        print "Iteration #%i" % i
        sleep(1)
finally:
    print "Goodbye"

#---
import signal
import time

class GracefulKiller:
  kill_now = False
  def __init__(self):
    signal.signal(signal.SIGINT, self.exit_gracefully)
    signal.signal(signal.SIGTERM, self.exit_gracefully)

  def exit_gracefully(self,signum, frame):
    self.kill_now = True

if __name__ == '__main__':
  killer = GracefulKiller()
  while not killer.kill_now:
    time.sleep(1)
    print("doing something in a loop ...")

  print("End of the program. I was killed gracefully :)")

예제

이 예제는 roscore를 자동으로 실행하고, rostopic을 실행한 후 10초 뒤에  kill하는 프로그래이다.

import subprocess
from time import sleep, time
import os, signal

def proc_ros():
    process = subprocess.Popen(['roscore'])
    print('1. process', process.pid)
    # process.wait(10)
    sleep(10)

def proc_roslaunch():
    process = subprocess.Popen(['roslaunch', 'rplidar_ros', 'rplidar.launch'])
    print('2. process', process.pid)
    #process.wait(10)
    sleep(10)

def term_proc():
    process = subprocess.Popen(['rostopic', 'echo', '/scan'])
    print('3. process', process.pid)
    sleep(10)
    for i in range(10):
        sleep(2)
        process.kill()
        print('Timed out - killing', process.pid)

def check_kill_process(pstring):
    for line in os.popen("ps ax | grep " + pstring + " | grep -v grep"):
        fields = line.split()
        pid = fields[0]
        os.kill(int(pid), signal.SIGKILL)

proc_ros();
proc_roslaunch();
term_proc()
sleep(10)
term_proc()
sleep(10)
print('End program')

레퍼런스