sumolib.output.convert.trj

  1# Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
  2# Copyright (C) 2013-2026 German Aerospace Center (DLR) and others.
  3# This program and the accompanying materials are made available under the
  4# terms of the Eclipse Public License 2.0 which is available at
  5# https://www.eclipse.org/legal/epl-2.0/
  6# This Source Code may also be made available under the following Secondary
  7# Licenses when the conditions for such availability set forth in the Eclipse
  8# Public License 2.0 are satisfied: GNU General Public License, version 2
  9# or later which is available at
 10# https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
 11# SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
 12
 13# @file    trj.py
 14# @author  Mirko Barthauer
 15# @date    2021-03-31
 16
 17"""
 18This module includes functions for converting SUMO's fcd-output into
 19data files read by SSAM.
 20See the SSAM TRJ standard at
 21https://github.com/OSADP/SSAM/blob/master/Documentation/SSAM%20File%20Format%20v1.04.pdf
 22https://github.com/OSADP/SSAM/blob/master/Documentation/Open%20Source%20SSAM%20File%20Format%20v3.0.pdf
 23"""
 24
 25import sys
 26import struct
 27import math
 28
 29
 30def fcd2trj(inpFCD, outSTRM, further):
 31    endian = b'B' if sys.byteorder == "big" else b'L'
 32
 33    # write FORMAT block
 34    outSTRM.write(struct.pack("=c", chr(0).encode()))
 35    outSTRM.write(struct.pack("=c", endian))
 36    outSTRM.write(struct.pack("f", 3.0))
 37    outSTRM.write(struct.pack("=c", chr(1).encode()))
 38
 39    # write DIMENSIONS block
 40    outSTRM.write(struct.pack("=c", chr(1).encode()))
 41    outSTRM.write(struct.pack("=c", chr(1).encode()))
 42    outSTRM.write(struct.pack("=f", 1.0))
 43    outSTRM.write(struct.pack("=i", int(further["bbox"][0][0])))
 44    outSTRM.write(struct.pack("=i", int(further["bbox"][0][1])))
 45    outSTRM.write(struct.pack("=i", int(further["bbox"][1][0])))
 46    outSTRM.write(struct.pack("=i", int(further["bbox"][1][1])))
 47
 48    # go through fcd output and encode links and vehicle IDs
 49    edgeDict = {}
 50    trafficPartDict = {}
 51    prevSpeed = {}
 52    edgeCounter = 0
 53    trafficPartCounter = 0
 54
 55    for timestep in inpFCD:
 56        # write TIMESTEP block
 57        outSTRM.write(struct.pack("=c", chr(2).encode()))
 58        outSTRM.write(struct.pack("=f", timestep.time))
 59
 60        for v in timestep.vehicle:
 61            speed = float(v.speed)
 62            if v.id not in trafficPartDict:
 63                trafficPartDict[v.id] = trafficPartCounter
 64                trafficPartCounter += 1
 65                prevSpeed[v.id] = speed
 66            numericID = trafficPartDict[v.id]
 67            accel = (speed - prevSpeed[v.id])/further["timestep"]
 68            if "_" not in v.lane:
 69                edge = v.lane
 70                laneIndex = 0
 71            else:
 72                edge, laneIndex = v.lane.rsplit("_", 1)
 73                laneIndex = min(int(laneIndex), 9)
 74
 75            if edge not in edgeDict:
 76                edgeDict[edge] = edgeCounter
 77                edgeCounter += 1
 78            edgeNumericID = edgeDict[edge]
 79
 80            # calculated values
 81            x = float(v.x)
 82            y = float(v.y)
 83            z = float(v.z)
 84            angle = float(v.angle) * math.pi/180.
 85            slope = float(v.slope) * math.pi/180.
 86            rearX = x - math.sin(angle) * further["length"]
 87            rearY = y - math.cos(angle) * further["length"]
 88            rearZ = z - math.sin(slope) * further["length"]
 89            # write VEHICLE block
 90            outSTRM.write(struct.pack("=c", chr(3).encode()))
 91            outSTRM.write(struct.pack("=i", numericID))
 92            outSTRM.write(struct.pack("=i", edgeNumericID))
 93            outSTRM.write(struct.pack("=c", chr(laneIndex).encode()))
 94            outSTRM.write(struct.pack("=f", x))
 95            outSTRM.write(struct.pack("=f", y))
 96            outSTRM.write(struct.pack("=f", rearX))
 97            outSTRM.write(struct.pack("=f", rearY))
 98            outSTRM.write(struct.pack("=f", further["length"]))
 99            outSTRM.write(struct.pack("=f", further["width"]))
