[ROS] roslibjs 활용 예제
포스트
취소

[ROS] roslibjs 활용 예제

  1. 프로젝트에서의 사용 예시
    • JavaScript
    • Html
  2. 코드 리뷰
    • JavaScript
    • Html

3

1. 프로젝트에서의 사용 예시

KFQ 최종 프로젝트에서 사용한 코드의 일부분을 발췌하였다.

gazebo를 활용한 환경의 최종 코드에서 다음과 같이 웹 페이지가 출력된다.

스크린샷, 2021-12-01 11-36-07

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
61
62
63
64
function init() {
  // Connecting to ROS
  // -----------------
  var ros = new ROSLIB.Ros();
  // If there is an error on the backend, an 'error' emit will be emitted.
  ros.on('error', function(error) {
    document.getElementById('connecting').style.display = 'none';
    document.getElementById('connected').style.display = 'none';
    document.getElementById('closed').style.display = 'none';
    document.getElementById('error').style.display = 'inline';
    console.log(error);
  });

  // Find out exactly when we made a connection.
  ros.on('connection', function() {
    console.log('Connection made!');
    document.getElementById('connecting').style.display = 'none';
    document.getElementById('error').style.display = 'none';
    document.getElementById('closed').style.display = 'none';
    document.getElementById('connected').style.display = 'inline';
  });

  ros.on('close', function() {
    console.log('Connection closed.');
    document.getElementById('connecting').style.display = 'none';
    document.getElementById('connected').style.display = 'none';
    document.getElementById('closed').style.display = 'inline';
  });

  // Create a connection to the rosbridge WebSocket server.
  ros.connect('ws://localhost:9090');

  cmd_vel_listener = new ROSLIB.Topic({
    ros : ros,
    name : "/cmd_vel",
    messageType : 'geometry_msgs/Twist'
  });
  var twist = new ROSLIB.Message({
    linear: {
      x: 0,
      y: 0,
      z: 0
    },
    angular: {
      x: 0,
      y: 0,
      z: 0
    }
  });
  cmd_vel_listener.publish(twist);

  // Initialize the teleop.
  var teleop = new KEYBOARDTELEOP.Teleop({
    ros : ros,
    topic : '/cmd_vel'
  });
  teleop.scale = (1);

  // Then we add a callback to be called every time a message is published on this topic.
  cmd_vel_listener.subscribe(function(cmd_vel) {
    var vel_x = document.getElementById('vel_linear_x');
    vel_x.innerText = '전/후 속도 \u00A0'+cmd_vel.linear.x.toPrecision(10);
  });
}

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
35
36
37
38
39
40
41
<head>
    <!-- roslibjs & css -->
    <script type="text/javascript" src="http://static.robotwebtools.org/roslibjs/current/roslib.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/example.js"></script>
</head>

<body onload="init()">
    <!-- Title -->
    <div class="row page-titles mx-0">
        <div class="col-sm-6 p-md-0">
            <div class="navbar">
                <h4> Security Robot</h4>
                <div id="statusIndicator">
                    <p id="connecting">
                    Connecting to rosbridge...
                    </p>
                    <p id="connected" style="color:#00D600; display:none">
                    Connected
                    </p>
                    <p id="error" style="color:#FF0000; display:none">
                    Error in the backend!
                    </p>
                    <p id="closed" style="display:none">
                    Connection closed.
                    </p>
                </div>
            </div>
            <div class="card">
              <div class="card-body">
                  <div id="vel_linear_x">전/후 속도</div>
              </div>
            </div>
        </div>
    </div>
</body>

2. 코드 리뷰

JavaScript

1
var ros = new ROSLIB.Ros();

roslibjs 라이브러리를 사용할 준비를 한다. ROS와의 연결을 담당.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
ros.on('error', function(error) {
  document.getElementById('connecting').style.display = 'none';
  document.getElementById('connected').style.display = 'none';
  document.getElementById('closed').style.display = 'none';
  document.getElementById('error').style.display = 'inline';
  console.log(error);
});

