diff --git a/Server/src/services/poi.service.ts b/Server/src/services/poi.service.ts index 3807821..474ed65 100644 --- a/Server/src/services/poi.service.ts +++ b/Server/src/services/poi.service.ts @@ -16,7 +16,7 @@ export default class POIService { * @param track `Track` the new POI belongs to, if no track is given, the closest will be chosen * @param description optional description of the new POI * @param isTurningPoint is the new POI a point, where one can turn around their vehicle (optional) - * @returns created `POI` if successful, `null` otherwise + * @returns created `POI` if successful */ public static async createPOI( position: GeoJSON.Feature, @@ -25,24 +25,18 @@ export default class POIService { track?: Track, description?: string, isTurningPoint?: boolean - ): Promise { + ): Promise { // TODO: check if poi is anywhere near the track // get closest track if none is given if (track == null) { - const tempTrack = await TrackService.getClosestTrack(position) - if (tempTrack == null) { - logger.error(`No closest track was found for position ${JSON.stringify(position)}.`) - return null - } - track = tempTrack + track = await TrackService.getClosestTrack(position) } // add kilometer value - const enrichedPoint = await this.enrichPOIPosition(position, track) - if (enrichedPoint == null) { - logger.error(`The position ${JSON.stringify(position)} could not be enriched.`) - return null - } + const enrichedPoint = await this.enrichPOIPosition( + position, + track ?? (await TrackService.getClosestTrack(position)) + ) // Note: geopos is from type GeoJSON.Feature and can't be parsed directly into Prisma.InputJsonValue // Therefore we cast it into unknown first. @@ -60,28 +54,19 @@ export default class POIService { * Add value of track kilometer to properties for a given point * @param point position of POI to enrich * @param track optional `TracK`, which is used to compute the track kilometer, if none is given the closest will be used - * @returns point with added track kilometer, `null` if not successful + * @returns point with added track kilometer */ public static async enrichPOIPosition( point: GeoJSON.Feature, track?: Track - ): Promise | null> { + ): Promise> { // initialize track if none is given if (track == null) { - const tempTrack = await TrackService.getClosestTrack(point) - if (tempTrack == null) { - logger.error(`No closest track was found for position ${JSON.stringify(point)}.`) - return null - } - track = tempTrack + track = await TrackService.getClosestTrack(point) } // calculate and set track kilometer - const trackKm = await TrackService.getPointTrackKm(point, track) - if (trackKm == null) { - logger.error(`Could not get track distance for position ${JSON.stringify(point)} on track with id ${track.uid}.`) - return null - } + const trackKm = TrackService.getPointTrackKm(point, track) GeoJSONUtils.setTrackKm(point, trackKm) return point } @@ -89,48 +74,30 @@ export default class POIService { /** * Wrapper to get distance of poi in kilometers along the assigned track * @param poi `POI` to get the distance for - * @returns track kilometer of `poi`, `null` if computation was not possible + * @returns track kilometer of `poi` */ - public static async getPOITrackDistanceKm(poi: POI): Promise { + public static async getPOITrackDistanceKm(poi: POI): Promise { // get closest track if none is given const poiPos = GeoJSONUtils.parseGeoJSONFeaturePoint(poi.position) - if (poiPos == null) { - logger.error(`Position ${JSON.stringify(poi.position)} could not be parsed.`) - return null - } // get track distance in kilometers let poiTrackKm = GeoJSONUtils.getTrackKm(poiPos) if (poiTrackKm == null) { - if (poiTrackKm == null) { - logger.info(`Position of POI with ID ${poi.uid} is not enriched yet.`) - // the poi position is not "enriched" yet. - // Therefore, obtain and typecast the position - const poiPos = GeoJSONUtils.parseGeoJSONFeaturePoint(poi.position) - if (poiPos == null) { - logger.error(`Position ${JSON.stringify(poi.position)} could not be parsed.`) - return null - } + logger.info(`Position of POI with ID ${poi.uid} is not enriched yet.`) + // the poi position is not "enriched" yet. + // Therefore, obtain and typecast the position + const poiPos = GeoJSONUtils.parseGeoJSONFeaturePoint(poi.position) - // get track of POI to enrich it - const track = await database.tracks.getById(poi.trackId) + // get track of POI to enrich it + const track = await database.tracks.getById(poi.trackId) - // then enrich it with the given track - const enrichedPos = await this.enrichPOIPosition(poiPos, track) - if (enrichedPos == null) { - logger.error(`Could not enrich position of POI with ID ${poi.uid}.`) - return null - } - // try to update the poi in the database, now that we have enriched it - await database.pois.update(poi.uid, { position: enrichedPos as unknown as Prisma.InputJsonValue }) + // then enrich it with the given track + const enrichedPos = await this.enrichPOIPosition(poiPos, track) + // try to update the poi in the database, now that we have enriched it + await database.pois.update(poi.uid, { position: enrichedPos as unknown as Prisma.InputJsonValue }) - // and re-calculate poiTrackKm (we do not care that much at this point if the update was successful) - poiTrackKm = GeoJSONUtils.getTrackKm(enrichedPos) - if (poiTrackKm == null) { - logger.error(`Could not get track kilometer of POI position ${JSON.stringify(enrichedPos)}.`) - return null - } - } + // and re-calculate poiTrackKm (we do not care that much at this point if the update was successful) + poiTrackKm = GeoJSONUtils.getTrackKm(enrichedPos) } return poiTrackKm } @@ -138,25 +105,15 @@ export default class POIService { /** * Compute distance of given POI as percentage along the assigned track * @param poi `POI` to compute distance for - * @returns percentage of track distance of `poi`, `null` if computation was not possible + * @returns percentage of track distance of `poi` */ - public static async getPOITrackDistancePercentage(poi: POI): Promise { + public static async getPOITrackDistancePercentage(poi: POI): Promise { // get track length const track = await database.tracks.getById(poi.trackId) - const trackLength = TrackService.getTrackLength(track) - if (trackLength == null) { - logger.error(`Length of track with id ${track.uid} could not be calculated.`) - return null - } - - const poiDistKm = await this.getPOITrackDistanceKm(poi) - if (poiDistKm == null) { - logger.error(`Could not get track kilometer of POI with ID ${poi.uid}.`) - return null - } // compute percentage + const poiDistKm = await this.getPOITrackDistanceKm(poi) return (poiDistKm / trackLength) * 100 } diff --git a/Server/src/services/track.service.ts b/Server/src/services/track.service.ts index 61a59ce..4770aaa 100644 --- a/Server/src/services/track.service.ts +++ b/Server/src/services/track.service.ts @@ -8,6 +8,7 @@ import * as turfMeta from "@turf/meta" import * as turfHelpers from "@turf/helpers" import bearing from "@turf/bearing" import { logger } from "../utils/logger" +import { HTTPError } from "../models/error" /** * Service for track management. This also includes handling the GeoJSON track data. @@ -18,7 +19,7 @@ export default class TrackService { * @param track `GeoJSON.FeatureCollection` of points of track, this has to be ordered * @param start starting location of the track * @param dest destination of track (currently in modelling start and end point do not differentiate) - * @returns `Track` if creation was successful, `null` otherwise + * @returns `Track` if creation was successful */ public static createTrack( track: GeoJSON.FeatureCollection, @@ -38,7 +39,7 @@ export default class TrackService { * @param path `GeoJSON.FeatureCollection` of points of track, this has to be ordered * @param start starting location of the track * @param dest destination of track (currently in modelling start and end point do not differentiate) - * @returns `Track` if creation was successful, `null` otherwise + * @returns `Track` if creation was successful */ public static updateTrack( track_uid: number, @@ -87,15 +88,11 @@ export default class TrackService { * Calculate projected track kilometer for a given position * @param position position to calculate track kilometer for (does not need to be on the track) * @param track `Track` to use for calculation - * @returns track kilometer of `position` projected on `track`, `null` if an error occurs + * @returns track kilometer of `position` projected on `track` */ - public static getPointTrackKm(position: GeoJSON.Feature, track: Track): number | null { + public static getPointTrackKm(position: GeoJSON.Feature, track: Track): number { // get the track kilometer value from projected point const projectedPoint = this.getProjectedPointOnTrack(position, track) - if (projectedPoint == null) { - logger.error(`Could not project position ${JSON.stringify(position)}.`) - return null - } return GeoJSONUtils.getTrackKm(projectedPoint) } @@ -103,20 +100,15 @@ export default class TrackService { * Calculate percentage value for given track kilometer of given track * @param trackKm track kilometer value to convert to percentage * @param track `Track` to use for calculation as reference - * @returns percentage value of `trackKm` regarding `track`, `null` if an error occurs + * @returns percentage value of `trackKm` regarding `track` */ - public static getTrackKmAsPercentage(trackKm: number, track: Track): number | null { + public static getTrackKmAsPercentage(trackKm: number, track: Track): number { // get total track length in kilometers const trackLength = this.getTrackLength(track) - if (trackLength == null) { - logger.error(`Could not compute track length from track with id ${track.uid} to convert track kilometer value.`) - return null - } // check if track kilometer is within bounds if (trackKm < 0 || trackKm > trackLength) { - logger.error(`Expected track kilometer to be between 0 and ${trackLength}, but got ${trackKm}.`) - return null + throw new HTTPError(`Expected track kilometer to be between 0 and ${trackLength}, but got ${trackKm}.`, 500) } // convert to percentage @@ -127,18 +119,14 @@ export default class TrackService { * Project a position onto a track * @param position position to project onto the track * @param track `Track` to project `position` onto - * @returns track point, which is the `position` projected onto `track`, enriched with a track kilometer value, `null` if an error occurs + * @returns track point, which is the `position` projected onto `track`, enriched with a track kilometer value */ public static getProjectedPointOnTrack( position: GeoJSON.Feature, track: Track - ): GeoJSON.Feature | null { + ): GeoJSON.Feature { // converting feature collection of points from track to linestring to project position onto it const trackData = GeoJSONUtils.parseGeoJSONFeatureCollectionPoints(track.data) - if (trackData == null) { - logger.error(`Could not parse track data of track with id ${track.uid}.`) - return null - } const lineStringData: GeoJSON.Feature = turfHelpers.lineString(turfMeta.coordAll(trackData)) // projecting point on linestring of track @@ -147,13 +135,13 @@ export default class TrackService { // for easier access we set the property of track kilometer to the already calculated value if (projectedPoint.properties["location"] == null) { - logger.error( + // this is a slight overreaction as we can still return the projected point, but the track kilometer property will not be accessible + throw new HTTPError( `Turf error: Could not calculate nearest point on line correctly for position ${JSON.stringify( position - )} and for linestring of track with id ${track.uid}.` + )} and for linestring of track with id ${track.uid}.`, + 500 ) - // this is a slight overreaction as we can still return the projected point, but the track kilometer property will not be accessible - return null } GeoJSONUtils.setTrackKm(projectedPoint, projectedPoint.properties["location"]) return projectedPoint @@ -163,31 +151,23 @@ export default class TrackService { * Calculate current heading of track for a given distance / track kilometer * @param track `Track` to get heading for * @param trackKm distance of `track` to get heading for - * @returns current heading (0-359) of `track` at distance `trackKm`, `null` if an error occurs + * @returns current heading (0-359) of `track` at distance `trackKm` */ - public static getTrackHeading(track: Track, trackKm: number): number | null { + public static getTrackHeading(track: Track, trackKm: number): number { // TODO quite inefficient? did not found anything from turf, that could do this in a simple way // TODO: maybe enrich track with bearing as well // validate track kilometer value const trackLength = this.getTrackLength(track) - if (trackLength == null) { - logger.error(`Length of track with id ${track.uid} could not be calculated.`) - return null - } if (trackKm < 0 || trackKm > trackLength) { - logger.error( - `Unexpected value for track kilometer: ${trackKm}. This needs to be more than 0 and less than ${trackLength}.` + throw new HTTPError( + `Unexpected value for track kilometer: ${trackKm}. This needs to be more than 0 and less than ${trackLength}.`, + 500 ) - return null } // get track data const trackData = GeoJSONUtils.parseGeoJSONFeatureCollectionPoints(track.data) - if (trackData == null) { - logger.error(`Could not parse track data of track with id ${track.uid}.`) - return null - } // check if we are right at the beginning of the track (not covered by loop below) if (trackKm == 0) { @@ -198,34 +178,27 @@ export default class TrackService { for (let i = 1; i < trackData.features.length; i++) { const trackPoint = trackData.features[i] const trackPointKm = GeoJSONUtils.getTrackKm(trackPoint) - if (trackPointKm == null) { - logger.error(`Could not access track kilometer value of track point ${i} of track with id ${track.uid}.`) - return null - } - - // actual check if (trackKm <= trackPointKm) { return bearing(trackData.features[i - 1], trackPoint) } } - logger.error( - `Track kilometer value ${trackKm} could not be found while iterating track points of track with id ${track.uid}.` + throw new HTTPError( + `Track kilometer value ${trackKm} could not be found while iterating track points of track with id ${track.uid}.`, + 500 ) - return null } /** * Look for the closest track for a given position * @param position position to search the closest track for - * @returns closest `Track` for `position` or `null` if an error occurs + * @returns closest `Track` for `position` */ - public static async getClosestTrack(position: GeoJSON.Feature): Promise { + public static async getClosestTrack(position: GeoJSON.Feature): Promise { const tracks = await database.tracks.getAll() // there are no tracks at all if (tracks.length == 0) { - logger.warn(`No track was found.`) - return null + throw new HTTPError(`No track was found.`, 404) } // find closest track by iterating @@ -233,10 +206,6 @@ export default class TrackService { let minTrack = -1 for (let i = 0; i < tracks.length; i++) { const trackData = GeoJSONUtils.parseGeoJSONFeatureCollectionPoints(tracks[i].data) - if (trackData == null) { - logger.error(`Could not parse track data of track with id ${tracks[i].uid}.`) - return null - } // converting feature collection of points to linestring to measure distance const lineStringData: GeoJSON.Feature = turfHelpers.lineString(turfMeta.coordAll(trackData)) @@ -260,8 +229,7 @@ export default class TrackService { // check if closest track was found if (minTrack < 0) { - logger.warn(`Somehow no closest track was found even after iterating all existing tracks.`) - return null + throw new HTTPError(`Somehow no closest track was found even after iterating all existing tracks.`, 500) } else { return tracks[minTrack] } @@ -271,37 +239,25 @@ export default class TrackService { * Get total distance for a given track. This is just for easier access as the track kilometer * of the last track point is essentially the length of the track. * @param track `Track` to get the length of - * @returns lenth of `track` in kilometers if possible, `null` otherwise (this could be caused by invalid track data) + * @returns lenth of `track` in kilometers if possible */ - public static getTrackLength(track: Track): number | null { + public static getTrackLength(track: Track): number { // load track data const trackData = GeoJSONUtils.parseGeoJSONFeatureCollectionPoints(track.data) - if (trackData == null) { - logger.error(`Could not parse track data of track with id ${track.uid}.`) - return null - } // get last points track kilometer const trackPointsLength = trackData.features.length const trackLength = GeoJSONUtils.getTrackKm(trackData.features[trackPointsLength - 1]) - if (trackLength == null) { - logger.error(`Could not access track kilometer value of last track point of track with id ${track.uid}.`) - return null - } return trackLength } /** * Wrapper for converting internal presentation of track data as points to a linestring * @param track `Track` to get linestring for - * @returns GeoJSON feature of a linestring. This only contains pure coordinates (i.e. no property values). `null` if an error occured. + * @returns GeoJSON feature of a linestring. This only contains pure coordinates (i.e. no property values). */ - public static getTrackAsLineString(track: Track): GeoJSON.Feature | null { + public static getTrackAsLineString(track: Track): GeoJSON.Feature { const trackData = GeoJSONUtils.parseGeoJSONFeatureCollectionPoints(track.data) - if (trackData == null) { - logger.error(`Could not parse track data of track with id ${track.uid}.`) - return null - } return turfHelpers.lineString(turfMeta.coordAll(trackData)) } } diff --git a/Server/src/services/vehicle.service.ts b/Server/src/services/vehicle.service.ts index e593dad..9f43c78 100644 --- a/Server/src/services/vehicle.service.ts +++ b/Server/src/services/vehicle.service.ts @@ -23,11 +23,11 @@ import { Feature, GeoJsonProperties, Point } from "geojson" export type VehicleData = { vehicle: Vehicle position: GeoJSON.Feature - trackKm?: number - percentagePosition?: number + trackKm: number + percentagePosition: number speed: number heading: number - direction?: -1 | 1 + direction: -1 | 1 } /** Service for vehicle management. */ @@ -107,9 +107,6 @@ export default class VehicleService { let position: Feature | null = null if (trackerLogs.length > 0) { position = GeoJSONUtils.parseGeoJSONFeaturePoint(trackerLogs[0].position) - if (position == null) { - throw new HTTPError(`Could not parse position ${JSON.stringify(trackerLogs[0].position)}.`, 500) - } } // get heading and speed @@ -126,6 +123,7 @@ export default class VehicleService { position = TrackService.getProjectedPointOnTrack(position, track) } else { // compute position and track kilometer as well as percentage value + // TODO: try-catch and fallback (should be done in #169) position = this.computeVehiclePosition(trackerLogs, appLogs, heading, speed, track) } @@ -134,22 +132,12 @@ export default class VehicleService { } const trackKm = GeoJSONUtils.getTrackKm(position) - if (trackKm == null) { - throw new HTTPError(`Could not get track kilometer of position ${JSON.stringify(position)}.`, 500) - } - const percentagePosition = TrackService.getTrackKmAsPercentage(trackKm, track) - if (percentagePosition == null) { - throw new HTTPError( - `Could not compute percentage position for track kilometer ${trackKm} on track with id ${track.uid}.`, - 500 - ) - } return { vehicle, position, trackKm, - percentagePosition, + percentagePosition: TrackService.getTrackKmAsPercentage(trackKm, track), heading, speed, direction: this.computeVehicleTravellingDirection(trackKm, heading, track) @@ -164,7 +152,7 @@ export default class VehicleService { * @param vehicleSpeed heading of vehicle (>= 0), can be obtained with `getVehicleSpeed` * @param track `Track` assigned to the vehicle * @returns computed position of the vehicle based on log data, besides the GeoJSON point there is - * also the track kilometer in the returned GeoJSON properties field (could be null if an error occurs) + * also the track kilometer in the returned GeoJSON properties field */ private static computeVehiclePosition( trackerLogs: Log[], @@ -172,13 +160,8 @@ export default class VehicleService { vehicleHeading: number, vehicleSpeed: number, track: Track - ): GeoJSON.Feature | null { + ): GeoJSON.Feature { const lineStringData = TrackService.getTrackAsLineString(track) - if (lineStringData == null) { - logger.error(`Could not convert track with id ${track.uid} to a linestring.`) - // fallback - return GeoJSONUtils.parseGeoJSONFeaturePoint(trackerLogs[0].position) - } // add a weight to the tracker logs const weightedTrackerLogs = this.addWeightToLogs(trackerLogs, lineStringData) @@ -191,17 +174,17 @@ export default class VehicleService { // now it is unlikely, that weights can be added to the app logs, but we could at least try it logger.warn(`Could not add any weights to tracker logs.`) } else { - const tempWeightedTrackKm = this.weightedLogsToWeightedTrackKm( - weightedTrackerLogs, - vehicleSpeed, - vehicleHeading, - track - ) - if (tempWeightedTrackKm == null) { - // (if this does not work we can still try app logs, though it is also unlikely to work) - logger.warn(`Could not convert weighted tracker logs to weighted track kilometers.`) - } else { + let tempWeightedTrackKm + try { + tempWeightedTrackKm = this.weightedLogsToWeightedTrackKm( + weightedTrackerLogs, + vehicleSpeed, + vehicleHeading, + track + ) weightedTrackKm.push(...tempWeightedTrackKm) + } catch (err) { + logger.warn(`Could not convert weighted tracker logs to weighted track kilometers.`) } } @@ -211,16 +194,16 @@ export default class VehicleService { logger.warn(`Could not add any weights to app logs.`) } else { // try adding them to the list as well - const tempWeightedTrackKm = this.weightedLogsToWeightedTrackKm( - weightedAppLogs, - vehicleSpeed, - vehicleHeading, - track - ) - if (tempWeightedTrackKm == null) { - logger.warn(`Could not convert weighted app logs to weighted track kilometers.`) - } else { + try { + const tempWeightedTrackKm = this.weightedLogsToWeightedTrackKm( + weightedAppLogs, + vehicleSpeed, + vehicleHeading, + track + ) weightedTrackKm.push(...tempWeightedTrackKm) + } catch (err) { + logger.warn(`Could not convert weighted app logs to weighted track kilometers.`) } } @@ -232,10 +215,6 @@ export default class VehicleService { // build average track kilometer value const avgTrackKm = this.averageWeightedTrackKmValues(weightedTrackKm) - if (avgTrackKm == null) { - logger.info(`Could not compute average track kilometer. Perhaps the logs were not recent or accurate enough.`) - return GeoJSONUtils.parseGeoJSONFeaturePoint(trackerLogs[0].position) - } // in the end we just need to turn the track kilometer into a position again const avgPosition = along(lineStringData, avgTrackKm) @@ -259,7 +238,7 @@ export default class VehicleService { ): [number, number][] { // just need to check this for the next step if (weightedLogs.length === 0) { - return [] + throw new HTTPError(`Expected at least one log for converting to track kilometer`, 500) } // vehicle should be the same for all logs @@ -277,8 +256,10 @@ export default class VehicleService { } // get last known track kilometer - const lastTrackKm = this.getTrackKmFromLog(weightedLogs[i][0], track) - if (lastTrackKm == null) { + let lastTrackKm + try { + lastTrackKm = this.getTrackKmFromLog(weightedLogs[i][0], track) + } catch (err) { logger.warn(`Could not compute last track kilometer for last log with id ${weightedLogs[i][0].uid}.`) continue } @@ -299,26 +280,14 @@ export default class VehicleService { * Compute track kilometer for a position of a given log * @param log `Log` to compute track kilometer for * @param track related track of `log` - * @returns track kilometer value for `log`, `null` if an error occurs + * @returns track kilometer value for `log` */ - private static getTrackKmFromLog(log: Log, track: Track): number | null { + private static getTrackKmFromLog(log: Log, track: Track): number { // get position from log const logPosition = GeoJSONUtils.parseGeoJSONFeaturePoint(log.position) - if (logPosition == null) { - logger.error(`Position ${JSON.stringify(log.position)} could not be parsed.`) - return null - } // compute track kilometer for this position - const logTrackKm = TrackService.getPointTrackKm(logPosition, track) - if (logTrackKm == null) { - logger.error( - `Could not compute track kilometer for position ${JSON.stringify(logPosition)} and track with id ${track.uid}.` - ) - return null - } - - return logTrackKm + return TrackService.getPointTrackKm(logPosition, track) } /** @@ -350,8 +319,10 @@ export default class VehicleService { timeWeight = timeWeight > 0 ? timeWeight : 0 // get position from log - const logPosition = GeoJSONUtils.parseGeoJSONFeaturePoint(logs[i].position) - if (logPosition == null) { + let logPosition + try { + logPosition = GeoJSONUtils.parseGeoJSONFeaturePoint(logs[i].position) + } catch (err) { logger.warn(`Position ${JSON.stringify(logs[i].position)} could not be parsed.`) continue } @@ -378,16 +349,18 @@ export default class VehicleService { /** * Build average of weighted track kilometer values * @param weightedTrackKms list of track kilometer values (first) with their related positive weight (second) - * @returns averaged track kilometer value of `weightedTrackKms`, null if an error occurs + * @returns averaged track kilometer value of `weightedTrackKms` */ - private static averageWeightedTrackKmValues(weightedTrackKms: [number, number][]): number | null { + private static averageWeightedTrackKmValues(weightedTrackKms: [number, number][]): number { // calculate total of all weights let weightSum = 0 for (let i = 0; i < weightedTrackKms.length; i++) { // check if weight is negative (this could result in unwanted behaviour) if (weightedTrackKms[i][1] < 0) { - logger.error(`Expected positive weights for track kilometer values only, but got ${weightedTrackKms[i][1]}.`) - return null + throw new HTTPError( + `Expected positive weights for track kilometer values only, but got ${weightedTrackKms[i][1]}.`, + 500 + ) } weightSum += weightedTrackKms[i][1] @@ -395,8 +368,10 @@ export default class VehicleService { // avoid divide by zero if (weightSum == 0) { - logger.error(`All weights for track kilometers were 0`) - return null + throw new HTTPError( + `Expected at least one weight to be greater than 0 while computing average track kilometer.`, + 500 + ) } // normalizing weights and averaging track kilometer values @@ -441,8 +416,8 @@ export default class VehicleService { /** * Determine travelling direction of a vehicle related to its track (either "forward" or "backward") - * @param vehicleHeading heading of vehicle (0-359), can be obtained with `getVehicleHeading` * @param trackKm track kilometer at which the vehicle currently is (can be found with `VehicleService.getVehicleTrackDistanceKm`) + * @param vehicleHeading heading of vehicle (0-359), can be obtained with `getVehicleHeading` * @param track track to compute the direction of a vehicle with * @returns 1 or -1 if the vehicle is heading towards the end and start of the track respectively */ @@ -450,10 +425,6 @@ export default class VehicleService { // TODO: needs improvements (probably with #118 together), should be independent from track kilometer (position needs to be computed for that) // compute track heading const trackBearing = TrackService.getTrackHeading(track, trackKm) - // TODO - if (trackBearing == null) { - throw new HTTPError(`Could not compute heading of track with id ${track.uid} at track kilometer ${trackKm}.`, 500) - } // TODO: maybe give this a buffer of uncertainty if (vehicleHeading - trackBearing < 90 || vehicleHeading - trackBearing > -90) { return 1