Files
apt-nl-map/static/Magic4/ros2djs/ros2d.js
2024-12-03 16:40:54 +08:00

2903 lines
87 KiB
JavaScript

var ROS2D = (function (exports, createjs, ROSLIB) {
'use strict';
function _interopNamespace(e) {
if (e && e.__esModule) return e;
var n = Object.create(null);
if (e) {
Object.keys(e).forEach(function (k) {
if (k !== 'default') {
var d = Object.getOwnPropertyDescriptor(e, k);
Object.defineProperty(n, k, d.get ? d : {
enumerable: true,
get: function () { return e[k]; }
});
}
});
}
n["default"] = e;
return Object.freeze(n);
}
var createjs__namespace = /*#__PURE__*/_interopNamespace(createjs);
var ROSLIB__namespace = /*#__PURE__*/_interopNamespace(ROSLIB);
// convert the given global Stage coordinates to ROS coordinates
createjs__namespace.Stage.prototype.globalToRos = function(x, y) {
var rosX = (x - this.x) / this.scaleX;
var rosY = (this.y - y) / this.scaleY;
return new ROSLIB__namespace.Vector3({
x : rosX,
y : rosY
});
};
// convert the given ROS coordinates to global Stage coordinates
createjs__namespace.Stage.prototype.rosToGlobal = function(pos) {
var x = pos.x * this.scaleX + this.x;
var y = pos.y * this.scaleY + this.y;
return {
x : x,
y : y
};
};
// convert a ROS quaternion to theta in degrees
createjs__namespace.Stage.prototype.rosQuaternionToGlobalTheta = function(orientation) {
// See https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles#Rotation_matrices
// here we use [x y z] = R * [1 0 0]
var q0 = orientation.w;
var q1 = orientation.x;
var q2 = orientation.y;
var q3 = orientation.z;
// Canvas rotation is clock wise and in degrees
return -Math.atan2(2 * (q0 * q3 + q1 * q2), 1 - 2 * (q2 * q2 + q3 * q3)) * 180.0 / Math.PI;
};
/**
* @fileOverview
* @author Russell Toris - rctoris@wpi.edu
*/
class ImageMap extends createjs__namespace.Bitmap {
/**
* An image map is a PNG image scaled to fit to the dimensions of a OccupancyGrid.
*
* @constructor
* @param options - object with following keys:
* * message - the occupancy grid map meta data message
* * image - the image URL to load
*/
constructor(options) {
options = options || {};
var message = options.message;
var image = options.image;
// create the bitmap
super(image);
// save the metadata we need
this.pose = new ROSLIB__namespace.Pose({
position : message.origin.position,
orientation : message.origin.orientation
});
// set the size
this.width = message.width;
this.height = message.height;
// change Y direction
this.y = -this.height * message.resolution;
// scale the image
this.scaleX = message.resolution;
this.scaleY = message.resolution;
this.width *= this.scaleX;
this.height *= this.scaleY;
// set the pose
this.x += this.pose.position.x;
this.y -= this.pose.position.y;
};
}
function getDefaultExportFromCjs (x) {
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x;
}
var eventemitter2 = {exports: {}};
/*!
* EventEmitter2
* https://github.com/hij1nx/EventEmitter2
*
* Copyright (c) 2013 hij1nx
* Licensed under the MIT license.
*/
eventemitter2.exports;
(function (module, exports) {
!function(undefined$1) {
var hasOwnProperty= Object.hasOwnProperty;
var isArray = Array.isArray ? Array.isArray : function _isArray(obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
var defaultMaxListeners = 10;
var nextTickSupported= typeof process=='object' && typeof process.nextTick=='function';
var symbolsSupported= typeof Symbol==='function';
var reflectSupported= typeof Reflect === 'object';
var setImmediateSupported= typeof setImmediate === 'function';
var _setImmediate= setImmediateSupported ? setImmediate : setTimeout;
var ownKeys= symbolsSupported? (reflectSupported && typeof Reflect.ownKeys==='function'? Reflect.ownKeys : function(obj){
var arr= Object.getOwnPropertyNames(obj);
arr.push.apply(arr, Object.getOwnPropertySymbols(obj));
return arr;
}) : Object.keys;
function init() {
this._events = {};
if (this._conf) {
configure.call(this, this._conf);
}
}
function configure(conf) {
if (conf) {
this._conf = conf;
conf.delimiter && (this.delimiter = conf.delimiter);
if(conf.maxListeners!==undefined$1){
this._maxListeners= conf.maxListeners;
}
conf.wildcard && (this.wildcard = conf.wildcard);
conf.newListener && (this._newListener = conf.newListener);
conf.removeListener && (this._removeListener = conf.removeListener);
conf.verboseMemoryLeak && (this.verboseMemoryLeak = conf.verboseMemoryLeak);
conf.ignoreErrors && (this.ignoreErrors = conf.ignoreErrors);
if (this.wildcard) {
this.listenerTree = {};
}
}
}
function logPossibleMemoryLeak(count, eventName) {
var errorMsg = '(node) warning: possible EventEmitter memory ' +
'leak detected. ' + count + ' listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.';
if(this.verboseMemoryLeak){
errorMsg += ' Event name: ' + eventName + '.';
}
if(typeof process !== 'undefined' && process.emitWarning){
var e = new Error(errorMsg);
e.name = 'MaxListenersExceededWarning';
e.emitter = this;
e.count = count;
process.emitWarning(e);
} else {
console.error(errorMsg);
if (console.trace){
console.trace();
}
}
}
var toArray = function (a, b, c) {
var n = arguments.length;
switch (n) {
case 0:
return [];
case 1:
return [a];
case 2:
return [a, b];
case 3:
return [a, b, c];
default:
var arr = new Array(n);
while (n--) {
arr[n] = arguments[n];
}
return arr;
}
};
function toObject(keys, values) {
var obj = {};
var key;
var len = keys.length;
var valuesCount = values ? value.length : 0;
for (var i = 0; i < len; i++) {
key = keys[i];
obj[key] = i < valuesCount ? values[i] : undefined$1;
}
return obj;
}
function TargetObserver(emitter, target, options) {
this._emitter = emitter;
this._target = target;
this._listeners = {};
this._listenersCount = 0;
var on, off;
if (options.on || options.off) {
on = options.on;
off = options.off;
}
if (target.addEventListener) {
on = target.addEventListener;
off = target.removeEventListener;
} else if (target.addListener) {
on = target.addListener;
off = target.removeListener;
} else if (target.on) {
on = target.on;
off = target.off;
}
if (!on && !off) {
throw Error('target does not implement any known event API');
}
if (typeof on !== 'function') {
throw TypeError('on method must be a function');
}
if (typeof off !== 'function') {
throw TypeError('off method must be a function');
}
this._on = on;
this._off = off;
var _observers= emitter._observers;
if(_observers){
_observers.push(this);
}else {
emitter._observers= [this];
}
}
Object.assign(TargetObserver.prototype, {
subscribe: function(event, localEvent, reducer){
var observer= this;
var target= this._target;
var emitter= this._emitter;
var listeners= this._listeners;
var handler= function(){
var args= toArray.apply(null, arguments);
var eventObj= {
data: args,
name: localEvent,
original: event
};
if(reducer){
var result= reducer.call(target, eventObj);
if(result!==false){
emitter.emit.apply(emitter, [eventObj.name].concat(args));
}
return;
}
emitter.emit.apply(emitter, [localEvent].concat(args));
};
if(listeners[event]){
throw Error('Event \'' + event + '\' is already listening');
}
this._listenersCount++;
if(emitter._newListener && emitter._removeListener && !observer._onNewListener){
this._onNewListener = function (_event) {
if (_event === localEvent && listeners[event] === null) {
listeners[event] = handler;
observer._on.call(target, event, handler);
}
};
emitter.on('newListener', this._onNewListener);
this._onRemoveListener= function(_event){
if(_event === localEvent && !emitter.hasListeners(_event) && listeners[event]){
listeners[event]= null;
observer._off.call(target, event, handler);
}
};
listeners[event]= null;
emitter.on('removeListener', this._onRemoveListener);
}else {
listeners[event]= handler;
observer._on.call(target, event, handler);
}
},
unsubscribe: function(event){
var observer= this;
var listeners= this._listeners;
var emitter= this._emitter;
var handler;
var events;
var off= this._off;
var target= this._target;
var i;
if(event && typeof event!=='string'){
throw TypeError('event must be a string');
}
function clearRefs(){
if(observer._onNewListener){
emitter.off('newListener', observer._onNewListener);
emitter.off('removeListener', observer._onRemoveListener);
observer._onNewListener= null;
observer._onRemoveListener= null;
}
var index= findTargetIndex.call(emitter, observer);
emitter._observers.splice(index, 1);
}
if(event){
handler= listeners[event];
if(!handler) return;
off.call(target, event, handler);
delete listeners[event];
if(!--this._listenersCount){
clearRefs();
}
}else {
events= ownKeys(listeners);
i= events.length;
while(i-->0){
event= events[i];
off.call(target, event, listeners[event]);
}
this._listeners= {};
this._listenersCount= 0;
clearRefs();
}
}
});
function resolveOptions(options, schema, reducers, allowUnknown) {
var computedOptions = Object.assign({}, schema);
if (!options) return computedOptions;
if (typeof options !== 'object') {
throw TypeError('options must be an object')
}
var keys = Object.keys(options);
var length = keys.length;
var option, value;
var reducer;
function reject(reason) {
throw Error('Invalid "' + option + '" option value' + (reason ? '. Reason: ' + reason : ''))
}
for (var i = 0; i < length; i++) {
option = keys[i];
if (!allowUnknown && !hasOwnProperty.call(schema, option)) {
throw Error('Unknown "' + option + '" option');
}
value = options[option];
if (value !== undefined$1) {
reducer = reducers[option];
computedOptions[option] = reducer ? reducer(value, reject) : value;
}
}
return computedOptions;
}
function constructorReducer(value, reject) {
if (typeof value !== 'function' || !value.hasOwnProperty('prototype')) {
reject('value must be a constructor');
}
return value;
}
function makeTypeReducer(types) {
var message= 'value must be type of ' + types.join('|');
var len= types.length;
var firstType= types[0];
var secondType= types[1];
if (len === 1) {
return function (v, reject) {
if (typeof v === firstType) {
return v;
}
reject(message);
}
}
if (len === 2) {
return function (v, reject) {
var kind= typeof v;
if (kind === firstType || kind === secondType) return v;
reject(message);
}
}
return function (v, reject) {
var kind = typeof v;
var i = len;
while (i-- > 0) {
if (kind === types[i]) return v;
}
reject(message);
}
}
var functionReducer= makeTypeReducer(['function']);
var objectFunctionReducer= makeTypeReducer(['object', 'function']);
function makeCancelablePromise(Promise, executor, options) {
var isCancelable;
var callbacks;
var timer= 0;
var subscriptionClosed;
var promise = new Promise(function (resolve, reject, onCancel) {
options= resolveOptions(options, {
timeout: 0,
overload: false
}, {
timeout: function(value, reject){
value*= 1;
if (typeof value !== 'number' || value < 0 || !Number.isFinite(value)) {
reject('timeout must be a positive number');
}
return value;
}
});
isCancelable = !options.overload && typeof Promise.prototype.cancel === 'function' && typeof onCancel === 'function';
function cleanup() {
if (callbacks) {
callbacks = null;
}
if (timer) {
clearTimeout(timer);
timer = 0;
}
}
var _resolve= function(value){
cleanup();
resolve(value);
};
var _reject= function(err){
cleanup();
reject(err);
};
if (isCancelable) {
executor(_resolve, _reject, onCancel);
} else {
callbacks = [function(reason){
_reject(reason || Error('canceled'));
}];
executor(_resolve, _reject, function (cb) {
if (subscriptionClosed) {
throw Error('Unable to subscribe on cancel event asynchronously')
}
if (typeof cb !== 'function') {
throw TypeError('onCancel callback must be a function');
}
callbacks.push(cb);
});
subscriptionClosed= true;
}
if (options.timeout > 0) {
timer= setTimeout(function(){
var reason= Error('timeout');
reason.code = 'ETIMEDOUT';
timer= 0;
promise.cancel(reason);
reject(reason);
}, options.timeout);
}
});
if (!isCancelable) {
promise.cancel = function (reason) {
if (!callbacks) {
return;
}
var length = callbacks.length;
for (var i = 1; i < length; i++) {
callbacks[i](reason);
}
// internal callback to reject the promise
callbacks[0](reason);
callbacks = null;
};
}
return promise;
}
function findTargetIndex(observer) {
var observers = this._observers;
if(!observers){
return -1;
}
var len = observers.length;
for (var i = 0; i < len; i++) {
if (observers[i]._target === observer) return i;
}
return -1;
}
// Attention, function return type now is array, always !
// It has zero elements if no any matches found and one or more
// elements (leafs) if there are matches
//
function searchListenerTree(handlers, type, tree, i, typeLength) {
if (!tree) {
return null;
}
if (i === 0) {
var kind = typeof type;
if (kind === 'string') {
var ns, n, l = 0, j = 0, delimiter = this.delimiter, dl = delimiter.length;
if ((n = type.indexOf(delimiter)) !== -1) {
ns = new Array(5);
do {
ns[l++] = type.slice(j, n);
j = n + dl;
} while ((n = type.indexOf(delimiter, j)) !== -1);
ns[l++] = type.slice(j);
type = ns;
typeLength = l;
} else {
type = [type];
typeLength = 1;
}
} else if (kind === 'object') {
typeLength = type.length;
} else {
type = [type];
typeLength = 1;
}
}
var listeners= null, branch, xTree, xxTree, isolatedBranch, endReached, currentType = type[i],
nextType = type[i + 1], branches, _listeners;
if (i === typeLength) {
//
// If at the end of the event(s) list and the tree has listeners
// invoke those listeners.
//
if(tree._listeners) {
if (typeof tree._listeners === 'function') {
handlers && handlers.push(tree._listeners);
listeners = [tree];
} else {
handlers && handlers.push.apply(handlers, tree._listeners);
listeners = [tree];
}
}
} else {
if (currentType === '*') {
//
// If the event emitted is '*' at this part
// or there is a concrete match at this patch
//
branches = ownKeys(tree);
n = branches.length;
while (n-- > 0) {
branch = branches[n];
if (branch !== '_listeners') {
_listeners = searchListenerTree(handlers, type, tree[branch], i + 1, typeLength);
if (_listeners) {
if (listeners) {
listeners.push.apply(listeners, _listeners);
} else {
listeners = _listeners;
}
}
}
}
return listeners;
} else if (currentType === '**') {
endReached = (i + 1 === typeLength || (i + 2 === typeLength && nextType === '*'));
if (endReached && tree._listeners) {
// The next element has a _listeners, add it to the handlers.
listeners = searchListenerTree(handlers, type, tree, typeLength, typeLength);
}
branches = ownKeys(tree);
n = branches.length;
while (n-- > 0) {
branch = branches[n];
if (branch !== '_listeners') {
if (branch === '*' || branch === '**') {
if (tree[branch]._listeners && !endReached) {
_listeners = searchListenerTree(handlers, type, tree[branch], typeLength, typeLength);
if (_listeners) {
if (listeners) {
listeners.push.apply(listeners, _listeners);
} else {
listeners = _listeners;
}
}
}
_listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength);
} else if (branch === nextType) {
_listeners = searchListenerTree(handlers, type, tree[branch], i + 2, typeLength);
} else {
// No match on this one, shift into the tree but not in the type array.
_listeners = searchListenerTree(handlers, type, tree[branch], i, typeLength);
}
if (_listeners) {
if (listeners) {
listeners.push.apply(listeners, _listeners);
} else {
listeners = _listeners;
}
}
}
}
return listeners;
} else if (tree[currentType]) {
listeners = searchListenerTree(handlers, type, tree[currentType], i + 1, typeLength);
}
}
xTree = tree['*'];
if (xTree) {
//
// If the listener tree will allow any match for this part,
// then recursively explore all branches of the tree
//
searchListenerTree(handlers, type, xTree, i + 1, typeLength);
}
xxTree = tree['**'];
if (xxTree) {
if (i < typeLength) {
if (xxTree._listeners) {
// If we have a listener on a '**', it will catch all, so add its handler.
searchListenerTree(handlers, type, xxTree, typeLength, typeLength);
}
// Build arrays of matching next branches and others.
branches= ownKeys(xxTree);
n= branches.length;
while(n-->0){
branch= branches[n];
if (branch !== '_listeners') {
if (branch === nextType) {
// We know the next element will match, so jump twice.
searchListenerTree(handlers, type, xxTree[branch], i + 2, typeLength);
} else if (branch === currentType) {
// Current node matches, move into the tree.
searchListenerTree(handlers, type, xxTree[branch], i + 1, typeLength);
} else {
isolatedBranch = {};
isolatedBranch[branch] = xxTree[branch];
searchListenerTree(handlers, type, {'**': isolatedBranch}, i + 1, typeLength);
}
}
}
} else if (xxTree._listeners) {
// We have reached the end and still on a '**'
searchListenerTree(handlers, type, xxTree, typeLength, typeLength);
} else if (xxTree['*'] && xxTree['*']._listeners) {
searchListenerTree(handlers, type, xxTree['*'], typeLength, typeLength);
}
}
return listeners;
}
function growListenerTree(type, listener, prepend) {
var len = 0, j = 0, i, delimiter = this.delimiter, dl= delimiter.length, ns;
if(typeof type==='string') {
if ((i = type.indexOf(delimiter)) !== -1) {
ns = new Array(5);
do {
ns[len++] = type.slice(j, i);
j = i + dl;
} while ((i = type.indexOf(delimiter, j)) !== -1);
ns[len++] = type.slice(j);
}else {
ns= [type];
len= 1;
}
}else {
ns= type;
len= type.length;
}
//
// Looks for two consecutive '**', if so, don't add the event at all.
//
if (len > 1) {
for (i = 0; i + 1 < len; i++) {
if (ns[i] === '**' && ns[i + 1] === '**') {
return;
}
}
}
var tree = this.listenerTree, name;
for (i = 0; i < len; i++) {
name = ns[i];
tree = tree[name] || (tree[name] = {});
if (i === len - 1) {
if (!tree._listeners) {
tree._listeners = listener;
} else {
if (typeof tree._listeners === 'function') {
tree._listeners = [tree._listeners];
}
if (prepend) {
tree._listeners.unshift(listener);
} else {
tree._listeners.push(listener);
}
if (
!tree._listeners.warned &&
this._maxListeners > 0 &&
tree._listeners.length > this._maxListeners
) {
tree._listeners.warned = true;
logPossibleMemoryLeak.call(this, tree._listeners.length, name);
}
}
return true;
}
}
return true;
}
function collectTreeEvents(tree, events, root, asArray){
var branches= ownKeys(tree);
var i= branches.length;
var branch, branchName, path;
var hasListeners= tree['_listeners'];
var isArrayPath;
while(i-->0){
branchName= branches[i];
branch= tree[branchName];
if(branchName==='_listeners'){
path= root;
}else {
path = root ? root.concat(branchName) : [branchName];
}
isArrayPath= asArray || typeof branchName==='symbol';
hasListeners && events.push(isArrayPath? path : path.join(this.delimiter));
if(typeof branch==='object'){
collectTreeEvents.call(this, branch, events, path, isArrayPath);
}
}
return events;
}
function recursivelyGarbageCollect(root) {
var keys = ownKeys(root);
var i= keys.length;
var obj, key, flag;
while(i-->0){
key = keys[i];
obj = root[key];
if(obj){
flag= true;
if(key !== '_listeners' && !recursivelyGarbageCollect(obj)){
delete root[key];
}
}
}
return flag;
}
function Listener(emitter, event, listener){
this.emitter= emitter;
this.event= event;
this.listener= listener;
}
Listener.prototype.off= function(){
this.emitter.off(this.event, this.listener);
return this;
};
function setupListener(event, listener, options){
if (options === true) {
promisify = true;
} else if (options === false) {
async = true;
} else {
if (!options || typeof options !== 'object') {
throw TypeError('options should be an object or true');
}
var async = options.async;
var promisify = options.promisify;
var nextTick = options.nextTick;
var objectify = options.objectify;
}
if (async || nextTick || promisify) {
var _listener = listener;
var _origin = listener._origin || listener;
if (nextTick && !nextTickSupported) {
throw Error('process.nextTick is not supported');
}
if (promisify === undefined$1) {
promisify = listener.constructor.name === 'AsyncFunction';
}
listener = function () {
var args = arguments;
var context = this;
var event = this.event;
return promisify ? (nextTick ? Promise.resolve() : new Promise(function (resolve) {
_setImmediate(resolve);
}).then(function () {
context.event = event;
return _listener.apply(context, args)
})) : (nextTick ? process.nextTick : _setImmediate)(function () {
context.event = event;
_listener.apply(context, args);
});
};
listener._async = true;
listener._origin = _origin;
}
return [listener, objectify? new Listener(this, event, listener): this];
}
function EventEmitter(conf) {
this._events = {};
this._newListener = false;
this._removeListener = false;
this.verboseMemoryLeak = false;
configure.call(this, conf);
}
EventEmitter.EventEmitter2 = EventEmitter; // backwards compatibility for exporting EventEmitter property
EventEmitter.prototype.listenTo= function(target, events, options){
if(typeof target!=='object'){
throw TypeError('target musts be an object');
}
var emitter= this;
options = resolveOptions(options, {
on: undefined$1,
off: undefined$1,
reducers: undefined$1
}, {
on: functionReducer,
off: functionReducer,
reducers: objectFunctionReducer
});
function listen(events){
if(typeof events!=='object'){
throw TypeError('events must be an object');
}
var reducers= options.reducers;
var index= findTargetIndex.call(emitter, target);
var observer;
if(index===-1){
observer= new TargetObserver(emitter, target, options);
}else {
observer= emitter._observers[index];
}
var keys= ownKeys(events);
var len= keys.length;
var event;
var isSingleReducer= typeof reducers==='function';
for(var i=0; i<len; i++){
event= keys[i];
observer.subscribe(
event,
events[event] || event,
isSingleReducer ? reducers : reducers && reducers[event]
);
}
}
isArray(events)?
listen(toObject(events)) :
(typeof events==='string'? listen(toObject(events.split(/\s+/))): listen(events));
return this;
};
EventEmitter.prototype.stopListeningTo = function (target, event) {
var observers = this._observers;
if(!observers){
return false;
}
var i = observers.length;
var observer;
var matched= false;
if(target && typeof target!=='object'){
throw TypeError('target should be an object');
}
while (i-- > 0) {
observer = observers[i];
if (!target || observer._target === target) {
observer.unsubscribe(event);
matched= true;
}
}
return matched;
};
// By default EventEmitters will print a warning if more than
// 10 listeners are added to it. This is a useful default which
// helps finding memory leaks.
//
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.delimiter = '.';
EventEmitter.prototype.setMaxListeners = function(n) {
if (n !== undefined$1) {
this._maxListeners = n;
if (!this._conf) this._conf = {};
this._conf.maxListeners = n;
}
};
EventEmitter.prototype.getMaxListeners = function() {
return this._maxListeners;
};
EventEmitter.prototype.event = '';
EventEmitter.prototype.once = function(event, fn, options) {
return this._once(event, fn, false, options);
};
EventEmitter.prototype.prependOnceListener = function(event, fn, options) {
return this._once(event, fn, true, options);
};
EventEmitter.prototype._once = function(event, fn, prepend, options) {
return this._many(event, 1, fn, prepend, options);
};
EventEmitter.prototype.many = function(event, ttl, fn, options) {
return this._many(event, ttl, fn, false, options);
};
EventEmitter.prototype.prependMany = function(event, ttl, fn, options) {
return this._many(event, ttl, fn, true, options);
};
EventEmitter.prototype._many = function(event, ttl, fn, prepend, options) {
var self = this;
if (typeof fn !== 'function') {
throw new Error('many only accepts instances of Function');
}
function listener() {
if (--ttl === 0) {
self.off(event, listener);
}
return fn.apply(this, arguments);
}
listener._origin = fn;
return this._on(event, listener, prepend, options);
};
EventEmitter.prototype.emit = function() {
if (!this._events && !this._all) {
return false;
}
this._events || init.call(this);
var type = arguments[0], ns, wildcard= this.wildcard;
var args,l,i,j, containsSymbol;
if (type === 'newListener' && !this._newListener) {
if (!this._events.newListener) {
return false;
}
}
if (wildcard) {
ns= type;
if(type!=='newListener' && type!=='removeListener'){
if (typeof type === 'object') {
l = type.length;
if (symbolsSupported) {
for (i = 0; i < l; i++) {
if (typeof type[i] === 'symbol') {
containsSymbol = true;
break;
}
}
}
if (!containsSymbol) {
type = type.join(this.delimiter);
}
}
}
}
var al = arguments.length;
var handler;
if (this._all && this._all.length) {
handler = this._all.slice();
for (i = 0, l = handler.length; i < l; i++) {
this.event = type;
switch (al) {
case 1:
handler[i].call(this, type);
break;
case 2:
handler[i].call(this, type, arguments[1]);
break;
case 3:
handler[i].call(this, type, arguments[1], arguments[2]);
break;
default:
handler[i].apply(this, arguments);
}
}
}
if (wildcard) {
handler = [];
searchListenerTree.call(this, handler, ns, this.listenerTree, 0, l);
} else {
handler = this._events[type];
if (typeof handler === 'function') {
this.event = type;
switch (al) {
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
default:
args = new Array(al - 1);
for (j = 1; j < al; j++) args[j - 1] = arguments[j];
handler.apply(this, args);
}
return true;
} else if (handler) {
// need to make copy of handlers because list can change in the middle
// of emit call
handler = handler.slice();
}
}
if (handler && handler.length) {
if (al > 3) {
args = new Array(al - 1);
for (j = 1; j < al; j++) args[j - 1] = arguments[j];
}
for (i = 0, l = handler.length; i < l; i++) {
this.event = type;
switch (al) {
case 1:
handler[i].call(this);
break;
case 2:
handler[i].call(this, arguments[1]);
break;
case 3:
handler[i].call(this, arguments[1], arguments[2]);
break;
default:
handler[i].apply(this, args);
}
}
return true;
} else if (!this.ignoreErrors && !this._all && type === 'error') {
if (arguments[1] instanceof Error) {
throw arguments[1]; // Unhandled 'error' event
} else {
throw new Error("Uncaught, unspecified 'error' event.");
}
}
return !!this._all;
};
EventEmitter.prototype.emitAsync = function() {
if (!this._events && !this._all) {
return false;
}
this._events || init.call(this);
var type = arguments[0], wildcard= this.wildcard, ns, containsSymbol;
var args,l,i,j;
if (type === 'newListener' && !this._newListener) {
if (!this._events.newListener) { return Promise.resolve([false]); }
}
if (wildcard) {
ns= type;
if(type!=='newListener' && type!=='removeListener'){
if (typeof type === 'object') {
l = type.length;
if (symbolsSupported) {
for (i = 0; i < l; i++) {
if (typeof type[i] === 'symbol') {
containsSymbol = true;
break;
}
}
}
if (!containsSymbol) {
type = type.join(this.delimiter);
}
}
}
}
var promises= [];
var al = arguments.length;
var handler;
if (this._all) {
for (i = 0, l = this._all.length; i < l; i++) {
this.event = type;
switch (al) {
case 1:
promises.push(this._all[i].call(this, type));
break;
case 2:
promises.push(this._all[i].call(this, type, arguments[1]));
break;
case 3:
promises.push(this._all[i].call(this, type, arguments[1], arguments[2]));
break;
default:
promises.push(this._all[i].apply(this, arguments));
}
}
}
if (wildcard) {
handler = [];
searchListenerTree.call(this, handler, ns, this.listenerTree, 0);
} else {
handler = this._events[type];
}
if (typeof handler === 'function') {
this.event = type;
switch (al) {
case 1:
promises.push(handler.call(this));
break;
case 2:
promises.push(handler.call(this, arguments[1]));
break;
case 3:
promises.push(handler.call(this, arguments[1], arguments[2]));
break;
default:
args = new Array(al - 1);
for (j = 1; j < al; j++) args[j - 1] = arguments[j];
promises.push(handler.apply(this, args));
}
} else if (handler && handler.length) {
handler = handler.slice();
if (al > 3) {
args = new Array(al - 1);
for (j = 1; j < al; j++) args[j - 1] = arguments[j];
}
for (i = 0, l = handler.length; i < l; i++) {
this.event = type;
switch (al) {
case 1:
promises.push(handler[i].call(this));
break;
case 2:
promises.push(handler[i].call(this, arguments[1]));
break;
case 3:
promises.push(handler[i].call(this, arguments[1], arguments[2]));
break;
default:
promises.push(handler[i].apply(this, args));
}
}
} else if (!this.ignoreErrors && !this._all && type === 'error') {
if (arguments[1] instanceof Error) {
return Promise.reject(arguments[1]); // Unhandled 'error' event
} else {
return Promise.reject("Uncaught, unspecified 'error' event.");
}
}
return Promise.all(promises);
};
EventEmitter.prototype.on = function(type, listener, options) {
return this._on(type, listener, false, options);
};
EventEmitter.prototype.prependListener = function(type, listener, options) {
return this._on(type, listener, true, options);
};
EventEmitter.prototype.onAny = function(fn) {
return this._onAny(fn, false);
};
EventEmitter.prototype.prependAny = function(fn) {
return this._onAny(fn, true);
};
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
EventEmitter.prototype._onAny = function(fn, prepend){
if (typeof fn !== 'function') {
throw new Error('onAny only accepts instances of Function');
}
if (!this._all) {
this._all = [];
}
// Add the function to the event listener collection.
if(prepend){
this._all.unshift(fn);
}else {
this._all.push(fn);
}
return this;
};
EventEmitter.prototype._on = function(type, listener, prepend, options) {
if (typeof type === 'function') {
this._onAny(type, listener);
return this;
}
if (typeof listener !== 'function') {
throw new Error('on only accepts instances of Function');
}
this._events || init.call(this);
var returnValue= this, temp;
if (options !== undefined$1) {
temp = setupListener.call(this, type, listener, options);
listener = temp[0];
returnValue = temp[1];
}
// To avoid recursion in the case that type == "newListeners"! Before
// adding it to the listeners, first emit "newListeners".
if (this._newListener) {
this.emit('newListener', type, listener);
}
if (this.wildcard) {
growListenerTree.call(this, type, listener, prepend);
return returnValue;
}
if (!this._events[type]) {
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
} else {
if (typeof this._events[type] === 'function') {
// Change to array.
this._events[type] = [this._events[type]];
}
// If we've already got an array, just add
if(prepend){
this._events[type].unshift(listener);
}else {
this._events[type].push(listener);
}
// Check for listener leak
if (
!this._events[type].warned &&
this._maxListeners > 0 &&
this._events[type].length > this._maxListeners
) {
this._events[type].warned = true;
logPossibleMemoryLeak.call(this, this._events[type].length, type);
}
}
return returnValue;
};
EventEmitter.prototype.off = function(type, listener) {
if (typeof listener !== 'function') {
throw new Error('removeListener only takes instances of Function');
}
var handlers,leafs=[];
if(this.wildcard) {
var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
leafs = searchListenerTree.call(this, null, ns, this.listenerTree, 0);
if(!leafs) return this;
} else {
// does not use listeners(), so no side effect of creating _events[type]
if (!this._events[type]) return this;
handlers = this._events[type];
leafs.push({_listeners:handlers});
}
for (var iLeaf=0; iLeaf<leafs.length; iLeaf++) {
var leaf = leafs[iLeaf];
handlers = leaf._listeners;
if (isArray(handlers)) {
var position = -1;
for (var i = 0, length = handlers.length; i < length; i++) {
if (handlers[i] === listener ||
(handlers[i].listener && handlers[i].listener === listener) ||
(handlers[i]._origin && handlers[i]._origin === listener)) {
position = i;
break;
}
}
if (position < 0) {
continue;
}
if(this.wildcard) {
leaf._listeners.splice(position, 1);
}
else {
this._events[type].splice(position, 1);
}
if (handlers.length === 0) {
if(this.wildcard) {
delete leaf._listeners;
}
else {
delete this._events[type];
}
}
if (this._removeListener)
this.emit("removeListener", type, listener);
return this;
}
else if (handlers === listener ||
(handlers.listener && handlers.listener === listener) ||
(handlers._origin && handlers._origin === listener)) {
if(this.wildcard) {
delete leaf._listeners;
}
else {
delete this._events[type];
}
if (this._removeListener)
this.emit("removeListener", type, listener);
}
}
this.listenerTree && recursivelyGarbageCollect(this.listenerTree);
return this;
};
EventEmitter.prototype.offAny = function(fn) {
var i = 0, l = 0, fns;
if (fn && this._all && this._all.length > 0) {
fns = this._all;
for(i = 0, l = fns.length; i < l; i++) {
if(fn === fns[i]) {
fns.splice(i, 1);
if (this._removeListener)
this.emit("removeListenerAny", fn);
return this;
}
}
} else {
fns = this._all;
if (this._removeListener) {
for(i = 0, l = fns.length; i < l; i++)
this.emit("removeListenerAny", fns[i]);
}
this._all = [];
}
return this;
};
EventEmitter.prototype.removeListener = EventEmitter.prototype.off;
EventEmitter.prototype.removeAllListeners = function (type) {
if (type === undefined$1) {
!this._events || init.call(this);
return this;
}
if (this.wildcard) {
var leafs = searchListenerTree.call(this, null, type, this.listenerTree, 0), leaf, i;
if (!leafs) return this;
for (i = 0; i < leafs.length; i++) {
leaf = leafs[i];
leaf._listeners = null;
}
this.listenerTree && recursivelyGarbageCollect(this.listenerTree);
} else if (this._events) {
this._events[type] = null;
}
return this;
};
EventEmitter.prototype.listeners = function (type) {
var _events = this._events;
var keys, listeners, allListeners;
var i;
var listenerTree;
if (type === undefined$1) {
if (this.wildcard) {
throw Error('event name required for wildcard emitter');
}
if (!_events) {
return [];
}
keys = ownKeys(_events);
i = keys.length;
allListeners = [];
while (i-- > 0) {
listeners = _events[keys[i]];
if (typeof listeners === 'function') {
allListeners.push(listeners);
} else {
allListeners.push.apply(allListeners, listeners);
}
}
return allListeners;
} else {
if (this.wildcard) {
listenerTree= this.listenerTree;
if(!listenerTree) return [];
var handlers = [];
var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
searchListenerTree.call(this, handlers, ns, listenerTree, 0);
return handlers;
}
if (!_events) {
return [];
}
listeners = _events[type];
if (!listeners) {
return [];
}
return typeof listeners === 'function' ? [listeners] : listeners;
}
};
EventEmitter.prototype.eventNames = function(nsAsArray){
var _events= this._events;
return this.wildcard? collectTreeEvents.call(this, this.listenerTree, [], null, nsAsArray) : (_events? ownKeys(_events) : []);
};
EventEmitter.prototype.listenerCount = function(type) {
return this.listeners(type).length;
};
EventEmitter.prototype.hasListeners = function (type) {
if (this.wildcard) {
var handlers = [];
var ns = typeof type === 'string' ? type.split(this.delimiter) : type.slice();
searchListenerTree.call(this, handlers, ns, this.listenerTree, 0);
return handlers.length > 0;
}
var _events = this._events;
var _all = this._all;
return !!(_all && _all.length || _events && (type === undefined$1 ? ownKeys(_events).length : _events[type]));
};
EventEmitter.prototype.listenersAny = function() {
if(this._all) {
return this._all;
}
else {
return [];
}
};
EventEmitter.prototype.waitFor = function (event, options) {
var self = this;
var type = typeof options;
if (type === 'number') {
options = {timeout: options};
} else if (type === 'function') {
options = {filter: options};
}
options= resolveOptions(options, {
timeout: 0,
filter: undefined$1,
handleError: false,
Promise: Promise,
overload: false
}, {
filter: functionReducer,
Promise: constructorReducer
});
return makeCancelablePromise(options.Promise, function (resolve, reject, onCancel) {
function listener() {
var filter= options.filter;
if (filter && !filter.apply(self, arguments)) {
return;
}
self.off(event, listener);
if (options.handleError) {
var err = arguments[0];
err ? reject(err) : resolve(toArray.apply(null, arguments).slice(1));
} else {
resolve(toArray.apply(null, arguments));
}
}
onCancel(function(){
self.off(event, listener);
});
self._on(event, listener, false);
}, {
timeout: options.timeout,
overload: options.overload
})
};
function once(emitter, name, options) {
options= resolveOptions(options, {
Promise: Promise,
timeout: 0,
overload: false
}, {
Promise: constructorReducer
});
var _Promise= options.Promise;
return makeCancelablePromise(_Promise, function(resolve, reject, onCancel){
var handler;
if (typeof emitter.addEventListener === 'function') {
handler= function () {
resolve(toArray.apply(null, arguments));
};
onCancel(function(){
emitter.removeEventListener(name, handler);
});
emitter.addEventListener(
name,
handler,
{once: true}
);
return;
}
var eventListener = function(){
errorListener && emitter.removeListener('error', errorListener);
resolve(toArray.apply(null, arguments));
};
var errorListener;
if (name !== 'error') {
errorListener = function (err){
emitter.removeListener(name, eventListener);
reject(err);
};
emitter.once('error', errorListener);
}
onCancel(function(){
errorListener && emitter.removeListener('error', errorListener);
emitter.removeListener(name, eventListener);
});
emitter.once(name, eventListener);
}, {
timeout: options.timeout,
overload: options.overload
});
}
var prototype= EventEmitter.prototype;
Object.defineProperties(EventEmitter, {
defaultMaxListeners: {
get: function () {
return prototype._maxListeners;
},
set: function (n) {
if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) {
throw TypeError('n must be a non-negative number')
}
prototype._maxListeners = n;
},
enumerable: true
},
once: {
value: once,
writable: true,
configurable: true
}
});
Object.defineProperties(prototype, {
_maxListeners: {
value: defaultMaxListeners,
writable: true,
configurable: true
},
_observers: {value: null, writable: true, configurable: true}
});
if (typeof undefined$1 === 'function' && undefined$1.amd) {
// AMD. Register as an anonymous module.
undefined$1(function() {
return EventEmitter;
});
} else {
// CommonJS
module.exports = EventEmitter;
}
}();
} (eventemitter2, eventemitter2.exports));
var eventemitter2Exports = eventemitter2.exports;
var EventEmitter2 = /*@__PURE__*/getDefaultExportFromCjs(eventemitter2Exports);
/**
* @fileOverview
* @author Russell Toris - rctoris@wpi.edu
*/
class ImageMapClient extends EventEmitter2 {
/**
* A image map is a PNG image scaled to fit to the dimensions of a OccupancyGrid.
*
* Emits the following events:
* * 'change' - there was an update or change in the map
*
* @constructor
* @param options - object with following keys:
* * ros - the ROSLIB.Ros connection handle
* * topic (optional) - the map meta data topic to listen to
* * image - the image URL to load
* * rootObject (optional) - the root object to add this marker to
*/
constructor(options) {
super();
options = options || {};
var ros = options.ros;
var topic = options.topic || '/map_metadata';
this.image = options.image;
this.rootObject = options.rootObject || new createjs__namespace.Container();
// create an empty shape to start with
this.currentImage = new createjs__namespace.Shape();
// subscribe to the topic
var rosTopic = new ROSLIB__namespace.Topic({
ros : ros,
name : topic,
messageType : 'nav_msgs/MapMetaData'
});
rosTopic.subscribe(function(message) {
// we only need this once
rosTopic.unsubscribe();
// create the image
this.currentImage = new ImageMap({
message : message,
image : this.image
});
this.rootObject.addChild(this.currentImage);
this.emit('change');
}.bind(this));
};
}
/**
* @fileOverview
* @author Russell Toris - rctoris@wpi.edu
*/
class OccupancyGrid extends createjs__namespace.Bitmap {
/**
* An OccupancyGrid can convert a ROS occupancy grid message into a createjs Bitmap object.
*
* @constructor
* @param options - object with following keys:
* * message - the occupancy grid message
*/
constructor(options) {
options = options || {};
var message = options.message;
// internal drawing canvas
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
// set the size
canvas.width = message.info.width;
canvas.height = message.info.height;
var imageData = context.createImageData(canvas.width, canvas.height);
for ( var row = 0; row < canvas.height; row++) {
for ( var col = 0; col < canvas.width; col++) {
// determine the index into the map data
var mapI = col + ((canvas.height - row - 1) * canvas.width);
// determine the value
var data = message.data[mapI];
var val;
if (data === 100) {
val = 0;
} else if (data === 0) {
val = 255;
} else {
val = 127;
}
// determine the index into the image data array
var i = (col + (row * canvas.width)) * 4;
// r
imageData.data[i] = val;
// g
imageData.data[++i] = val;
// b
imageData.data[++i] = val;
// a
imageData.data[++i] = 255;
}
}
context.putImageData(imageData, 0, 0);
// create the bitmap
super(canvas);
this.width = canvas.width;
this.height = canvas.height;
// save the metadata we need
this.pose = new ROSLIB__namespace.Pose({
position : message.info.origin.position,
orientation : message.info.origin.orientation
});
// change Y direction
this.y = -this.height * message.info.resolution;
// scale the image
this.scaleX = message.info.resolution;
this.scaleY = message.info.resolution;
this.width *= this.scaleX;
this.height *= this.scaleY;
// set the pose
this.x += this.pose.position.x;
this.y -= this.pose.position.y;
};
}
/**
* @fileOverview
* @author Raffaello Bonghi - raffaello.bonghi@officinerobotiche.it
*/
class Grid extends createjs__namespace.Shape {
/**
* A Grid object draw in map.
*
* @constructor
* @param options - object with following keys:
* * size (optional) - the size of the grid
* * cellSize (optional) - the cell size of map
* * lineWidth (optional) - the width of the lines in the grid
*/
constructor(options) {
options = options || {};
var size = options.size || 10;
var cellSize = options.cellSize || 0.1;
var lineWidth = options.lineWidth || 0.001;
// draw the arrow
var graphics = new createjs__namespace.Graphics();
// line width
graphics.setStrokeStyle(lineWidth*5);
graphics.beginStroke(createjs__namespace.Graphics.getRGB(0, 0, 0));
graphics.beginFill(createjs__namespace.Graphics.getRGB(255, 0, 0));
graphics.moveTo(-size*cellSize, 0);
graphics.lineTo(size*cellSize, 0);
graphics.moveTo(0, -size*cellSize);
graphics.lineTo(0, size*cellSize);
graphics.endFill();
graphics.endStroke();
graphics.setStrokeStyle(lineWidth);
graphics.beginStroke(createjs__namespace.Graphics.getRGB(0, 0, 0));
graphics.beginFill(createjs__namespace.Graphics.getRGB(255, 0, 0));
for (var i = -size; i <= size; i++) {
graphics.moveTo(-size*cellSize, i * cellSize);
graphics.lineTo(size*cellSize, i * cellSize);
graphics.moveTo(i * cellSize, -size*cellSize);
graphics.lineTo(i * cellSize, size*cellSize);
}
graphics.endFill();
graphics.endStroke();
// create the shape
super(graphics);
};
}
/**
* @fileOverview
* @author Russell Toris - rctoris@wpi.edu
*/
class OccupancyGridClient extends EventEmitter2 {
/**
* A map that listens to a given occupancy grid topic.
*
* Emits the following events:
* * 'change' - there was an update or change in the map
*
* @constructor
* @param options - object with following keys:
* * ros - the ROSLIB.Ros connection handle
* * topic (optional) - the map topic to listen to
* * rootObject (optional) - the root object to add this marker to
* * continuous (optional) - if the map should be continuously loaded (e.g., for SLAM)
*/
constructor(options) {
super();
var that = this;
options = options || {};
var ros = options.ros;
var topic = options.topic || '/map';
this.continuous = options.continuous;
this.rootObject = options.rootObject || new createjs__namespace.Container();
// current grid that is displayed
// create an empty shape to start with, so that the order remains correct.
this.currentGrid = new createjs__namespace.Shape();
this.rootObject.addChild(this.currentGrid);
// work-around for a bug in easeljs -- needs a second object to render correctly
this.rootObject.addChild(new Grid({size:1}));
// subscribe to the topic
var rosTopic = new ROSLIB__namespace.Topic({
ros : ros,
name : topic,
messageType : 'nav_msgs/OccupancyGrid',
compression : 'png'
});
rosTopic.subscribe(function(message) {
// check for an old map
var index = null;
if (that.currentGrid) {
index = that.rootObject.getChildIndex(that.currentGrid);
that.rootObject.removeChild(that.currentGrid);
}
that.currentGrid = new OccupancyGrid({
message : message
});
if (index !== null) {
that.rootObject.addChildAt(that.currentGrid, index);
}
else {
that.rootObject.addChild(that.currentGrid);
}
that.emit('change');
// check if we should unsubscribe
if (!that.continuous) {
rosTopic.unsubscribe();
}
});
};
}
/**
* @fileOverview
* @author Jihoon Lee- jihoonlee.in@gmail.com
* @author Russell Toris - rctoris@wpi.edu
*/
class OccupancyGridSrvClient extends EventEmitter2 {
/**
* A static map that receives from map_server.
*
* Emits the following events:
* * 'change' - there was an update or change in the map
*
* @constructor
* @param options - object with following keys:
* * ros - the ROSLIB.Ros connection handle
* * service (optional) - the map topic to listen to, like '/static_map'
* * rootObject (optional) - the root object to add this marker to
*/
constructor(options) {
super();
var that = this;
options = options || {};
var ros = options.ros;
var service = options.service || '/static_map';
this.rootObject = options.rootObject || new createjs__namespace.Container();
// current grid that is displayed
this.currentGrid = null;
// Setting up to the service
var rosService = new ROSLIB__namespace.Service({
ros : ros,
name : service,
serviceType : 'nav_msgs/GetMap',
compression : 'png'
});
rosService.callService(new ROSLIB__namespace.ServiceRequest(),function(response) {
// check for an old map
if (that.currentGrid) {
that.rootObject.removeChild(that.currentGrid);
}
that.currentGrid = new OccupancyGrid({
message : response.map
});
that.rootObject.addChild(that.currentGrid);
that.emit('change', that.currentGrid);
});
};
}
/**
* @fileOverview
* @author Bart van Vliet - bart@dobots.nl
*/
class ArrowShape extends createjs__namespace.Shape {
/**
* An arrow with line and triangular head, based on the navigation arrow.
* Aims to the left at 0 rotation, as would be expected.
*
* @constructor
* @param {Object} options
* @param {Int} [options.size] - The size of the marker
* @param {Int} [options.strokeSize] - The size of the outline
* @param {String} [options.strokeColor] - The createjs color for the stroke
* @param {String} [options.fillColor] - The createjs color for the fill
* @param {Bool} [options.pulse] - If the marker should "pulse" over time
*/
constructor(options) {
var that = this;
options = options || {};
var size = options.size || 10;
var strokeSize = options.strokeSize || 3;
var strokeColor = options.strokeColor || createjs__namespace.Graphics.getRGB(0, 0, 0);
var fillColor = options.fillColor || createjs__namespace.Graphics.getRGB(255, 0, 0);
var pulse = options.pulse;
// draw the arrow
var graphics = new createjs__namespace.Graphics();
var headLen = size / 3.0;
var headWidth = headLen * 2.0 / 3.0;
graphics.setStrokeStyle(strokeSize);
graphics.beginStroke(strokeColor);
graphics.moveTo(0, 0);
graphics.lineTo(size-headLen, 0);
graphics.beginFill(fillColor);
graphics.moveTo(size, 0);
graphics.lineTo(size-headLen, headWidth / 2.0);
graphics.lineTo(size-headLen, -headWidth / 2.0);
graphics.closePath();
graphics.endFill();
graphics.endStroke();
// create the shape
super(graphics);
// check if we are pulsing
if (pulse) {
// have the model "pulse"
var growCount = 0;
var growing = true;
createjs__namespace.Ticker.addEventListener('tick', function() {
if (growing) {
that.scaleX *= 1.035;
that.scaleY *= 1.035;
growing = (++growCount < 10);
} else {
that.scaleX /= 1.035;
that.scaleY /= 1.035;
growing = (--growCount < 0);
}
});
}
};
}
/**
* @fileOverview
* @author Russell Toris - rctoris@wpi.edu
*/
class NavigationArrow extends createjs__namespace.Shape {
/**
* A navigation arrow is a directed triangle that can be used to display orientation.
*
* @constructor
* @param options - object with following keys:
* * size (optional) - the size of the marker
* * strokeSize (optional) - the size of the outline
* * strokeColor (optional) - the createjs color for the stroke
* * fillColor (optional) - the createjs color for the fill
* * pulse (optional) - if the marker should "pulse" over time
*/
constructor(options) {
var that = this;
options = options || {};
var size = options.size || 10;
var strokeSize = options.strokeSize || 3;
var strokeColor = options.strokeColor || createjs__namespace.Graphics.getRGB(0, 0, 0);
var fillColor = options.fillColor || createjs__namespace.Graphics.getRGB(255, 0, 0);
var pulse = options.pulse;
// draw the arrow
var graphics = new createjs__namespace.Graphics();
// line width
graphics.setStrokeStyle(strokeSize);
graphics.moveTo(-size / 2.0, -size / 2.0);
graphics.beginStroke(strokeColor);
graphics.beginFill(fillColor);
graphics.lineTo(size, 0);
graphics.lineTo(-size / 2.0, size / 2.0);
graphics.closePath();
graphics.endFill();
graphics.endStroke();
// create the shape
super(graphics);
// check if we are pulsing
if (pulse) {
// have the model "pulse"
var growCount = 0;
var growing = true;
createjs__namespace.Ticker.addEventListener('tick', function() {
if (growing) {
that.scaleX *= 1.035;
that.scaleY *= 1.035;
growing = (++growCount < 10);
} else {
that.scaleX /= 1.035;
that.scaleY /= 1.035;
growing = (--growCount < 0);
}
});
}
};
}
/**
* @fileOverview
* @author Inigo Gonzalez - ingonza85@gmail.com
*/
class NavigationImage extends createjs__namespace.Bitmap {
/**
* A navigation image that can be used to display orientation.
*
* @constructor
* @param options - object with following keys:
* * size (optional) - the size of the marker
* * image - the image to use as a marker
* * pulse (optional) - if the marker should "pulse" over time
*/
constructor(options) {
options = options || {};
var size = options.size || 10;
var image_url = options.image;
var pulse = options.pulse;
var alpha = options.alpha || 1;
var originals = {};
var image = new Image();
super(image);
var paintImage = function() {
var scale = calculateScale(size);
this.alpha = alpha;
this.scaleX = scale;
this.scaleY = scale;
this.regY = this.image.height/2;
this.regX = this.image.width/2;
originals['rotation'] = this.rotation;
Object.defineProperty(this, 'rotation', {
get: function(){ return originals['rotation'] + 90; },
set: function(value){ originals['rotation'] = value; }
});
if (pulse) {
// have the model "pulse"
var growCount = 0;
var growing = true;
var SCALE_SIZE = 1.020;
createjs__namespace.Ticker.addEventListener('tick', function() {
if (growing) {
this.scaleX *= SCALE_SIZE;
this.scaleY *= SCALE_SIZE;
growing = (++growCount < 10);
} else {
this.scaleX /= SCALE_SIZE;
this.scaleY /= SCALE_SIZE;
growing = (--growCount < 0);
}
});
}
};
image.onload = paintImage.bind(this);
image.src = image_url;
var calculateScale = function(_size){
return _size / image.width;
};
};
}
/**
* @fileOverview
* @author Bart van Vliet - bart@dobots.nl
*/
class PathShape extends createjs__namespace.Shape {
/**
* A shape to draw a nav_msgs/Path msg
*
* @constructor
* @param options - object with following keys:
* * path (optional) - the initial path to draw
* * strokeSize (optional) - the size of the outline
* * strokeColor (optional) - the createjs color for the stroke
*/
constructor(options) {
options = options || {};
var path = options.path;
this.strokeSize = options.strokeSize || 3;
this.strokeColor = options.strokeColor || createjs__namespace.Graphics.getRGB(0, 0, 0);
// draw the line
this.graphics = new createjs__namespace.Graphics();
if (path !== null && typeof path !== 'undefined') {
this.graphics.setStrokeStyle(this.strokeSize);
this.graphics.beginStroke(this.strokeColor);
this.graphics.moveTo(path.poses[0].pose.position.x / this.scaleX, path.poses[0].pose.position.y / -this.scaleY);
for (var i=1; i<path.poses.length; ++i) {
this.graphics.lineTo(path.poses[i].pose.position.x / this.scaleX, path.poses[i].pose.position.y / -this.scaleY);
}
this.graphics.endStroke();
}
// create the shape
super(this.graphics);
};
/**
* Set the path to draw
*
* @param path of type nav_msgs/Path
*/
setPath(path) {
this.graphics.clear();
if (path !== null && typeof path !== 'undefined') {
this.graphics.setStrokeStyle(this.strokeSize);
this.graphics.beginStroke(this.strokeColor);
this.graphics.moveTo(path.poses[0].pose.position.x / this.scaleX, path.poses[0].pose.position.y / -this.scaleY);
for (var i=1; i<path.poses.length; ++i) {
this.graphics.lineTo(path.poses[i].pose.position.x / this.scaleX, path.poses[i].pose.position.y / -this.scaleY);
}
this.graphics.endStroke();
}
};
}
/**
* @fileOverview
* @author Bart van Vliet - bart@dobots.nl
*/
class PolygonMarker extends createjs__namespace.Container {
/**
* A polygon that can be edited by an end user
*
* @constructor
* @param options - object with following keys:
* * pose (optional) - the first pose of the trace
* * lineSize (optional) - the width of the lines
* * lineColor (optional) - the createjs color of the lines
* * pointSize (optional) - the size of the points
* * pointColor (optional) - the createjs color of the points
* * fillColor (optional) - the createjs color to fill the polygon
* * lineCallBack (optional) - callback function for mouse interaction with a line
* * pointCallBack (optional) - callback function for mouse interaction with a point
*/
constructor(options) {
// var that = this;
super();
options = options || {};
this.lineSize = options.lineSize || 3;
this.lineColor = options.lineColor || createjs__namespace.Graphics.getRGB(0, 0, 255, 0.66);
this.pointSize = options.pointSize || 10;
this.pointColor = options.pointColor || createjs__namespace.Graphics.getRGB(255, 0, 0, 0.66);
this.fillColor = options.pointColor || createjs__namespace.Graphics.getRGB(0, 255, 0, 0.33);
this.lineCallBack = options.lineCallBack;
this.pointCallBack = options.pointCallBack;
// Array of point shapes
// this.points = [];
this.pointContainer = new createjs__namespace.Container();
// Array of line shapes
// this.lines = [];
this.lineContainer = new createjs__namespace.Container();
this.fillShape = new createjs__namespace.Shape();
// Container with all the lines and points
this.addChild(this.fillShape);
this.addChild(this.lineContainer);
this.addChild(this.pointContainer);
};
/**
* Internal use only
*/
createLineShape(startPoint, endPoint) {
var line = new createjs__namespace.Shape();
// line.graphics.setStrokeStyle(this.strokeSize);
// line.graphics.beginStroke(this.strokeColor);
// line.graphics.moveTo(startPoint.x, startPoint.y);
// line.graphics.lineTo(endPoint.x, endPoint.y);
this.editLineShape(line, startPoint, endPoint);
var that = this;
line.addEventListener('mousedown', function(event) {
if (that.lineCallBack !== null && typeof that.lineCallBack !== 'undefined') {
that.lineCallBack('mousedown', event, that.lineContainer.getChildIndex(event.target));
}
});
return line;
};
/**
* Internal use only
*/
editLineShape(line, startPoint, endPoint) {
line.graphics.clear();
line.graphics.setStrokeStyle(this.lineSize);
line.graphics.beginStroke(this.lineColor);
line.graphics.moveTo(startPoint.x, startPoint.y);
line.graphics.lineTo(endPoint.x, endPoint.y);
};
/**
* Internal use only
*/
createPointShape(pos) {
var point = new createjs__namespace.Shape();
point.graphics.beginFill(this.pointColor);
point.graphics.drawCircle(0, 0, this.pointSize);
point.x = pos.x;
point.y = -pos.y;
var that = this;
point.addEventListener('mousedown', function(event) {
if (that.pointCallBack !== null && typeof that.pointCallBack !== 'undefined') {
that.pointCallBack('mousedown', event, that.pointContainer.getChildIndex(event.target));
}
});
return point;
};
/**
* Adds a point to the polygon
*
* @param position of type ROSLIB.Vector3
*/
addPoint(pos) {
var point = this.createPointShape(pos);
this.pointContainer.addChild(point);
var numPoints = this.pointContainer.numChildren;
// 0 points -> 1 point, 0 lines
// 1 point -> 2 points, lines: add line between previous and new point, add line between new point and first point
// 2 points -> 3 points, 3 lines: change last line, add line between new point and first point
// 3 points -> 4 points, 4 lines: change last line, add line between new point and first point
// etc
if (numPoints < 2) ;
else if (numPoints < 3) {
// Now 2 points: add line between previous and new point
var line = this.createLineShape(this.pointContainer.getChildAt(numPoints-2), point);
this.lineContainer.addChild(line);
}
if (numPoints > 2) {
// Now 3 or more points: change last line
this.editLineShape(this.lineContainer.getChildAt(numPoints-2), this.pointContainer.getChildAt(numPoints-2), point);
}
if (numPoints > 1) {
// Now 2 or more points: add line between new point and first point
var lineEnd = this.createLineShape(point, this.pointContainer.getChildAt(0));
this.lineContainer.addChild(lineEnd);
}
this.drawFill();
};
/**
* Removes a point from the polygon
*
* @param obj either an index (integer) or a point shape of the polygon
*/
remPoint(obj) {
var index;
// var point;
if (obj instanceof createjs__namespace.Shape) {
index = this.pointContainer.getChildIndex(obj);
// point = obj;
}
else {
index = obj;
// point = this.pointContainer.getChildAt(index);
}
// 0 points -> 0 points, 0 lines
// 1 point -> 0 points, 0 lines
// 2 points -> 1 point, 0 lines: remove all lines
// 3 points -> 2 points, 2 lines: change line before point to remove, remove line after point to remove
// 4 points -> 3 points, 3 lines: change line before point to remove, remove line after point to remove
// etc
var numPoints = this.pointContainer.numChildren;
if (numPoints < 2) ;
else if (numPoints < 3) {
// 2 points: remove all lines
this.lineContainer.removeAllChildren();
}
else {
// 3 or more points: change line before point to remove, remove line after point to remove
this.editLineShape(
this.lineContainer.getChildAt((index-1+numPoints)%numPoints),
this.pointContainer.getChildAt((index-1+numPoints)%numPoints),
this.pointContainer.getChildAt((index+1)%numPoints)
);
this.lineContainer.removeChildAt(index);
}
this.pointContainer.removeChildAt(index);
// this.points.splice(index, 1);
this.drawFill();
};
/**
* Moves a point of the polygon
*
* @param obj either an index (integer) or a point shape of the polygon
* @param position of type ROSLIB.Vector3
*/
movePoint(obj, newPos) {
var index;
var point;
if (obj instanceof createjs__namespace.Shape) {
index = this.pointContainer.getChildIndex(obj);
point = obj;
}
else {
index = obj;
point = this.pointContainer.getChildAt(index);
}
point.x = newPos.x;
point.y = -newPos.y;
var numPoints = this.pointContainer.numChildren;
if (numPoints > 1) {
// line before moved point
var line1 = this.lineContainer.getChildAt((index-1+numPoints)%numPoints);
this.editLineShape(line1, this.pointContainer.getChildAt((index-1+numPoints)%numPoints), point);
// line after moved point
var line2 = this.lineContainer.getChildAt(index);
this.editLineShape(line2, point, this.pointContainer.getChildAt((index+1)%numPoints));
}
this.drawFill();
};
/**
* Splits a line of the polygon: inserts a point at the center of the line
*
* @param obj either an index (integer) or a line shape of the polygon
*/
splitLine(obj) {
var index;
var line;
if (obj instanceof createjs__namespace.Shape) {
index = this.lineContainer.getChildIndex(obj);
line = obj;
}
else {
index = obj;
line = this.lineContainer.getChildAt(index);
}
var numPoints = this.pointContainer.numChildren;
var xs = this.pointContainer.getChildAt(index).x;
var ys = this.pointContainer.getChildAt(index).y;
var xe = this.pointContainer.getChildAt((index+1)%numPoints).x;
var ye = this.pointContainer.getChildAt((index+1)%numPoints).y;
var xh = (xs+xe)/2.0;
var yh = (ys+ye)/2.0;
var pos = new ROSLIB__namespace.Vector3({ x:xh, y:-yh });
// Add a point in the center of the line to split
var point = this.createPointShape(pos);
this.pointContainer.addChildAt(point, index+1);
++numPoints;
// Add a line between the new point and the end of the line to split
var lineNew = this.createLineShape(point, this.pointContainer.getChildAt((index+2)%numPoints));
this.lineContainer.addChildAt(lineNew, index+1);
// Set the endpoint of the line to split to the new point
this.editLineShape(line, this.pointContainer.getChildAt(index), point);
this.drawFill();
};
/**
* Internal use only
*/
drawFill() {
var numPoints = this.pointContainer.numChildren;
if (numPoints > 2) {
var g = this.fillShape.graphics;
g.clear();
g.setStrokeStyle(0);
g.beginStroke();
g.beginFill(this.fillColor);
g.moveTo(this.pointContainer.getChildAt(0).x, this.pointContainer.getChildAt(0).y);
for (var i=1; i<numPoints; ++i) {
g.lineTo(this.pointContainer.getChildAt(i).x, this.pointContainer.getChildAt(i).y);
}
g.closePath();
g.endFill();
g.endStroke();
}
else {
this.fillShape.graphics.clear();
}
};
}
/**
* @fileOverview
* @author Bart van Vliet - bart@dobots.nl
*/
class TraceShape extends createjs__namespace.Shape {
/**
* A trace of poses, handy to see where a robot has been
*
* @constructor
* @param options - object with following keys:
* * pose (optional) - the first pose of the trace
* * strokeSize (optional) - the size of the outline
* * strokeColor (optional) - the createjs color for the stroke
* * maxPoses (optional) - the maximum number of poses to keep, 0 for infinite
* * minDist (optional) - the minimal distance between poses to use the pose for drawing (default 0.05)
*/
constructor(options) {
// var that = this;
options = options || {};
var pose = options.pose;
this.strokeSize = options.strokeSize || 3;
this.strokeColor = options.strokeColor || createjs__namespace.Graphics.getRGB(0, 0, 0);
this.maxPoses = (options.maxPoses || options.maxPoses === 0) ? options.maxPoses : 100;
this.minDist = options.minDist || 0.05;
// Store minDist as the square of it
this.minDist = this.minDist*this.minDist;
// Array of the poses
// TODO: do we need this?
this.poses = [];
// Create the graphics
this.graphics = new createjs__namespace.Graphics();
this.graphics.setStrokeStyle(this.strokeSize);
this.graphics.beginStroke(this.strokeColor);
// Add first pose if given
if (pose !== null && typeof pose !== 'undefined') {
this.poses.push(pose);
}
// Create the shape
super(this.graphics);
};
/**
* Adds a pose to the trace and updates the graphics
*
* @param pose of type ROSLIB.Pose
*/
addPose(pose) {
var last = this.poses.length-1;
if (last < 0) {
this.poses.push(pose);
this.graphics.moveTo(pose.position.x / this.scaleX, pose.position.y / -this.scaleY);
}
else {
var prevX = this.poses[last].position.x;
var prevY = this.poses[last].position.y;
var dx = (pose.position.x - prevX);
var dy = (pose.position.y - prevY);
if (dx*dx + dy*dy > this.minDist) {
this.graphics.lineTo(pose.position.x / this.scaleX, pose.position.y / -this.scaleY);
this.poses.push(pose);
}
}
if (this.maxPoses > 0 && this.maxPoses < this.poses.length) {
this.popFront();
}
};
/**
* Removes front pose and updates the graphics
*/
popFront() {
if (this.poses.length > 0) {
this.poses.shift();
// TODO: shift drawing instructions rather than doing it all over
this.graphics.clear();
this.graphics.setStrokeStyle(this.strokeSize);
this.graphics.beginStroke(this.strokeColor);
this.graphics.lineTo(this.poses[0].position.x / this.scaleX, this.poses[0].position.y / -this.scaleY);
for (var i=1; i<this.poses.length; ++i) {
this.graphics.lineTo(this.poses[i].position.x / this.scaleX, this.poses[i].position.y / -this.scaleY);
}
}
};
}
/**
* @fileOverview
* @author Bart van Vliet - bart@dobots.nl
*/
class PanView {
/**
* Adds panning to a view
*
* @constructor
* @param options - object with following keys:
* * rootObject (optional) - the root object to apply panning to
*/
constructor(options) {
options = options || {};
this.rootObject = options.rootObject;
// get a handle to the stage
if (this.rootObject instanceof createjs__namespace.Stage) {
this.stage = this.rootObject;
}
else {
this.stage = this.rootObject.getStage();
}
this.startPos = new ROSLIB__namespace.Vector3();
};
startPan(startX, startY) {
this.startPos.x = startX;
this.startPos.y = startY;
};
pan(curX, curY) {
this.stage.x += curX - this.startPos.x;
this.startPos.x = curX;
this.stage.y += curY - this.startPos.y;
this.startPos.y = curY;
};
}
/**
* @fileOverview
* @author Russell Toris - rctoris@wpi.edu
*/
class Viewer {
/**
* A Viewer can be used to render an interactive 2D scene to a HTML5 canvas.
*
* @constructor
* @param options - object with following keys:
* * divID - the ID of the div to place the viewer in
* * width - the initial width, in pixels, of the canvas
* * height - the initial height, in pixels, of the canvas
* * background (optional) - the color to render the background, like '#efefef'
*/
constructor(options) {
options = options || {};
var divID = options.divID;
this.width = options.width;
this.height = options.height;
var background = options.background || '#111111';
// create the canvas to render to
var canvas = document.createElement('canvas');
canvas.width = this.width;
canvas.height = this.height;
canvas.style.background = background;
document.getElementById(divID).appendChild(canvas);
// create the easel to use
this.scene = new createjs__namespace.Stage(canvas);
// change Y axis center
this.scene.y = this.height;
// add the renderer to the page
document.getElementById(divID).appendChild(canvas);
// update at 30fps
createjs__namespace.Ticker.framerate = 30;
createjs__namespace.Ticker.addEventListener('tick', this.scene);
};
/**
* Add the given createjs object to the global scene in the viewer.
*
* @param object - the object to add
*/
addObject(object) {
this.scene.addChild(object);
};
/**
* Scale the scene to fit the given width and height into the current canvas.
*
* @param width - the width to scale to in meters
* @param height - the height to scale to in meters
*/
scaleToDimensions(width, height) {
// restore to values before shifting, if ocurred
this.scene.x = typeof this.scene.x_prev_shift !== 'undefined' ? this.scene.x_prev_shift : this.scene.x;
this.scene.y = typeof this.scene.y_prev_shift !== 'undefined' ? this.scene.y_prev_shift : this.scene.y;
// save scene scaling
this.scene.scaleX = this.width / width;
this.scene.scaleY = this.height / height;
};
/**
* Shift the main view of the canvas by the given amount. This is based on the
* ROS coordinate system. That is, Y is opposite that of a traditional canvas.
*
* @param x - the amount to shift by in the x direction in meters
* @param y - the amount to shift by in the y direction in meters
*/
shift(x, y) {
// save current offset
this.scene.x_prev_shift = this.scene.x;
this.scene.y_prev_shift = this.scene.y;
// shift scene by scaling the desired offset
this.scene.x -= (x * this.scene.scaleX);
this.scene.y += (y * this.scene.scaleY);
};
}
/**
* @fileOverview
* @author Bart van Vliet - bart@dobots.nl
*/
class ZoomView {
/**
* Adds zooming to a view
*
* @constructor
* @param options - object with following keys:
* * rootObject (optional) - the root object to apply zoom to
* * minScale (optional) - minimum scale to set to preserve precision
*/
constructor(options) {
options = options || {};
this.rootObject = options.rootObject;
this.minScale = options.minScale || 0.001;
// get a handle to the stage
if (this.rootObject instanceof createjs__namespace.Stage) {
this.stage = this.rootObject;
}
else {
this.stage = this.rootObject.getStage();
}
this.center = new ROSLIB__namespace.Vector3();
this.startShift = new ROSLIB__namespace.Vector3();
this.startScale = new ROSLIB__namespace.Vector3();
};
startZoom(centerX, centerY) {
this.center.x = centerX;
this.center.y = centerY;
this.startShift.x = this.stage.x;
this.startShift.y = this.stage.y;
this.startScale.x = this.stage.scaleX;
this.startScale.y = this.stage.scaleY;
};
zoom(zoom) {
// Make sure scale doesn't become too small
if (this.startScale.x*zoom < this.minScale) {
zoom = this.minScale/this.startScale.x;
}
if (this.startScale.y*zoom < this.minScale) {
zoom = this.minScale/this.startScale.y;
}
this.stage.scaleX = this.startScale.x*zoom;
this.stage.scaleY = this.startScale.y*zoom;
this.stage.x = this.startShift.x - (this.center.x-this.startShift.x) * (this.stage.scaleX/this.startScale.x - 1);
this.stage.y = this.startShift.y - (this.center.y-this.startShift.y) * (this.stage.scaleY/this.startScale.y - 1);
};
}
exports.ArrowShape = ArrowShape;
exports.Grid = Grid;
exports.ImageMap = ImageMap;
exports.ImageMapClient = ImageMapClient;
exports.NavigationArrow = NavigationArrow;
exports.NavigationImage = NavigationImage;
exports.OccupancyGrid = OccupancyGrid;
exports.OccupancyGridClient = OccupancyGridClient;
exports.OccupancyGridSrvClient = OccupancyGridSrvClient;
exports.PanView = PanView;
exports.PathShape = PathShape;
exports.PolygonMarker = PolygonMarker;
exports.TraceShape = TraceShape;
exports.Viewer = Viewer;
exports.ZoomView = ZoomView;
Object.defineProperty(exports, '__esModule', { value: true });
return exports;
})({}, createjs, ROSLIB);