100            outSTRM.write(struct.pack("=f", speed))
101            outSTRM.write(struct.pack("=f", accel))
102            outSTRM.write(struct.pack("=f", z))  # front z coord
103            outSTRM.write(struct.pack("=f", rearZ))  # back z coord
104            # remember value for next timestep
105            prevSpeed[numericID] = speed
def fcd2trj(inpFCD, outSTRM, further):
 31def fcd2trj(inpFCD, outSTRM, further):
 32    endian = b'B' if sys.byteorder == "big" else b'L'
 33
 34    # write FORMAT block
 35    outSTRM.write(struct.pack("=c", chr(0).encode()))
 36    outSTRM.write(struct.pack("=c", endian))
 37    outSTRM.write(struct.pack("f", 3.0))
 38    outSTRM.write(struct.pack("=c", chr(1).encode()))
 39
 40    # write DIMENSIONS block
 41    outSTRM.write(struct.pack("=c", chr(1).encode()))
 42    outSTRM.write(struct.pack("=c", chr(1).encode()))
 43    outSTRM.write(struct.pack("=f", 1.0))
 44    outSTRM.write(struct.pack("=i", int(further["bbox"][0][0])))
 45    outSTRM.write(struct.pack("=i", int(further["bbox"][0][1])))
 46    outSTRM.write(struct.pack("=i", int(further["bbox"][1][0])))
 47    outSTRM.write(struct.pack("=i", int(further["bbox"][1][1])))
 48
 49    # go through fcd output and encode links and vehicle IDs
 50    edgeDict = {}
 51    trafficPartDict = {}
 52    prevSpeed = {}
 53    edgeCounter = 0
 54    trafficPartCounter = 0
 55
 56    for timestep in inpFCD:
 57        # write TIMESTEP block
 58        outSTRM.write(struct.pack("=c", chr(2).encode()))
 59        outSTRM.write(struct.pack("=f", timestep.time))
 60
 61        for v in timestep.vehicle:
 62            speed = float(v.speed)
 63            if v.id not in trafficPartDict:
 64                trafficPartDict[v.id] = trafficPartCounter
 65                trafficPartCounter += 1
 66                prevSpeed[v.id] = speed
 67            numericID = trafficPartDict[v.id]
 68            accel = (speed - prevSpeed[v.id])/further["timestep"]
 69            if "_" not in v.lane:
 70                edge = v.lane
 71                laneIndex = 0
 72            else:
 73                edge, laneIndex = v.lane.rsplit("_", 1)
 74                laneIndex = min(int(laneIndex), 9)
 75
 76            if edge not in edgeDict:
 77                edgeDict[edge] = edgeCounter
 78                edgeCounter += 1
 79            edgeNumericID = edgeDict[edge]
 80
 81            # calculated values
 82            x = float(v.x)
 83            y = float(v.y)
 84            z = float(v.z)
 85            angle = float(v.angle) * math.pi/180.
 86            slope = float(v.slope) * math.pi/180.
 87            rearX = x - math.sin(angle) * further["length"]
 88            rearY = y - math.cos(angle) * further["length"]
 89            rearZ = z - math.sin(slope) * further["length"]
 90            # write VEHICLE block
 91            outSTRM.write(struct.pack("=c", chr(3).encode()))
 92            outSTRM.write(struct.pack("=i", numericID))
 93            outSTRM.write(struct.pack("=i", edgeNumericID))
 94            outSTRM.write(struct.pack("=c", chr(laneIndex).encode()))
 95            outSTRM.write(struct.pack("=f", x))
 96            outSTRM.write(struct.pack("=f", y))
 97            outSTRM.write(struct.pack("=f", rearX))
 98            outSTRM.write(struct.pack("=f", rearY))
 99            outSTRM.write(struct.pack("=f", further["length"]))
100            outSTRM.write(struct.pack("=f", further["width"]))
101            outSTRM.write(struct.pack("=f", speed))
102            outSTRM.write(struct.pack("=f", accel))
103            outSTRM.write(struct.pack("=f", z))  # front z coord
104            outSTRM.write(struct.pack("=f", rearZ))  # back z coord
105            # remember value for next timestep
106            prevSpeed[numericID] = speed