forked from Freeboard/freeboard
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathros.js
218 lines (190 loc) · 6.85 KB
/
ros.js
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
(function()
{
freeboard.loadDatasourcePlugin({
"type_name" : "ros_sub",
"display_name": "ROS Subscriber",
"description" : "Subscribe to ROS topics through rosbridge",
// **external_scripts** : Any external scripts that should be loaded before the plugin instance is created.
"external_scripts" : [
"http://cdn.robotwebtools.org/EventEmitter2/current/eventemitter2.min.js",
"http://cdn.robotwebtools.org/roslibjs/current/roslib.min.js"
],
"settings" : [
{
"name" : "server",
"display_name" : "rosbridge Server",
"type" : "text",
"default_value": "localhost",
"description" : "Hostname of rosbridge Server",
"required" : true
},
{
"name" : "topic",
"display_name" : "Topic",
"type" : "text",
"default_value": "",
"description" : "ROS Topic to Subscribe",
"required" : true
},
{
"name" : "port",
"display_name" : "rosbridge Port",
"type" : "number",
"default_value": 9090,
"description" : "Port number of rosbridge server",
"required" : true
},
{
"name": "refresh",
"display_name": "Refresh Every",
"type": "number",
"suffix": "seconds",
"default_value": 5
}
],
// **newInstance(settings, newInstanceCallback, updateCallback)** (required) : A function that will be called when a new instance of this plugin is requested.
// * **settings** : A javascript object with the initial settings set by the user. The names of the properties in the object will correspond to the setting names defined above.
// * **newInstanceCallback** : A callback function that you'll call when the new instance of the plugin is ready. This function expects a single argument, which is the new instance of your plugin object.
// * **updateCallback** : A callback function that you'll call if and when your datasource has an update for freeboard to recalculate. This function expects a single parameter which is a javascript object with the new, updated data. You should hold on to this reference and call it when needed.
newInstance : function(settings, newInstanceCallback, updateCallback)
{
// myDatasourcePlugin is defined below.
newInstanceCallback(new rossubInstance(settings, updateCallback));
}
});
// ### Datasource Implementation
//
// -------------------
// Here we implement the actual datasource plugin. We pass in the settings and updateCallback.
var rossubInstance = function(settings, updateCallback)
{
var self = this;
var currentSettings = settings;
var updateTimer = null;
var rosbridge_url;
var connected = false;
var subscribed = false;
var ros;
var listener;
var data;
function connectRos()
{
if (connected) return;
rosbridge_url = 'ws://' + currentSettings.server + ':' + currentSettings.port;
console.log('[ros] Attempting to connect to ', rosbridge_url);
ros = new ROSLIB.Ros({
url : rosbridge_url
});
ros.on('connection', function() {
connected = true;
console.log('[ros] Connected to rosbridge server.');
});
ros.on('error', function(error) {
// TODO: Communicate error to the UI
connected = false;
console.error('[ros] Error connecting to rosbridge server: ', error);
});
ros.on('close', function() {
connected = false;
console.log('[ros] Connection to rosbridge server closed.');
});
console.log('[ros] Exiting connect()')
}
function disconnectRos()
{
if (connected)
{
console.log('[ros] Closing connection to ', rosbridge_url);
ros.close();
connected = false;
}
}
function subscribeRos()
{
console.log('[ros] Subscribing to ', currentSettings.topic);
listener = new ROSLIB.Topic({
ros : ros,
name : currentSettings.topic
// No message type is intentional
});
listener.subscribe(function(message) {
if (!subscribed)
{
console.log('[ros] Message received on ', listener.name);
subscribed = true;
}
data = message;
});
}
function unsubscribeRos()
{
if (subscribed)
{
console.log('[ros] Unsubscribing from', listener.name);
listener.unsubscribe();
}
}
function updateRefresh(refreshTime) {
if (updateTimer) {
clearInterval(updateTimer);
}
updateTimer = setInterval(function () {
self.updateNow();
}, refreshTime);
}
function getData()
{
if (connected)
{
updateCallback(data);
}
}
// **onSettingsChanged(newSettings)** (required) : A public function we must implement that will be called when a user makes a change to the settings.
self.onSettingsChanged = function(newSettings)
{
console.log("New settings.");
// Here we update our current settings with the variable that is passed in.
oldSettings = currentSettings;
currentSettings = newSettings;
if (
connected &&
(
newSettings.server !== oldSettings.server ||
newSettings.port !== oldSettings.port))
{
unsubscribeRos
disconnectRos();
connectRos();
subscribeRos();
}
else if (subscribed && newSettings.topic !== oldSettings.topic)
{
unsubscribeRos();
subscribeRos();
};
// if (subscribed)
// {
// unsubscribe();
// }
updateRefresh(currentSettings.refresh * 1000);
}
// **updateNow()** (required) : A public function we must implement that will be called when the user wants to manually refresh the datasource
self.updateNow = function()
{
// Most likely I'll just call getData() here.
getData();
}
// **onDispose()** (required) : A public function we must implement that will be called when this instance of this plugin is no longer needed. Do anything you need to cleanup after yourself here.
self.onDispose = function()
{
clearInterval(updateTimer);
updateTimer = null;
unsubscribeRos();
disconnectRos();
//conn.close();
}
connectRos();
updateRefresh(currentSettings.refresh * 1000);
subscribeRos();
}
}());