// Find out exactly when we made a connection.
ros.on('connection', function() {
  console.log('Connection made!');
  document.getElementById('connecting').style.display = 'none';
  document.getElementById('error').style.display = 'none';
  document.getElementById('closed').style.display = 'none';
  document.getElementById('connected').style.display = 'inline';
});

ros.on('close', function() {
  console.log('Connection closed.');
  document.getElementById('connecting').style.display = 'none';
  document.getElementById('connected').style.display = 'none';
  document.getElementById('closed').style.display = 'inline';
});

ROS 통신 상태가 ‘error’인지, ‘connection’인지, ‘close’인지를 구분지어 표기해주기 위함이다.

Html에서 id를 통해 display style을 선택해주기 때문에, if 문으로 작성된 것과 같은 기능을 할 수 있다.

1
ros.connect('ws://localhost:9090');

rosbridgewebsocket server와 연결한다. localhost 부분의 ip 설정을 통해 다른 기기와도 연동이 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cmd_vel_listener = new ROSLIB.Topic({
  ros : ros,
  name : "/cmd_vel",
  messageType : 'geometry_msgs/Twist'
});
var twist = new ROSLIB.Message({
  linear: {
    x: 0,
    y: 0,
    z: 0
  },
  angular: {
    x: 0,
    y: 0,
    z: 0
  }
});
cmd_vel_listener.publish(twist);

cmd_vel_listener를 새로운 topic으로 지정한다. topic의 이름message type을 설정할 수 있다.

이를 활용하여, 이미 발행되고 있는 topic으로의 publisher 역할을 수행 할 수있다.

var twist = new ROSLIB.Message({~}) 내부의 메세지를 cmd_vel_listener topic으로 publish 하겠다는 뜻이다.

즉, /cmd_vel, 속도의 값을 전부 0으로 초기화 시키는 publisher라고 볼 수 있다.

1
2
3
4
5
  var teleop = new KEYBOARDTELEOP.Teleop({
    ros : ros,
    topic : '/cmd_vel'
  });
  teleop.scale = (1);

keyboardteleop.js 라이브러리를 활용.

/cmd_vel 토픽에 keyboard teleoperation 기능을 수행할 수 있다.

keyboardteleop.js에 대해서는 추후 포스팅 예정이다.

1
2
3
4
cmd_vel_listener.subscribe(function(cmd_vel) {
  var vel_x = document.getElementById('vel_linear_x');
  vel_x.innerText = '전/후 속도 \u00A0'+cmd_vel.linear.x.toPrecision(10);
});

앞서 설정해준 cmd_vel_listener의 subscriberHtml document에 ‘vel_linear_x’라는 id로 제공한다.

Html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<div id="statusIndicator">
    <p id="connecting">
    Connecting to rosbridge...
    </p>
    <p id="connected" style="color:#00D600; display:none">
    Connected
    </p>
    <p id="error" style="color:#FF0000; display:none">
    Error in the backend!
    </p>
    <p id="closed" style="display:none">
    Connection closed.
    </p>
</div>

앞선 javascript를 활용하여 rosbridge web socket server와의 연결을 표시한다.

2

1
2
3
4
5
<div class="card">
  <div class="card-body">
      <div id="vel_linear_x">전/후 속도</div>
  </div>
</div>

다음과 같이 정상적으로 속도가 표기된다.

4


공식 wiki를 참고하면, 토픽 외에도 서비스와 액션도 가능하고, 활용도가 매우 무궁무진하다.

나는 roslibjs 공식 wiki를 보면서도, 처음에는 와닿지 않아서 헤매었다. 도움이 되면 좋을 것 같다.


참고

ros 공식 wiki

Robotwebtools (roslibjs 등 제공)

roslibjs 공식 wiki

keyboardteleopjs 공식 wiki

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.