ROS & Web page
Updated:
CAUTION
나는 웹과 서버, 프론트/백앤드에 전혀 지식이 없습니다. 이론적으로 틀린 내용이 있어도 적당히 필터링 해주시기 바랍니다.
ROS & Web
ROS는 단일 네트워크 환경으로 많이 쓴다. 하지만 rosbridge라는 것을 활용하여 web을 통한 원격 통신 또한 가능하다. 본 페이지에서는 flask를 사용해 웹 페이지를 생성하고, 이 웹 페이지에 ROS에서 publish하는 topic들을 확인할 것이다. 이 페이지의 마지막에서는, 서울에서 publish하는 topic을 부산에서 웹 페이지를 통해 확인할 수 있을 것이다.
Flask
먼저 웹 페이지를 생성할 Flask를 설치한다. Flask는 파이썬 웹 프레임워크(Python-web-framework)로, 파이썬 문법을 통해 간단한 웹 페이지를 생성할 수 있다. Flask 외에도 Django 같은 프레임워크도 있고, 이를 가장 많이 쓰는 것 같다. 이에 비해 Flask는 다소 기능은 적지만 간단하고 가볍고 직관적이라고 한다. 사실 파이썬 웹 프레임워크는 관심 영역 밖이고 나도 이번 기회에 처음 써보는 거라 대충 넘어간다. 아무튼 flask를 사용해 페이지를 생성해 보겠다.
$ python3 -m pip install flask # pip3 install flask
위와 같이 간단한 설치를 마치고 다음 파이썬 파일을 생성한다. 보통 이름은 app.py로 하는 것 같다. 워크스페이스는 다음과 같이 만든다.
└── Flask
├── static/
├── templates
│ └── subscriber.html
└── app.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/') # main url
def home():
return 'Hello, World!'
host = '0.0.0.0'
port = '9900'
if __name__ == '__main__':
app.run(host=host, port=port, debug=True)
Local에서만 값을 확인할거면 애초에 웹 페이지를 만들지도 않았다. 즉, 외부 네트워크에서도 우리가 만든 웹 페이지에 접속할 수 있어야 한다. 이를 위해 host = '0.0.0.0'
를 추가했다. app.run() 함수를 실행할 때 host 인자로 ‘0.0.0.0’을 주면 외부 네트워크의 접속을 허용한다는 의미이다. 다음으로 port 인지는 이름 그대로 접속 포트를 정하는 것이다. 처음에는 ‘5000’, ‘8080’ 등 해봤는데 얘네는 뭔가 역할이 있는 포트인가보다. 외부 네트워크에서 접속이 안됐다. 뭐 되면 그냥 해도 되지 않을까 싶다. 그래서 적당히 구글링하다가 ‘9900’이라는 임의의 포트 번호를 선정했다.
이제 파이썬 파일을 실행한다.
$ python3 app.py
위 사진처럼 메시지가 뜨고, 생성된 웹 페이지의 주소를 확인할 수 있을 것이다. 주소 형식은 xxx.xx.xx.xxx/port 형식일 것이다. 이 주소를 그대로 인터넷 주소창에 적기만 하면 웹 페이지에 접속할 수 있다. 그럼 어디서든 Hello, World! 가 떠있는 화면을 볼 수 있을 것이다.
이제 살짝만 바꿔 ROS 토픽을 띄우는 웹 페이지로 만들어보겠다. 먼저 위 파이썬 코드를 살짝만 수정한다.
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route('/') # main url
def index():
return render_template("subscriber.html")
host = '0.0.0.0'
port = '9900'
if __name__ == '__main__':
app.run(host=host, port=port, debug=True)
Hello, World! 를 지우고 subscriber.html 파일로 대체했다. 이제 저 subsrciber.html 을 만들면 된다.
rosbridge
아 맞다. rosbridge를 먼저 설치해준다. 뭐 언제하나 상관은 없다.
$ sudo apt-get install ros-melodic-rosbridge-server
roslibjs
웹 페이지를 만들고 ROS랑 상호작용하고 다 roslibjs를 통해 이뤄진다고 한다. roslibjs를 쓰기 위해서 npm을 설치해야 한다. npm은 다음 명령어로 설치할 수 있다.
$ sudo apt-get install npm
아마 바로 설치가 안될 수도 있다. 그렇다고 바로 구글링하러가지 않기를 바란다… npm을 설치하는 방법이야 잘 나와있지만 경험상 그렇게 하면 npm을 설치할 때 ROS 패키지가 다 날아가고, 또 ROS를 다시 설치하면 npm 관련이 다 날아간다. npm 설치가 바로 안되면 다음 방법을 통해 설치할 수 있다.
$ sudo apt-get install curl software-properties-common
$ curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
$ sudo apt-get install nodejs
npm을 설치하는 명령어는 없어보이지만 저래하면 암튼 npm이 깔린다. 터미널에서 npm -v
을 통해 확인할 수 있다. 정상적으로 버전이 뜨면 된 것이다. 아 그리고 이 방법을 쓰면 이제 sudo apt-get install npm
으로는 npm 설치가 불가능한 듯 하다. broken package 어쩌고 뜨는데… 꼬우면 우분투 밀면 된다. 암튼 이제 roslibjs을 사용할 수 있다.
토픽 publish, subscribe, 서비스 까지 한 번에 확인할 수 있다. 우리가 할 것은 ROS 네트워크의 토픽을 subscribe해서 웹 페이지에 띄우는 것이므로 필요없는 부분은 날리겠다. 전체 코드와 자세한 설명은 원본 링크에 있다.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="http://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script type="text/javascript" src="http://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
<script type="text/javascript" type="text/javascript">
// Connecting to ROS
// -----------------
var ros = new ROSLIB.Ros({
url : 'ws://localhost:9090'
});
ros.on('connection', function() {
console.log('Connected to websocket server.');
});
ros.on('error', function(error) {
console.log('Error connecting to websocket server: ', error);
});
ros.on('close', function() {
console.log('Connection to websocket server closed.');
});
// Subscribing to a Topic
// ----------------------
var listener = new ROSLIB.Topic({
ros : ros,
name : '/listener',
messageType : 'std_msgs/String'
});
listener.subscribe(function(message) {
console.log('Received message on ' + listener.name + ': ' + message.data);
listener.unsubscribe();
});
</script>
</head>
<body>
<h1>Simple roslib Example</h1>
<p>Check your Web Console for output.</p>
</body>
</html>
Subscribing to a Topic 부분을 보면 직관적으로 어떻게 하면 원하는 토픽을 웹 페이지로 띄울 수 있는지 감이 올 것이다. 위 내용을 templates/subscriber.html에 저장하겠다.
Test
이제 다시 파이썬 파일을 실행한다.
$ python3 app.py
그 후 rosbridge_websocket을 실행한다.
$ roslaunch rosbridge_server rosbridge_websocket.launch
다른 터미널에선 임의의 토픽을 publish 한다.
$ rostopic pub /listener std_msgs/String "Hello, World"
이제 웹 페이지에 접속한다.
아무것도 없다. flask에서 웹 페이지를 꾸며주지 않아서 그렇다. 일단은 f12를 눌러서 web console을 켜보자. f12 누르고 뜨는 이상한 창 상단에 뒤적거리다 보면 Console을 발견할 수 있을 것이다.
이렇게 새로고침 할 때마다 Hello, World! 가 콘솔에 출력되는 것을 볼 수 있다. 만약에 새로고침 없이 계속 반복적으로 값을 갱신하고 싶으면 listener.unsubscribe();
를 지우면 된다. 그리고 이 값들을 웹 페이지 내에 텍스트 박스 등을 통해서 이쁘게 띄우고 싶다면 구글링을 하면 된다.
후기
아 맞다. 이래하면 서울에서 뿌린거 부산에서 확인 못 하네요 ㅋㅋ 그 알아서 구글링해서 웹 콘솔 말고 페이지에 띄워야 확인 가능하지 그건 알아서들 합시다. 저도 아직 못했어요
Comments