Skip to content
Snippets Groups Projects
Commit 631a9245 authored by Oleksandr Husak's avatar Oleksandr Husak
Browse files

display relative position

parent cc3d414c
No related branches found
No related tags found
No related merge requests found
...@@ -35,7 +35,8 @@ ...@@ -35,7 +35,8 @@
], ],
"styles": [ "styles": [
"./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss" "src/styles.scss",
"./node_modules/leaflet/dist/leaflet.css"
], ],
"scripts": [] "scripts": []
}, },
......
This diff is collapsed.
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
"@angular/router": "~12.2.0", "@angular/router": "~12.2.0",
"@asymmetrik/ngx-leaflet": "^8.1.0", "@asymmetrik/ngx-leaflet": "^8.1.0",
"leaflet": "^1.7.1", "leaflet": "^1.7.1",
"ngx-mqtt": "^9.0.5",
"rxjs": "~6.6.0", "rxjs": "~6.6.0",
"tslib": "^2.3.0", "tslib": "^2.3.0",
"zone.js": "~0.11.4" "zone.js": "~0.11.4"
......
...@@ -4,5 +4,3 @@ ...@@ -4,5 +4,3 @@
<app-map class="wrapper"></app-map> <app-map class="wrapper"></app-map>
<router-outlet></router-outlet>
...@@ -4,6 +4,11 @@ import { BrowserModule } from '@angular/platform-browser'; ...@@ -4,6 +4,11 @@ import { BrowserModule } from '@angular/platform-browser';
// --- Map // --- Map
import { LeafletModule } from '@asymmetrik/ngx-leaflet'; import { LeafletModule } from '@asymmetrik/ngx-leaflet';
// --- MQTT
import { MqttModule } from 'ngx-mqtt';
import { MQTTconfig } from './../environments/environment';
// --- WS // --- WS
// import * as SockJS from 'sockjs-client'; // import * as SockJS from 'sockjs-client';
...@@ -14,7 +19,6 @@ import { CoreModule } from './core/core.module'; ...@@ -14,7 +19,6 @@ import { CoreModule } from './core/core.module';
// --- Services // --- Services
import { ApiService } from "./core/api.service"; import { ApiService } from "./core/api.service";
// import { StompService, StompConfig } from '@stomp/ng2-stompjs'; // import { StompService, StompConfig } from '@stomp/ng2-stompjs';
import { environment } from './../environments/environment';
// --- Components // --- Components
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
...@@ -35,7 +39,8 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; ...@@ -35,7 +39,8 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
SharedModule, SharedModule,
CoreModule, CoreModule,
LeafletModule, LeafletModule,
BrowserAnimationsModule BrowserAnimationsModule,
MqttModule.forRoot(MQTTconfig)
], ],
providers: [ApiService], providers: [ApiService],
bootstrap: [AppComponent] bootstrap: [AppComponent]
......
.map {
margin-bottom: 20px;
height: 70vh
}
table {
width: 100%;
}
.table {
margin-bottom: 35px;
th.mat-header-cell {
vertical-align: middle;
}
}
\ No newline at end of file
import { NONE_TYPE } from '@angular/compiler';
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import * as L from "leaflet"; import { Subscription } from 'rxjs';
class Location {
id: string;
type = 'position';
lat: Float32Array;
lng: Float32Array;
constructor(obj: any, id: any) {
this.id = id
this.lat = obj.lat
this.lng = obj.lng
}
}
class Measurements { import * as L from "leaflet";
id: string import { IMqttMessage, MqttService } from 'ngx-mqtt';
type = 'measurements'
data: number[];
constructor(dist: any, id: any) { import { environment } from 'src/environments/environment';
this.id = id import {RelativePos, WGS84} from 'src/app/model/base-model';
this.data = dist
}
}
@Component({ @Component({
selector: 'app-map', selector: 'app-map',
...@@ -33,90 +14,122 @@ class Measurements { ...@@ -33,90 +14,122 @@ class Measurements {
}) })
export class MapComponent implements OnInit { export class MapComponent implements OnInit {
_stompService: any; private subsPosition: Subscription;
map: L.Map; private subsOrigin: Subscription;
constructor() { private map!: L.Map;
this.map = L.map('map', {
center: [51.505, -0.09],
zoom: 13
});
}
ngOnInit(): void { private origin!: WGS84;
// wait on new Location
this._stompService.watch('/topic/locations').subscribe((message: any) => { agentsInfo = new Map();
let payload = JSON.parse(message.body); markOverlays = new Map();
this.addNewMarker(payload) posOverlays: { [key: string]: L.LayerGroup<any> } = {};
constructor(private _mqttService: MqttService) {
this.origin = {"latitude": 51.02545, "longitude": 13.72295}
this.subsPosition = this._mqttService.observe('testtopic/5699').subscribe((message: IMqttMessage) => {
let pos: RelativePos = JSON.parse(message.payload.toString())
this.updatePosition('default', pos)
}); });
// wait on new measurements this.subsOrigin = this._mqttService.observe('testtopic/5699/origin').subscribe((message: IMqttMessage) => {
this._stompService.watch('/topic/positions').subscribe((message: any) => { this.origin = JSON.parse(message.payload.toString())
let payload = JSON.parse(message.body);
console.log('positions', payload)
this.addPosition(payload)
}); });
} }
addPosition(point: any) { ngOnInit(): void {}
let marker = L.marker(point.position, {
icon: L.icon({
iconSize: [25, 41],
iconAnchor: [13, 41],
iconUrl: 'assets/marker-icon-red.png',
iconRetinaUrl: 'assets/marker-icon-2x-red.png',
shadowUrl: 'assets/marker-shadow.png'
})
}).bindPopup(point.id).openPopup();
marker.addTo(this.map);
}
// --- Controllers // --- Controllers
updatePosition(key: string, pos: RelativePos) {
// estimated position of an agent
let glob_pos = this.convert2wgs(pos)
// let point = L.point(pos.x, pos.y);
// let glob_pos = (this.map).layerPointToLatLng(point)
// --- Leyers
if (key in this.posOverlays) {
this.posOverlays[key].clearLayers();
} else {
this.posOverlays[key] = L.layerGroup().addTo(<L.Map>this.map)
}
// --- Info
this.agentsInfo.set(key, {"glob_pos": glob_pos})
L.circle(glob_pos, 6, { color: '#d32f2f' }
).addTo(this.posOverlays[key]);
}
convert2wgs(pos: RelativePos) {
let origin = L.latLng([this.origin.latitude, this.origin.longitude]);
let point = this.map.latLngToContainerPoint(origin);
let newPoint = L.point([point.x + pos.x, point.y + pos.y]);
let newLatLng = this.map.containerPointToLatLng(newPoint);
return newLatLng
}
// @https://asymmetrik.com/ngx-leaflet-tutorial-angular-cli/ // @https://asymmetrik.com/ngx-leaflet-tutorial-angular-cli/
// --- Layers: Define base layers so we can reference them multiple times // --- Layers: Define base layers so we can reference them multiple times
streetMaps = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { streetMaps = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
detectRetina: true, detectRetina: true,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}); });
wMaps = L.tileLayer('http://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png', { wMaps = L.tileLayer('http://maps.wikimedia.org/osm-intl/{z}/{x}/{y}.png', {
detectRetina: true, detectRetina: true,
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}); });
satelliteMaps = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { satelliteMaps = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
id: 'mapbox.streets', id: 'mapbox.gis',
attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' attribution: 'Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
}); });
mapBoxMaps = L.tileLayer(
'https://api.mapbox.com/styles/v1/mapbox/streets-v11/tiles/{z}/{x}/{y}?access_token=' + environment.mapbox.accessToken2, {
id: 'mapbox.streets-v11',
attribution: '© <a href="https://apps.mapbox.com/feedback/">Mapbox</a> © <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
})
options = { options = {
layers: [this.streetMaps], layers: [this.mapBoxMaps],
zoom: 15, zoom: 19,
center: L.latLng([51.037845, 13.762852]) center: L.latLng([51.02545, 13.72295])
}; };
onMapReady(map: L.Map) { onMapReady(map: L.Map) {
this.map = map
// Layers control object with our two base layers and the three overlay layers this.map = map;
let baseLayers = { let baseLayers = {
'MapBox': this.mapBoxMaps,
'Street Maps': this.streetMaps, 'Street Maps': this.streetMaps,
'Wikimedia Maps': this.wMaps, 'Wikimedia Maps': this.wMaps,
'Satellite': this.satelliteMaps 'Satellite': this.satelliteMaps
} }
L.control.layers(baseLayers).addTo(this.map); L.control.layers(baseLayers).addTo(this.map);
let legend = new L.Control({ position: "bottomleft" });
legend.onAdd = function () {
var div = L.DomUtil.create("div", "legend");
div.innerHTML += '<img style="opacity: .5" src="assets/marker-icon-grey.png"> <span> Agents </span><br>';
div.innerHTML += '<i class="est-pos"></i> <span> Estimated position </span><br>';
return div;
};
legend.addTo(this.map);
} }
addNewMarker(obj: any) { public ngOnDestroy() {
let marker = L.marker([obj.lat, obj.lng], { this.subsPosition.unsubscribe();
icon: L.icon({ this.subsOrigin.unsubscribe();
iconSize: [25, 41],
iconAnchor: [13, 41],
iconUrl: 'assets/marker-icon-grey.png',
iconRetinaUrl: 'assets/marker-icon-2x-grey.png',
shadowUrl: 'assets/marker-shadow.png'
})
}).bindPopup(obj.id).openPopup();
marker.addTo(this.map);
} }
} }
export interface WGS84 {
latitude: number
longitude: number
}
export interface RelativePos {
x: number
y: number
}
interface IposConfigWrapper {
frames: IposFrameConfig[]
objects: IposObject[]
objectConfigs: IposObjectConfig[]
refSystems: RefSystem[]
monitoringRequests: IposMonitoringRequest[]
}
interface IposObjectConfig {
agentId: string
sensorId: string
agentType: string
sensorType: string
}
// note: IposObjectConfigs are used to register sensors. Beacon-positions are POIs and should be sent to sensor after registration. Bluetooth/UWB sensor need to know a reference system id. All Beacon-position sent to the Bluetooth/UWB sensor should have the same reference system id
interface IposPositionEvent {
object: IposObject[]
type: string
// repeated IposZoneDescriptor zoneDescriptors = 2; // contains information about all zones that this position belongs to
}
interface IposZoneDescriptor {
zoneId: string
type: string
}
interface IposObject {
id: string
sensorId: string
type: string
sensorType: string
position: IposPosition
orientation: IposSimpleOrientation
lastPosUpdate: string
}
interface IposFrameConfig {
id: string
space: IposSpace[]
}
interface RefSystem {
id: string
position: IposPosition
orientation: IposSimpleOrientation
}
interface IposMonitoringRequest {
frameId: string
// repeated string frameIds = 1;
delta: number
updateFrequency: number
type: string[]
id: string[]
fusionStrategy: string
exit_notification: boolean
properties: string[]
monitoringTaskId: string
requestorProtocol: string
}
interface IposMonitoringResponse {
monitoringTaskId: string
status: string
}
interface IposPosition {
refSystemId: string
point: IposPoint3D
accuracy: number
}
interface IposPoint3D {
x: number
y: number
z: number
}
interface IposSpace {
position: IposPosition
orientation: IposSimpleOrientation
x: number
y: number
z: number
}
interface IposSimpleOrientation {
x: number
y: number
z: number
w: number
}
...@@ -47,7 +47,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; ...@@ -47,7 +47,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
MatCardModule, MatCardModule,
MatExpansionModule, MatExpansionModule,
MatSidenavModule, MatSidenavModule,
MatTooltipModule MatTooltipModule,
], ],
exports: [ exports: [
FormsModule, FormsModule,
...@@ -67,7 +67,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; ...@@ -67,7 +67,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
MatCardModule, MatCardModule,
MatExpansionModule, MatExpansionModule,
MatSidenavModule, MatSidenavModule,
MatTooltipModule MatTooltipModule,
] ]
}) })
export class SharedModule { } export class SharedModule { }
...@@ -2,17 +2,27 @@ ...@@ -2,17 +2,27 @@
// `ng build` replaces `environment.ts` with `environment.prod.ts`. // `ng build` replaces `environment.ts` with `environment.prod.ts`.
// The list of file replacements can be found in `angular.json`. // The list of file replacements can be found in `angular.json`.
import { IMqttServiceOptions } from 'ngx-mqtt';
export const environment = { export const environment = {
production: false, production: false,
APIEndpoint: 'http://localhost:7071', APIEndpoint: 'http://localhost:7071',
mapbox: { mapbox: {
accessToken: 'pk.eyJ1IjoidmFsYXZhbmNhIiwiYSI6ImNrbGZlNzhpaTJhb3oyeG4weHEyZ2dvaDMifQ.3CSKC5AkzxrAtQ40BD5tsQ' accessToken1: 'pk.eyJ1IjoidmFsYXZhbmNhIiwiYSI6ImNrbGZlNzhpaTJhb3oyeG4weHEyZ2dvaDMifQ.3CSKC5AkzxrAtQ40BD5tsQ',
accessToken2: 'pk.eyJ1IjoidmFsYXZhbmNhIiwiYSI6ImNrbGZlYm13ZTJtZ2gyb25wbGhqdGhmZzkifQ.atRzBqwKjY9wEUlue2YLzQ'
}, },
indoorequal: { indoorequal: {
APIkey: 'l70N1y3m02lRDrlIqOzYyB' APIkey: 'l70N1y3m02lRDrlIqOzYyB'
} },
};
export const MQTTconfig: IMqttServiceOptions = {
hostname: 'broker.hivemq.com',
port: 8000,
path: '/mqtt'
}; };
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head> </head>
<body> <body>
<app-root></app-root> <app-root>
<div style="margin:20px; font-size:16px;">
Loading...
</div>
</app-root>
</body> </body>
</html> </html>
...@@ -18,3 +18,54 @@ app-root { ...@@ -18,3 +18,54 @@ app-root {
html, body { height: 100%; } html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
/*Legend specific*/
.legend {
padding: 6px 8px;
font: 14px Arial, Helvetica, sans-serif;
background: white;
background: rgba(255, 255, 255, 0.8);
/*box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);*/
/*border-radius: 5px;*/
line-height: 24px;
color: $primary-text-color;
h4 {
text-align: center;
font-size: 16px;
margin: 2px 12px 8px;
color: $primary-text-color;
}
span {
position: relative;
bottom: 3px;
}
i {
width: 18px;
height: 18px;
float: left;
margin: 0 8px 0 0;
opacity: 0.7;
.icon {
background-size: 18px;
background-color: rgba(255, 255, 255, 1);
}
}
img {
height: 35px;
}
.est-pos {
border: 3px solid #d32f2f;
background-color: rgba(211, 47, 47, .4);
border-radius: 50%;
}
}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment