- ros2djs
- 프로젝트에서의 사용 예시
- JavaScript
- Html
- 코드 리뷰
- JavaScript
- Html
1. ros2djs
roslibjs, rosbridge 등을 제작한 robot webtools에서 제공하는 slam & navigation 관련 라이브러리이다.
rviz로 쉽게 표현되던 자율주행 관련 명령, 시각화를 roslibjs를 활용하여 웹으로 제공한다.
roslibjs의 위에 EaselJS 를 사용하여 표현한만큼, 플래쉬 개발에 익숙할 경우 더 이쁜 디자인으로 뽑아낼 수 있을 것 같다.
EaselJS는 HTML Canvas를 쉽게 활용하기 위해 개발된 오픈소스 라이브러리라고 한다.
2. 프로젝트에서의 사용 예시
KFQ 최종 프로젝트에서 사용한 코드의 일부분을 발췌하였다.
gazebo를 활용한 환경의 최종 코드에서 다음과 같이 웹 페이지가 출력된다.
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
function init() {
// Connecting to ROS
// -----------------
var ros = new ROSLIB.Ros();
// Create a connection to the rosbridge WebSocket server.
ros.connect('ws://localhost:9090');
// Create the main viewer.
var viewer = new ROS2D.Viewer({
divID : 'map',
width : 516,
height : 516
});
var nav = NAV2D.OccupancyGridClientNav({
ros : ros,
rootObject : viewer.scene,
viewer : viewer
});
var nav_status = new ROSLIB.Topic({
ros : ros,
name : '/move_base/status',
messageType : 'actionlib_msgs/GoalStatusArray'
});
// Then we add a callback to be called every time a message is published on this topic.
nav_status.subscribe(function(status) {
var length = status.status_list.length;
if (length == 1) {
// var nav_status = document.getElementById('nav_status');
if (status.status_list[0].text == "Goal reached.") {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '목표 지점 도착 완료';
}
else if (status.status_list[0].text == "This goal has been accepted by the simple action server") {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '목표 지점 전달 중';
}
else {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '명령 전달 진행 중';
}
}
else {
if (status.status_list[1].text == "Goal reached.") {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '목표 지점 도착 완료';
}
else if (status.status_list[1].text == "This goal has been accepted by the simple action server") {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '목표 지점 전달 중';
}
else {
nav_status.innerText = '명령 전달 진행 중';
}
}
});
}
Html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<head>
<!-- roslibjs & css -->
<script type="text/javascript" src="http://static.robotwebtools.org/roslibjs/current/roslib.min.js"></script>
<!-- <script type="text/javascript" src="https://static.robotwebtools.org/ros2djs/current/ros2d.min.js"></script> -->
<script src="https://static.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js"></script>
<script src="https://static.robotwebtools.org/EaselJS/current/easeljs.js"></script>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8/themes/base/jquery-ui.css" />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.23/jquery-ui.min.js"></script>
<script src="static/js/ros/ros2d.js"></script>
<script src="static/js/ros/example.js"></script>
</head>
<body onload="init()">
<!-- 자율주행 관련 메세지 -->
<div class="col-xl-4 mb-3 col-lg-6 col-xxl-6 col-md-6 container-box">
<div class="card h-100">
<div class="card-title text-center">
<br/><br/><br/><br/><br/><br/><br/><br/>
<div id="nav_status">자율 주행 메세지</div>
</div>
</div>
</div>
<!-- 지도 -->
<div class="col-xl-4 mb-3 col-lg-6 col-xxl-6 col-md-6 container-box">
<div class="card text-center">
<div class="card-body">
<div id="map" style='height: 100%; width: 100%;'></div>
</div>
</div>
</div>
</body>
3. 코드 리뷰
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Create the main viewer.
var viewer = new ROS2D.Viewer({
divID : 'map',
width : 516,
height : 516
});
var nav = NAV2D.OccupancyGridClientNav({
ros : ros,
rootObject : viewer.scene,
viewer : viewer
});
var nav_status = new ROSLIB.Topic({
ros : ros,
name : '/move_base/status',
messageType : 'actionlib_msgs/GoalStatusArray'
});
생성해준 map을 nav2djs의 OccupancyGridClientNav를 활용해서 여러 토픽들과 연결해 주었고,
nav_status를 통해서는 자율주행의 결과와 관련된 토픽에 연결해 주었다.
nav2djs 원본에서는 OccupancyGridClientNav를 통해서 slam & navigation 명령을 내리는 부분을 확인하면 Topic이 아닌 Action으로 연결 되어있다.
내가 아직 액션에 대해서 익숙하지 않은 이유인지, 작동이 잘 되지않아서 코드를 수정하여 토픽으로 연결해주었다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
nav_status.subscribe(function(status) {
var length = status.status_list.length;
if (length == 1) {
// var nav_status = document.getElementById('nav_status');
if (status.status_list[0].text == "Goal reached.") {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '목표 지점 도착 완료';
}
else if (status.status_list[0].text == "This goal has been accepted by the simple action server") {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '목표 지점 전달 중';
}
else {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '명령 전달 진행 중';
}
}
else {
if (status.status_list[1].text == "Goal reached.") {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '목표 지점 도착 완료';
}
else if (status.status_list[1].text == "This goal has been accepted by the simple action server") {
var nav_status = document.getElementById('nav_status');
nav_status.innerText = '목표 지점 전달 중';
}
else {
nav_status.innerText = '명령 전달 진행 중';
}
}
});
/move_base/status topic의 subscriber로 사용할 때, 메세지의 형태를 먼저 확인하고, 필요에 맞게 nav_status
라는 DOM에 내용을 배치하였다.
Html
1
<div id="map" style='height: 100%; width: 100%;'></div>
canvas로 map을 띄우고, 해당 캔버스 위에서 nav = NAV2D.OccupancyGridClientNav
와 맞는 명령들을 가능케 한다.
나는 일단 구현을 목표로 하여 캔버스의 크기를 조정한다거나, 내부의 이미지를 조정하는 기능은 사용하지 못했지만, 다 마련이 되어있다.
1
<div id="nav_status">자율 주행 메세지</div>
상황에 맞는 메세지가 출력된다.
nav2djs의 경우, 캔버스 안에 map 위의 마우스 좌표를 다시 변환하고, 변환된 좌표를 활용하여 주행과 관련된 토픽/액션 메세지를 전달하는 식으로 코드가 작성이 되어있다. 확대/축소 기능을 사용하기 위해서는 확대/축소 될 때마다 새로 좌표를 변환해주어야 하는데, 아직까지 나의 실력으로는 ajax를 활용하지 않으면 구현이 힘들어보였다. 원래는 단순히 마우스 휠을 통해 조정을 하려했지만 제대로 코드가 작동하지 않아서 일단 구현을 목표로 했었다. 아쉬움이 많은 만큼 다시 도전해보고싶다.
참고
ros 공식 wiki
Robotwebtools (roslibjs 등 제공)
roslibjs 공식 wiki
ros2djs 공식 wiki
EaselJS API Documents