=> because they don't represent a Data/R/S
$ npm install
$ gulp build
$ gulp build-minify
$ gulp clean
clone git@github.com:opensensorhub/osh-js.git
<swes:offering>
<sos:ObservationOffering>
<swes:description>Archive data from Solo Nav DataStore</swes:description>
<swes:identifier>urn:osh:solo-nav</swes:identifier>
<swes:name>Solo Nav DataStore</swes:name>
<swes:procedure>urn:osh:sensor:mavlink:solo:S115A5800419</swes:procedure>
<swes:observableProperty>http://www.opengis.net/def/property/OGC/0/PlatformOrientation</swes:observableProperty>
<swes:observableProperty>http://sensorml.com/ont/swe/property/OSH/0/GimbalOrientation</swes:observableProperty>
<swes:observableProperty>http://www.opengis.net/def/property/OGC/0/PlatformLocation</swes:observableProperty>
<sos:phenomenonTime>
<gml:TimePeriod gml:id="T4">
<gml:beginPosition>2016-08-30T18:58:46.180Z</gml:beginPosition>
<gml:endPosition>2016-08-30T19:20:17.002Z</gml:endPosition>
</gml:TimePeriod>
</sos:phenomenonTime>
...
</swes:offering>
<swes:offering>
<sos:ObservationOffering>
<swes:description>Archive data from Solo Video DataStore</swes:description>
<swes:identifier>urn:osh:solo-video</swes:identifier>
<swes:name>Solo Video DataStore</swes:name>
<swes:procedure>urn:osh:sensor:rtpcam:solo:S115A5800419</swes:procedure>
<swes:observableProperty>http://sensorml.com/ont/swe/property/VideoFrame</swes:observableProperty>
<swes:observableProperty>http://sensorml.com/ont/swe/property/Image</swes:observableProperty>
<sos:phenomenonTime>
<gml:TimePeriod gml:id="T5">
<gml:beginPosition>2016-08-30T18:59:03.009Z</gml:beginPosition>
<gml:endPosition>2016-08-30T19:20:16.402Z</gml:endPosition>
</gml:TimePeriod>
</sos:phenomenonTime>
...
</swes:offering>
Offering
ObservableProperty
Time
<body>
<div id="container-1" class="mini-view"></div> <!-- Video View -->
<div id="container-2" class="mini-view"></div> <!-- Chart View -->
<div id="container-3" class="mini-view"></div> <!-- Cesium View -->
</body>
// DEFINE TIME
var startTime = "2016-08-30T19:00:40Z";
var endTime = "2016-08-30T19:22:00Z";
var replaySpeed = "1";
// LatLon DataReceiver
var soloGPS = new OSH.DataReceiver.LatLonAlt("Solo GPS", {
protocol : "ws",
service: "SOS",
endpointUrl: hostname + "/sensorhub/sos",
offeringID: "urn:osh:solo-nav",
observedProperty: "http://www.opengis.net/def/property/OGC/0/PlatformLocation",
startTime: startTime,
endTime: endTime,
replaySpeed: replaySpeed,
syncMasterTime: true
});
// Orientation DataReceiver
var soloAttitude = new OSH.DataReceiver.EulerOrientation("Solo Attitude", {
protocol : "ws",
service: "SOS",
endpointUrl: hostname + "/sensorhub/sos",
offeringID: "urn:osh:solo-nav",
observedProperty: "http://www.opengis.net/def/property/OGC/0/PlatformOrientation",
startTime: startTime,
endTime: endTime,
replaySpeed: replaySpeed,
syncMasterTime: true
});
Synchronize the data
// Gimbal orientation DataReceiver
var soloGimbal = new OSH.DataReceiver.EulerOrientation("Solo Gimbal", {
protocol : "ws",
service: "SOS",
endpointUrl: hostname + "/sensorhub/sos",
offeringID: "urn:osh:solo-nav",
observedProperty: "http://sensorml.com/ont/swe/property/OSH/0/GimbalOrientation",
startTime: startTime,
endTime: endTime,
replaySpeed: replaySpeed,
syncMasterTime: true
});
// Video H264 DataReceiver
var soloVideo = new OSH.DataReceiver.VideoH264("Solo Video", {
protocol : "ws",
service: "SOS",
endpointUrl: hostname + "/sensorhub/sos",
offeringID: "urn:osh:solo-video",
observedProperty: "http://sensorml.com/ont/swe/property/VideoFrame",
startTime: startTime,
endTime: endTime,
replaySpeed: replaySpeed,
timeShift: -100,
syncMasterTime: true
});
//--------------------------------------------------------------//
//-------------------------- Entities --------------------------//
//--------------------------------------------------------------//
var soloEntity = {
id: "solo1",
name: "3DR Solo",
dataSources: [soloGPS, soloAttitude, soloGimbal, soloVideo]
};
//--------------------------------------------------------------//
//--------------------------- Views ---------------------------//
//--------------------------------------------------------------//
var soloVideoView = new OSH.UI.FFMPEGView("container-1", {
dataSourceId: soloVideo.getId(),
entityId : soloEntity.id,
css: "video",
cssSelected: "video-selected",
useWorker: true,
width: 1280,
height: 720
});
//--------------------------------------------------------------//
//--------------------------- Views ---------------------------//
//--------------------------------------------------------------//
var altChartView = new OSH.UI.Nvd3CurveChartView("container-2",
[{
styler: new OSH.UI.Styler.Curve({
valuesFunc: {
dataSourceIds: [soloGPS.getId()],
handler: function (rec, timeStamp) {
if (rec.alt < 1)
rec.alt *= 1e4; // *10^4 due to bug in Toulouse dataset
return {
x: timeStamp,
y: rec.alt+mslToWgs84
};
}
}
})
}],
{
dataSourceId: soloGPS.getId(),
yLabel: 'Altitude (m)',
xLabel: 'Time',
maxPoints: 100,
css:"chart-view",
cssSelected: "video-selected"
});
We use styler to apply an altitude rectification
Define Graph View properties
//--------------------------------------------------------------//
//--------------------------- Views ---------------------------//
//--------------------------------------------------------------//
// common point marker
var pointMarker = new OSH.UI.Styler.PointMarker({
label: "3DR Solo",
locationFunc : {
dataSourceIds : [soloGPS.getId()],
handler : function(rec) {
if (rec.alt < 1)
rec.alt *= 1e4; // *10^4 due to bug in Toulouse dataset
return {
x : rec.lon,
y : rec.lat,
z : rec.alt+mslToWgs84-5. // model offset
};
}
},
orientationFunc : {
dataSourceIds : [soloAttitude.getId()],
handler : function(rec) {
return {
heading : rec.heading
};
}
},
icon: "./models/Drone+06B.glb"
});
We use styler to add MSL to LatLon data
Get heading from altitude dataReceiver
var imageDrapingStyler = new OSH.UI.Styler.ImageDraping({
platformLocationFunc: {
dataSourceIds: [soloGPS.getId()],
handler: function(rec) {
if (rec.alt < 1)
rec.alt *= 1e4; // *10^4 due to bug in Toulouse dataset
return {
x: rec.lon,
y: rec.lat,
z: rec.alt + mslToWgs84
};
}
},
platformOrientationFunc: {
dataSourceIds: [soloAttitude.getId()],
handler: function(rec) {
return {
heading: rec.heading,
pitch: 0, //rec.pitch,
roll: 0, //rec.roll
};
}
},
gimbalOrientationFunc: {
dataSourceIds: [soloGimbal.getId()],
handler: function(rec) {
return {
heading: rec.heading,
pitch: -92, //rec.pitch,
roll: 0, //rec.roll
};
}
},
/*GoPro Mike*/
cameraModel: {
camProj: new Cesium.Matrix3(747.963 / 1280., 0.0, 650.66 / 1280.,
0.0, 769.576 / 738., 373.206 / 738.,
0.0, 0.0, 1.0),
camDistR: new Cesium.Cartesian3(-2.644e-01, 8.4e-02, 0.0),
camDistT: new Cesium.Cartesian2(-8.688e-04, 6.123e-04)
},
imageSrc: $$('#' + soloVideoView.getId() + ' canvas')[0]
})
Location
Camera setup
EulerOrientation
GimbalOrientation
var mapView = new OSH.UI.CesiumView("container-3", [
{
name: "3DR Solo",
entityId: soloEntity.id,
styler: pointMarkerStyler
}, {
name: "Geolocated Imagery",
entityId: soloEntity.id,
styler: imageDrapingStyler
}]);
ViewItem 1
ViewItem 2
var dataSourceController = new OSH.DataReceiver.DataReceiverController({
replayFactor: 1.0
});
dataSourceController.addEntity(soloEntity);
dataSourceController.connectAll();
// or fire an event
//OSH.EventManager.fire(OSH.EventManager.EVENT.CONNECT_DATASOURCE,
// {dataSourcesId:[videoDataSource.id]});
<div id="main-container" class="main-view"></div>
<div id="dialog-main-container" class="video-main-container"></div>
// video view
var soloVideoDialog = new OSH.UI.DialogView("dialog-main-container", {
draggable: false,
css: "video-dialog",
name: "UAV Video",
show: true,
dockable: true,
closeable: true,
canDisconnect : false,
swapId: "main-container"
});
var soloVideoView = new OSH.UI.FFMPEGView(soloVideoDialog.popContentDiv.id, {
dataSourceId: soloVideo.getId(),
entityId : soloEntity.id,
css: "video",
cssSelected: "video-selected",
useWorker: true,
width: 1280,
height: 720
});
plug the dialog to a main container
set the dialog div id instead of container id
// chart view
var altChartDialog = new OSH.UI.DialogView("dialog-main-container", {
draggable: false,
css: "dialog",
name: "Solo Altitude",
show: false,
dockable: true,
closeable: true,
canDisconnect : false,
swapId: "main-container"
});
var altChartView = new OSH.UI.Nvd3CurveChartView(altChartDialog.popContentDiv.id, ...);
// Cesium view is plugged as background
var mapView = new OSH.UI.CesiumView("main-container",...)
plug the dialog to a main container
Cesium is set as background
// menu ids
var soloTreeMenuId = "solo-tree-menu";
var soloMarkerMenuId = "solo-marker-menu";
var menuGroupId = "allmenus";
// cesium map view
var mapView = new OSH.UI.CesiumView("main-container", [{
name: "3DR Solo",
entityId: soloEntity.id,
styler: pointMarker,
contextMenuId: soloMarkerMenuId
}
[...]
var menuItems = [{
name: "Show Video",
viewId: soloVideoDialog.getId(),
css: "fa fa-video-camera",
action: "show"
}, {
name: "Show Altitude Chart",
viewId: altChartDialog.getId(),
css: "fa fa-bar-chart",
action: "show"
}, {
name: "TakeOff",
viewId: "",
css: "fa fa-upload",
action: "uav:takeoff"
}, {
name: "Land",
viewId: "",
css: "fa fa-download",
action: "uav:land"
}];
var markerMenu = new OSH.UI.ContextMenu.CircularMenu({
id: soloMarkerMenuId,
groupId: menuGroupId,
items: menuItems
});
Can also use EventManager:
OSH.EventManager.EVENT.SHOW_VIEW
// tree view
var entityTreeDialog = new OSH.UI.DialogView(document.body.id, {
css: "tree-dialog",
name: "Entities",
show: true,
draggable: true,
dockable: false,
closeable: true
});
var entityTreeView = new OSH.UI.EntityTreeView(entityTreeDialog.popContentDiv.id,
[{
entity : soloEntity,
path: "Sensors/Solo",
treeIcon : "images/drone.png",
contextMenuId: soloTreeMenuId
}],
{
css: "tree-container"
}
);
<div class="rangeSlider-container">
<div id="rangeSlider" class="rangeSlider"></div>
</div>
var rangeSlider = new OSH.UI.RangeSlider("rangeSlider",{
startTime: "2015-02-16T07:58:00Z",
endTime: "2015-02-16T08:09:00Z",
refreshRate:1
});
var rangeSlider = new OSH.UI.RangeSlider("rangeSlider");
OSH.DataReceiver.MyFakeLatLonAlt = Class.create(OSH.DataReceiver.DataSource,{
parseTimeStamp: function($super,data){
// do something
// this part extract the timestamp from data
// the data could be text, binary etc..
},
parseData: function($super,data){
// do something
// this part extract only the data without timestamp
}
});
parseTimeStamp: function($super,data){
// get record from websocket
var record = String.fromCharCode.apply(null, new Uint8Array(data));
// split the record using "," as separator
var tokens = record.trim().split(",");
// return the timeStamp using Data JS Object and getTime (milliseconds)
return new Date(tokens[0]).getTime();
}
parseData: function($super,data){
// get data from WebSocket
var record = String.fromCharCode.apply(null, new Uint8Array(data));
// split String using "," as separator
var tokens = record.trim().split(",");
// get lat, lon, alt
var lat = parseFloat(tokens[1]);
var lon = parseFloat(tokens[2]);
var alt = parseFloat(tokens[3]);
// return JS object
return {
lat : lat,
lon : lon,
alt : alt
};
}
var myFakeLatLonAlt = new OSH.DataReceiver.MyFakeLatLonAlt("Fake GPS", {
protocol : "ws",
service: "SOS",
endpointUrl: hostname + "/sensorhub/sos",
offeringID: "fake-offering",
observedProperty: "http://www.opengis.net/def/property/OGC/0/PlatformLocation",
startTime: 2016-08-30T19:00:40Z,
endTime: 2016-08-30T19:22:00Z,
replaySpeed: 1,
syncMasterTime: true
});
var discoveryView = new OSH.UI.DiscoveryView("",{
services: ["http://localhost:8181/","http://sensiasoft.net:8181/"],
css: "discovery-view",
dataReceiverController:dataProviderController,
swapId: "center-container",
entities: [androidEntity],
views: [{
name: 'Leaflet 2D Map',
viewId: leafletMainView.id,
type : OSH.UI.DiscoveryView.Type.MARKER_GPS
}, {
name: 'Cesium 3D Globe',
viewId: cesiumMainMapView.id,
type : OSH.UI.DiscoveryView.Type.MARKER_GPS
},{
name: 'Video dialog(H264)',
type : OSH.UI.DiscoveryView.Type.DIALOG_VIDEO_H264
},{
name: 'Video dialog(MJPEG)',
type : OSH.UI.DiscoveryView.Type.DIALOG_VIDEO_MJPEG
},{
name: 'Chart dialog',
type : OSH.UI.DiscoveryView.Type.DIALOG_CHART
}]
});