Skip to content

Commit 9e53927

Browse files
committed
initial commit
0 parents  commit 9e53927

7 files changed

+458
-0
lines changed

.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# all "hidden" files
2+
.*
3+
4+
# node and javascript stuff
5+
node_modules/
6+
npm-debug.log
7+
8+
coverage

MarkerArrayClient.js

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/**
2+
* @author Russell Toris - [email protected]
3+
* @author Nils Berg - [email protected]
4+
*/
5+
6+
var ROSLIB = require('roslib');
7+
var ROS3D = require('ros3d');
8+
var EventEmitter2 = require('eventemitter2');
9+
10+
/**
11+
* A MarkerArray client that listens to a given topic.
12+
*
13+
* Emits the following events:
14+
*
15+
* * 'change' - there was an update or change in the MarkerArray
16+
*
17+
* @constructor
18+
* @param options - object with following keys:
19+
*
20+
* * ros - the ROSLIB.Ros connection handle
21+
* * topic - the marker topic to listen to
22+
* * tfClient - the TF client handle to use
23+
* * canvas - ...
24+
* * path (optional) - the base path to any meshes that will be loaded
25+
*/
26+
var MarkerArrayClient = function(options) {
27+
options = options || {};
28+
this.ros = options.ros;
29+
this.topicName = options.topic;
30+
this.tfClient = options.tfClient;
31+
this.canvas = options.canvas;
32+
this.path = options.path || '/';
33+
34+
// Markers that are displayed (Map ns+id--Marker)
35+
this.markers = {};
36+
this.rosTopic = undefined;
37+
38+
this.subscribe();
39+
};
40+
MarkerArrayClient.prototype.__proto__ = EventEmitter2.prototype;
41+
42+
MarkerArrayClient.prototype.subscribe = function(){
43+
this.unsubscribe();
44+
45+
// subscribe to MarkerArray topic
46+
this.rosTopic = new ROSLIB.Topic({
47+
ros : this.ros,
48+
name : this.topicName,
49+
messageType : 'visualization_msgs/MarkerArray',
50+
compression : 'png'
51+
});
52+
this.rosTopic.subscribe(this.processMessage.bind(this));
53+
};
54+
55+
MarkerArrayClient.prototype.processMessage = function(arrayMessage){
56+
var that = this;
57+
58+
arrayMessage.markers.forEach(function(message) {
59+
var markerName = message.ns + message.id;
60+
if(message.action === 0) {
61+
var updated = false;
62+
if(markerName in this.markers) { // "MODIFY"
63+
var markerItem = that.markers[markerName];
64+
var marker = markerItem[0];
65+
var node = markerItem[1];
66+
updated = marker.update(message);
67+
if(!updated) { // "REMOVE"
68+
node.unsubscribeTf();
69+
that.canvas.removeMarker(marker,node);
70+
delete that.markers[markerName];
71+
}
72+
}
73+
if(!updated) { // "ADD"
74+
var newMarker = new ROS3D.Marker({
75+
message : message,
76+
path : this.path,
77+
});
78+
newMarker.isSelectable = true; // XXX
79+
newMarker.isSceneOrtho = false; // XXX
80+
newMarker.id = message.id;
81+
newMarker.ns = message.ns;
82+
newMarker.frame_id = message.header.frame_id; // XXX
83+
newMarker.marker_type = message.type; // XXX
84+
var newNode = new ROS3D.SceneNode({
85+
frameID : message.header.frame_id,
86+
tfClient : this.tfClient,
87+
object : newMarker
88+
});
89+
this.markers[markerName] = [newMarker,newNode];
90+
that.canvas.addMarker(newMarker,newNode);
91+
}
92+
}
93+
else if(message.action === 1) { // "DEPRECATED"
94+
console.warn('Received marker message with deprecated action identifier "1"');
95+
}
96+
else if(message.action === 2 && markerName in this.markers) { // "DELETE"
97+
var markerItem = that.markers[markerName];
98+
var marker = markerItem[0];
99+
var node = markerItem[1];
100+
node.unsubscribeTf();
101+
canvas.removeMarker(marker,node);
102+
delete that.markers[markerName];
103+
}
104+
else if(message.action === 3) { // "DELETE ALL"
105+
for (var markerItem in that.markers){
106+
var marker = markerItem[0];
107+
var node = markerItem[1];
108+
node.unsubscribeTf();
109+
canvas.removeMarker(marker,node);
110+
}
111+
that.markers = {};
112+
}
113+
else {
114+
console.warn('Received marker message with unknown action identifier "'+message.action+'"');
115+
}
116+
}.bind(this));
117+
118+
this.emit('change');
119+
};
120+
121+
MarkerArrayClient.prototype.getObjectMarker = function(objectName){
122+
x = this.markers[objectName]
123+
if(x) {
124+
return x[0];
125+
}
126+
else {
127+
return undefined;
128+
}
129+
}
130+
131+
MarkerArrayClient.prototype.unsubscribe = function(){
132+
if(this.rosTopic){
133+
this.rosTopic.unsubscribe();
134+
}
135+
};
136+
137+
module.exports = MarkerArrayClient;

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# @openease/ros-client
2+
3+
[![npm (scoped)](https://img.shields.io/npm/v/openease/ros-client.svg)](https://www.npmjs.com/package/openease/ros-client)
4+
[![Build Status](https://travis-ci.org/ease-crc/ros-js-client.svg?branch=master)](https://travis-ci.org/ease-crc/ros-js-client)

ROSClient.js

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
2+
var ROSLIB = require('roslib');
3+
4+
/**
5+
* Establishes connection to a ROS master via websocket.
6+
**/
7+
module.exports = function(options){
8+
var that = this;
9+
// Object that holds user information
10+
this.flask_user = options.flask_user;
11+
// ROS handle
12+
this.ros = undefined;
13+
// URL for ROS server
14+
var rosURL = options.ros_url || 'ws://localhost:9090';
15+
// Use rosauth?
16+
var authentication = options.authentication === '' ? true : options.authentication === 'True';
17+
// URL for rosauth token retrieval
18+
var authURL = options.auth_url || '/wsauth/v1.0/by_session';
19+
// global rosprolog handle
20+
var prolog;
21+
22+
// true iff connection to ROS master is established
23+
this.isConnected = false;
24+
// true iff registerNodes was called before
25+
this.isRegistered = false;
26+
// true after registerNodes has completed
27+
this.nodesRegistered = false;
28+
29+
this.connect = function (on_connection,on_error,on_close) {
30+
if(that.ros) return;
31+
that.ros = new ROSLIB.Ros({url : rosURL});
32+
that.ros.on('connection', function() {
33+
that.isConnected = true;
34+
console.log('Connected to websocket server.');
35+
if (authentication) {
36+
// Acquire auth token for current user and authenticate, then call registerNodes
37+
that.authenticate(authURL, function() {
38+
that.on_connection(on_connection);
39+
});
40+
} else {
41+
// No authentication requested, call registerNodes directly
42+
that.on_connection(on_connection);
43+
}
44+
});
45+
that.ros.on('close', function() {
46+
console.log('Connection was closed.');
47+
that.ros = undefined;
48+
that.isRegistered = false;
49+
if(on_close) on_close();
50+
setTimeout(that.connect, 500);
51+
});
52+
that.ros.on('error', function(error) {
53+
console.log('Error connecting to websocket server: ', error);
54+
if(that.ros) that.ros.close();
55+
that.ros = undefined;
56+
that.isRegistered = false;
57+
if(on_close) on_error(error);
58+
setTimeout(that.connect, 500);
59+
});
60+
};
61+
62+
this.authenticate = function (authurl, then) {
63+
console.log("Acquiring auth token");
64+
// Call wsauth api to acquire auth token by existing user login session
65+
$.ajax({
66+
url: authurl,
67+
type: "GET",
68+
contentType: "application/json",
69+
dataType: "json"
70+
}).done( function (request) {
71+
if(!that.ros) {
72+
console.warn("Lost connection to ROS master.");
73+
return;
74+
}
75+
console.log("Sending auth token");
76+
that.ros.authenticate(request.mac,
77+
request.client,
78+
request.dest,
79+
request.rand,
80+
request.t,
81+
request.level,
82+
request.end);
83+
84+
// If a callback function was specified, call it in the context of Knowrob class (that)
85+
if(then) {
86+
then.call(that);
87+
}
88+
});
89+
};
90+
91+
function containerRefresh() {
92+
$.ajax({
93+
url: '/api/v1.0/refresh_by_session',
94+
type: "GET",
95+
contentType: "application/json",
96+
dataType: "json"
97+
});
98+
};
99+
100+
this.on_connection = function (on_connection) {
101+
if(that.isRegistered) return;
102+
that.isRegistered = true;
103+
if(on_connection) on_connection(that.ros);
104+
//
105+
setInterval(containerRefresh, 570000);
106+
containerRefresh();
107+
// Setup publisher that sends a dummy message in order to keep alive the socket connection
108+
{
109+
var interval = options.interval || 30000;
110+
// The topic dedicated to keep alive messages
111+
var keepAliveTopic = new ROSLIB.Topic({ ros : that.ros, name : '/keep_alive', messageType : 'std_msgs/Bool' });
112+
// A dummy message for the topic
113+
var keepAliveMsg = new ROSLIB.Message({ data : true });
114+
// Function that publishes the keep alive message
115+
var ping = function() { keepAliveTopic.publish(keepAliveMsg); };
116+
// Call ping at regular intervals.
117+
setInterval(ping, interval);
118+
};
119+
that.nodesRegistered = true;
120+
};
121+
};

0 commit comments

Comments
 (0)