Package: openautomatumdronedata
MotivationThis package provides an object-oriented structure for loading and analyzing AUTOMATUM DATA datasets. It is intended to enable the rapid use of the dataset in research and development. In addition, a web server-based visualization is provided to give an instant overview of the dataset.Download the the dataset fromhttps://www.automatum-data.comDocumentation of this package is available under:https://openautomatumdronedata.rtfd.ioA video with annotated objects can be foundhere.InstallationTheopenautomatumdronedata-Utility is a standard PIP package which can be installed as any other PIP package withpip install openautomatumdronedataor depending on your machinepip3 install openautomatumdronedataIn addition, the package can also be installed manually, e.g. by placing the sources in your project folder.UpgradeIf you haveopenautomatumdronedataalready installed you can get the latest version withpip install --upgrade openautomatumdronedataChange HistorySince we update our dataset to keep track with the needs of the user. There are also updates in this library needed.In the following table you find which pip package version is compatible with which version of the dataset. You can use pip to directly download a specifc version. The latest version of the dataset is always available on our homepage.dataset versionopen.automatum.data versionchangesv1.0<= 0.2.1v3.0>= 0.4.0Object to lane assigment,  Object Relations are directly included in the data, Add TTC, TTH, Distance to left and right lane markingData StructureThe Automatum DATA datasets are strucktured in singlerecordingswith a length of appx. 10 to 18 minutes each. Eachrecordingwas captured on a so calledlocation.That means there are usually severalrecordingson eachlocationand therecordingsshare the common information of thelocationlike thestaticWorld (XODR)and the reference point.Eachrecordingitself comes in one folder with the following files:dynamicWorld.jsonwhich contains the dynamic behavior of the objects such as cars, trucks, etc.staticWorld.xodrwhich contains road geometry in theOpenDRIVEformat.recording_name.htmlwhich contains an overview of therecordingwith some basic metadata.dynamicWorld.jsonVariableDescriptionUTM-RferencepointReference point in the world coordinate system in UTM-Format. This reference point is the center of the coordinate system for the given position. The points is given as a tuple of (x [m], y [m], letter, number)WGS84-CoordinatesReferecne point in WGS82 format.Recording nameUnique recording name: Streettype_Streetname_LocationName_UUIDUUIDUnique UUID of the recordingReleaseRelease version of the dataset.Calculation versionDict that shows all versions of the the pipeline used to process the recording.Video Informationfps and count of containing frames of the recordingContact an Licencing InformationFurther contact and licence information of the given recordingObject dataThe actual objects data which is described in this documentation.Whereby, this Python package has the following objectives:Easy access to the information contained indynamicWorld.jsonandstaticWorld.xodr.Avoid effort by writing a parser for the provided data.Visualize the data easily in a webbrowserHow to start codingThe entry point for accessing a dataset is to load a dataset using theDroneDatasetclass. You can copy all code snipets one by one and run the code. All snipets together can be found also on thehello_world.pyprovided with the sources.fromopenautomatumdronedata.datasetimportdroneDatasetimportosimportnumpyasnppath_to_dataset_folder=os.path.abspath("datasets/hw-a9-stammhamm-015-39f0066a-28f0-4a68-b4e8-5d5024720c4e")dataset=droneDataset(path_to_dataset_folder)this command reads thedynamicWorld.jsonandstaticWorld.xodrand translates the complete data in to an object-oriented structure. This allows all further data accesses to be made with the instance of thedrone datasetclass. Whereby, thedrone datasetclass holds the following two subclasses:Dynamic WorldThe dynamic world holds all informations about dynamic objects (cars, trucks, vans) in the dataset and handles the access to objects over the recording time.You can access the dynamic world bydynWorld=dataset.dynWorldThe dynamic world provides you the following variables:VariableDescriptionUTM-RferencepointReference point in the world coordinate system in UTM-Format. This reference point is the center of the coordinate system for the given position. The points is given as a tuple of (x [m], y [m], letter, number)UUIDUnique UUID of the recordingtypeType of the object as stringfpsfps of the recordingdelta_tSample time of the recording. [s]frame_countTotal number of frames of the recording.maxTimeTotal duration of the recording. [s]DrivenDistanceInMeterTotal driven distance of all object in the recording. [m]MedianDrivenDistanceInMeterMedian driven distance of the objects or track length.  [m]ExampledynWorld=dataset.dynWorldprint(dynWorld.UUID)print(dynWorld.frame_count)print(dynWorld.fps)print(dynWorld.delta_t)print(dynWorld.utm_referene_point)print(dynWorld.maxTime)print(dynWorld.DrivenDistanceInMeter)print(dynWorld.MedianDrivenDistanceInMeter)print(dynWorld.type)#print(dynWorld.dynamicObjects) # Possible but not recommended. Use further discussed functions.Dynamic objectsObjects are represented by a set of type specific class:carObjecttruckObjectvanObjectcarWithTrailerObjectmotorcycleObjectFor evaluating the type of object, you can use the calls type or thetypemember variable which gives you a string.All these classes inherited from the base classdynamicObject, which implements the following features. This means you can use all the following features for all object type specific classes.Per Object the following information are available as scalar:VariableDescriptionUUIDUnique UUID of the objectlengthLength of the object [m]widthWidth of the object [m]delta_tTime difference between two data points (equal at all objects and with in thedynamicObject)Depending on your customized release, the channels per object can differ.
Documentation over all available channels can be found in the following table:VariableDescriptionx_vecx-Position of the assumed center of gravity of the object in the local coordinate systemy_vecy-Position of the assumed center of gravity of the object in the local coordinate systemvx_vecVelocity in x-directionin the vehicle coordinate systemvy_vecVelocity in y-directionin the vehicle coordinate systemvx_vec_worldVelocity in x-directionin the world coordinate systemvy_vec_worldVelocity in y-directionin the world coordinate systemax_vecAcceleration of the object in x-directionin the vehicle coordinate systemay_vecAcceleration of the object in y-directionin the vehicle coordinate systemjerk_x_vecJerk of the object in X-directionin the vehicle coordinate system. Only if available in your dataset, if not the value is Nonejerk_y_vecJerk of the object in Y-directionin the vehicle coordinate system. Only if available in your dataset, if not the value is NonetimeVector of the timestamp in the dataset recording for the mention valuespsi_vecVector of orientation of objects.curvature_vecDriving Curvature of the object. Only if available in your dataset, if not the value is Nonelane_id_vecVector of thelane_idon which the vehicle drives according to the static world described in the xodr, for details see chapterObject to lane assignment (OTLA)road_id_vecVector of theroad_idon which the vehicle drives according to the static world described in the xodr, for details see chapterObject to lane assignment (OTLA)road_type_listList of strings that describes the road type at every time step of the object. Only if available in your dataset, if not the value is Nonelane_change_flag_vecVector of bool values, whereby True means that a lane change occurred. In newer Datasets a vector of Integers. Whereby, -1 means lane change to the left, +1 means lane change to the right and 0 means no lane change, for details see chapterObject to lane assignment (OTLA)distance_left_lane_markingDistance from the center of gravity of a object (defined byx_vec,y_vec) to the left lane marking, for details see chapterDistance to lane markingsdistance_right_lane_markingDistance from the center of gravity of a object (defined byx_vec,y_vec) to the right lane marking, for details see chapterDistance to lane markingsobject_relation_dict_listList of dicts, whereby every dict describes the object relation at the current time step, for details see chapterObject Relationstth_dict_vecList of dicts, whereby every dict describes thetthto the related objects at the current time step, for details see chapterTTC / TTHttc_dict_vecList of dicts, whereby every dict describes thettcto the related objects at the current time step, for details see chapterTTC / TTHlat_dist_dict_vecList of dicts, whereby every dict describes thelateral distanceto the related objects at the current time step, for details see chapterLateral and Longitudinal Position between Objectslong_dist_dict_vecList of dicts, whereby every dict describes thelongitudinal distanceto the related objects at the current time step, for details see chapterLateral and Longitudinal Position between ObjectsExampledynObjectList=dynWorld.get_list_of_dynamic_objects_for_specific_time(1.0)dynObject=dynObjectList[-1]print(dynObject.x_vec)print(dynObject.y_vec)print(dynObject.vx_vec)print(dynObject.vy_vec)print(dynObject.psi_vec)print(dynObject.ax_vec)print(dynObject.ay_vec)print(dynObject.length)print(dynObject.width)print(dynObject.time)print(dynObject.UUID)print(dynObject.delta_t)To keep the size of the dataset files as small as possible the data of the objects is only provided for the time intervale where the object is visitable in the video recording. Therefore, the first element in the time vector is the entry time and the last element the time of exit.Dynamic objects utilitiesTo allow an easy access to objects, the following methods are implemented.Total objects includedReturns the total number of included objectslen(dynWorld)Get all objects at a specific timeGives you a list of all objects which are included in the first second of the recording.dynObjectList=dynWorld.get_list_of_dynamic_objects_for_specific_time(1.0)Get specific timestamps of an objectprint(dynObject.get_first_time())# Returns the time the object occurs the first timeprint(dynObject.get_last_time())# Returns the time the object occurs the last timeprint(dynObject.is_visible_at(10))# Checks if the object is visible at the given timeConvert a time step to a vector indexTo access the object vector based on a defined time step. You can use the functionnext_index_of_specific_timeto convert a given time into the index of the data vectors at that given time, liketime_vec=np.arange(dynObject.get_first_time(),dynObject.get_last_time(),dynObject.delta_t)# Print positionsx_vec=dynObject.x_vecy_vec=dynObject.y_vecfortimeintime_vec:idx=dynObject.get_object_relation_for_defined_time(time)print("At time%0.2fthe vehicle is at position%0.2f,%0.2f"%(time,x_vec[idx],y_vec[idx]))Object to lane assignment (OTLA)The object-lane mapping is calculated for each object in each time step with the corresponding lane ID.The x and y position of the object is used as a reference. Thus, the time stamp at which the lane ID changes is when that position passes over the lane marker.The lane ID / road ID is defined by the static world ofxodr, for more details see the static world chapter. Where all lane IDs with the same sign (e.g. positive) belong to one driving direction. Absolutely low IDs belong to a lane closer to the center of the road (between driving directions). Note that a lane ID does not have to start at 0, as there may also be an unnavigable lane near the center of the road.To access the Lane ID use:print(dynObject.lane_id_vec)print(dynObject.road_id_vec)Distance to lane markingFor each object the current distances were calculated to the next left and right lane marking from ego view.dlanddrare defined as the orthogonal distance from the center of gravity of the car to the next lane marking.Object RelationsThe object relation describing the relative position between object based on a view of one defined vehicle:The object relation are defined as dict of <relation name>:<UUID of other object>. If an object has no relation to an other then the element is still in the dict, however, the value isNone.[{# Time step 0'front_ego':None,'behind_ego':'4bc73813-79bc-413c-87ec-e9048514079f','front_left':None,'behind_left':None,'front_right':None,'behind_right':'0df4550c-a21b-4c38-bee3-e03ef4d59afc',},{#Time step 1'front_ego':None,'behind_ego':'4bc73813-79bc-413c-87ec-e9048514079f','front_left':None,'behind_left':None,'front_right':None,'behind_right':'0df4550c-a21b-4c38-bee3-e03ef4d59afc',}...]Therefore, the access is as followedobject_relation_dict=dynObject.object_relation_dict_list[0]print(object_relation_dict["front_ego"])print(object_relation_dict["behind_ego"])print(object_relation_dict["front_left"])print(object_relation_dict["behind_left"])print(object_relation_dict["front_right"])print(object_relation_dict["behind_right"])Lateral and Longitudinal Position between ObjectsSince the datasets consists also roads with a curvature, objects are not aligned to the coordinate system. Therefore, the lateral and longitudinal distance to the sounding objects in included in new datasets:[{# Time step 0'front_ego':None,'behind_ego':'11.3453242342','front_left':None,'behind_left':None,'front_right':None,'behind_right':'12.23107814',},{#Time step 1'front_ego':None,'behind_ego':'11.238790123','front_left':None,'behind_left':None,'front_right':None,'behind_right':'12.239001724',}...]If the data is not included, the lateral and longitudinal distance can be calculated by the functionget_lat_and_long.dynObject2=dynObjectList[1]long_distance,lat_distance=dynObject.get_lat_and_long(1.0,dynObject2)print(long_distance,lat_distance)TTC and TTHFor each object the currentTTCandTTHis calculatedonly to every infrontdriving object.The distancedas base of all calculations is defined as the closest distance of both vehicle centers'd. To compensate for the vehicle length,l/2of each vehicle was substracted from'd.TTCTTCis calculated asd/velocity difference.If the front car is moving faster than the ego vehicle, a collision is impossible an theTTCis marked as-1.TTHTTHis calculated asd/velocity ego.Static WorldWe implemented a basic parser forxodrwith some additional functionality. This parser stores the relevant information in the so called Static World. As the Dynamic World the Static World can be accessed by the dataset class:statWorld=dataset.statWorldThe Static World consist of a hierarchically structure of different classed to represents thexodr. Further information ofxodrcan be foundhere.We highly recommend to get a basic understanding ofxodrif lane related information are used.To get a fast and good view of anxodrwe highly recommend the easyOpenDriveViewerto open and analyze thexodrfiles.VisualizationThis package provides an integrated visualization of the dataset via a web server realized by bokeh.If you installed the package via pip simply starte the visualization by typing:automatum_visTo start the visualization manually execute thestart_bokeh.pyscript form thepackage source.To open a dataset simple copy the absolute path of the dataset folder into the text filed on the top of the webpage.
By clicking load the dataset will be loaded and visualized. Give it some seconds to load....After loading a dataset you should get a comparable view:If you scroll down you find the panel where you can control a live view of the data:With Play/Pause you start/stop the animation.With the arrows bellow you can step a single frame.The slider allows to change the playback speed.The two check boxes allow to show additional data.The "Jump to time" box allows it to jup directly to a picture of interest.Show object relations prints all present relation to each object:Show distance lane markings prints the current orthogonal distances of each car to the current lane:To get a lange change, please zoom into the overview picture and hover to a red dot which is indicating a lane change:The info box is telling you the UUID of the object which is performing the lane change and also the time step when this is happening. With the time step you can use the "Jump" box to show this time step in the animation.Complete ExampleHere you find the complete example of all code snipets from above:fromopenautomatumdronedata.datasetimportdroneDatasetimportosimportnumpyasnppath_to_dataset_folder=os.path.abspath("datasets/hw-a9-stammhamm-015-39f0066a-28f0-4a68-b4e8-5d5024720c4e")dataset=droneDataset(path_to_dataset_folder)dynWorld=dataset.dynWorldprint(dynWorld.UUID)print(dynWorld.frame_count)print(dynWorld.fps)print(dynWorld.delta_t)print(dynWorld.utm_referene_point)print(dynWorld.maxTime)print(dynWorld.DrivenDistanceInMeter)print(dynWorld.MedianDrivenDistanceInMeter)#print(dynWorld.dynamicObjects) # Possible but not recommended. Use further discussed functions.dynObjectList=dynWorld.get_list_of_dynamic_objects_for_specific_time(1.0)dynObject=dynObjectList[-1]print(dynObject.x_vec)print(dynObject.y_vec)print(dynObject.vx_vec)print(dynObject.vy_vec)print(dynObject.psi_vec)print(dynObject.ax_vec)print(dynObject.ay_vec)print(dynObject.length)print(dynObject.width)print(dynObject.time)print(dynObject.UUID)print(dynObject.delta_t)len(dynWorld)# Returns the number of included objectdynObjectList=dynWorld.get_list_of_dynamic_objects_for_specific_time(1.0)print(dynObject.get_first_time())# Returns the time the object occurs the first timeprint(dynObject.get_last_time())# Returns the time the object occurs the last timeprint(dynObject.is_visible_at(10))# Checks if the object is visible at the given timetime_vec=np.arange(dynObject.get_first_time(),dynObject.get_last_time(),dynObject.delta_t)# Print positionsx_vec=dynObject.x_vecy_vec=dynObject.y_vecfortimeintime_vec:idx=dynObject.next_index_of_specific_time(time)print("At time%0.2fthe vehicle is at position%0.2f,%0.2f"%(time,x_vec[idx],y_vec[idx]))print(dynObject.lane_id_vec)print(dynObject.road_id_vec)object_relation_dict=dynObject.object_relation_dict_list[0]print(object_relation_dict["front_ego"])print(object_relation_dict["behind_ego"])print(object_relation_dict["front_left"])print(object_relation_dict["behind_left"])print(object_relation_dict["front_right"])print(object_relation_dict["behind_right"])dynObject2=dynObjectList[1]long_distance,lat_distance=dynObject.get_lat_and_long(1.0,dynObject2)print(long_distance,lat_distance)statWorld=dataset.statWorldDisclamerThe implementation ofxodrvia theautomatum_viscan show artefacts or road elements are displayed incorrectly. Thexodritself is generated using IPG'sCarMakertool and is fully represented. Also not all road elements of the standard are implemented to be shown.