def defineRoadAttribution(): localRoadAttribution = road_attribution_pb2.RoadAttributionCategory() # We need to cover 2 HERE Maplet aspects here: # 1. Road Surface Markings # 2. Lane Marking Observations # for that reason, we only generate the category envelope and the two frames for the 2 topics here # and we dig deeper in separate functions. localCategoryEnvelope = base_pb2.CategoryEnvelope() localRoadAttribution.envelope.CopyFrom(localCategoryEnvelope) # now we add the lanes numOfLaneBoundaryDefinitionsPerHEREMaplet = config.getConfig_Int( "run_config", "numOfLaneMarkingObservations_perHEREMaplet") iterator = int(0) while iterator < numOfLaneBoundaryDefinitionsPerHEREMaplet: localRoadAttribution.lane_boundary.extend( [defineAnIndividualLaneBoundary()]) iterator += 1 # now we add the road surface markings numOfRoadSurfaceMarkings = config.getConfig_Int( "run_config", "numOfSurfaceMarkings_perHEREMaplet") iterator = int(0) while iterator < numOfRoadSurfaceMarkings: localRoadAttribution.surface_marking.extend( [defineAnIndividualSurfaceMarking()]) iterator += 1 return localRoadAttribution
def DefineCompilerVersion(): localVersion = base_pb2.Version() localVersion.major.value = config.getConfig_Int( "map_identification", "map_compiler_version_major") localVersion.minor.value = config.getConfig_Int( "map_identification", "map_compiler_version_minor") localVersion.patch.value = config.getConfig_Int( "map_identification", "map_compiler_version_patch") return localVersion
def DefineSENSORISVersion(): ############### 1 ############### # we locally define our own version message and append it to the SENSORIS message # the way, the version message is valid for non-repeated messages localVersion = base_pb2.Version() localVersion.major.value = config.getConfig_Int("general", "major_version") localVersion.minor.value = config.getConfig_Int("general", "minor_version") localVersion.patch.value = config.getConfig_Int("general", "patch_version") localVersion.name.value = config.getConfig_Str("general", "version_name") return localVersion
def DefineSENSORISDataMessage(): # A SENSORIS DataMessage has some main fields, these are # #1 (envelope) # #2 (event group) # #3 (event relation) # #4 (event source) # these elements will be generated here # please check deeper going python files for deeper insights # generating the data message container itself localDataMessage = data_pb2.DataMessage() # putting the local data message together # see, that the envelope is a non-repeated value, whereas the others are repeated messages localDataMessage.envelope.CopyFrom( define_Envelope.defineSENSORISEnvelope()) iterator = int(0) while iterator < config.getConfig_Int("run_config", "numOfHEREMaplets"): localDataMessage.event_group.extend( [define_EventGroup.defineSENSORISEventGroup()]) iterator += 1 #localDataMessage.event_relation.extend([define_EventRelation.defineSENSORISEventRelation()]) #localDataMessage.event_source.extend([define_EventSource.defineSENSORISEventSource()]) return localDataMessage
def defineSENSORISEnvelope(): # the Envelope consists for three elements # #1 (identifiers) # #2 (vehicle dimensions) # #3 (field resolution override) // not needed for HERE Maplet # #4 (map identification) # generating a local container for the content localEnvelope = data_pb2.DataMessage.Envelope() localIdentifyer = base_pb2.MessageEnvelopeIds() localIdentifyer.session_id.value = str(uuid.uuid4()) localIdentifyer.message_id.value = config.getConfig_Int( "general_message_config", "message_id") localIdentifyer.vehicle_fleet_id.value = str(uuid.uuid4()) localIdentifyer.vehicle_id.value = str(uuid.uuid4()) localIdentifyer.driver_id.value = str(uuid.uuid4()) localIdentifyer.job_request_id.append(str(uuid.uuid4())) localIdentifyer.job_submitter_id.value = str(uuid.uuid4()) localEnvelope.ids.CopyFrom(localIdentifyer) localVehicleDimensions = data_pb2.DataMessage.Envelope.VehicleDimensions() localVehicleDimensions.length_to_front.value = config.getConfig_Int( "vehicle_dimensions", "vehicle_dimension_x_forward") localVehicleDimensions.length_to_back.value = config.getConfig_Int( "vehicle_dimensions", "vehicle_dimension_x_backward") localVehicleDimensions.length_to_left.value = config.getConfig_Int( "vehicle_dimensions", "vehicle_dimension_y_left") localVehicleDimensions.length_to_right.value = config.getConfig_Int( "vehicle_dimensions", "vehicle_dimension_y_right") localVehicleDimensions.length_to_top.value = config.getConfig_Int( "vehicle_dimensions", "vehicle_dimension_z_up") localVehicleDimensions.length_to_ground.value = config.getConfig_Int( "vehicle_dimensions", "vehicle_dimension_z_down") localEnvelope.vehicle_dimensions.CopyFrom(localVehicleDimensions) # this implementation is highly inefficient. I cannot recoomend to use it # you can simply avoid this, if you take the resolutions defined in the comments above your attributes #localFieldResolutionOverride = data_pb2.DataMessage.Envelope.FieldResolutionOverride() #localFieldResolutionOverride.path.value = "nice/path/to/attribute/with/different/scale/factor/than/defined/in/comment" #localFieldResolutionOverride.factor.value = 3 #translates into mulitplicator by 10-times-3 = 1,000 #localEnvelope.field_resolution_override.extend([localFieldResolutionOverride]) # provinding some information on used map localMapIdentification = data_pb2.DataMessage.Envelope.MapIdentification() localMapIdentification.map_source_identification.map_source_name.value = config.getConfig_Str( "map_identification", "map_source_name") localMapIdentification.map_source_identification.map_source_version.CopyFrom( define_Version.DefineMapVersion()) localMapIdentification.map_compiler_identification.map_compiler_name.value = config.getConfig_Str( "map_identification", "map_compiler_name") localMapIdentification.map_compiler_identification.map_compiler_version.CopyFrom( define_Version.DefineCompilerVersion()) localMapIdentification.map_format = data_pb2.DataMessage.Envelope.MapIdentification.NDS localEnvelope.map_identification.CopyFrom(localMapIdentification) return localEnvelope
def defineObjectDetectionCategory(): localObjectDetection = object_detection_pb2.ObjectDetectionCategory() numOfPLOs = config.getConfig_Int("run_config", "numOfPLOs_perHEREMaplet") numOfConesAndBarrels = config.getConfig_Int( "run_config", "numOfConesBarrels_perHEREMaplet") iterator = int(0) while iterator < numOfPLOs: localObjectDetection.static_object_detection.extend( [definePoleLikeObjects()]) iterator += 1 iterator = int(0) while iterator < numOfConesAndBarrels: localObjectDetection.static_object_detection.extend( [defineConesAndBarrels()]) iterator += 1 return localObjectDetection
def defineIntersectionAttribution(): localTrafficSignal = intersection_attribution_pb2.IntersectionAttributionCategory() # here we define the mandatory event envelope for the localization # There is a little bug in the Sensoris spec, as no content is defined in the category envelope # but we define it, to comply TrafficSignalCategoryEnvelope = base_pb2.CategoryEnvelope() localTrafficSignal.envelope.CopyFrom(TrafficSignalCategoryEnvelope) NumOfTrafficSignalsInSensorisMessage = config.getConfig_Int("run_config", "numOfTrafficSignals_perHEREMaplet") iterator = int(0) while iterator < NumOfTrafficSignalsInSensorisMessage: localTrafficSignal.traffic_light_status.extend([defineTrafficSignal()]) localTrafficSignal.traffic_light_cofiguration.extend([defineTrafficLightConfiguration()]) iterator += 1 return localTrafficSignal
def defineObjectDetectionCategory(): localObjectDetection = object_detection_pb2.ObjectDetectionCategory() # the object detecion category has 2 main messages # main message generation localMovingObject = object_detection_pb2.MovableObjectDetection() localStaticObject = object_detection_pb2.StaticObjectDetection() # a static object comes with the following attributes to be filled by this script: Lets see, what is happening, if # 1 - envelope # 2 - type and confidence # 4 - position # 5 - rotation # 6 - size vector # 7 - surface type # 8 - surface material type localStaticObject.envelope.CopyFrom(define_EventEnvelope.defineEventEnvelope(config.getConfig_Int("HERE_MAPLET_CONE_BARREL", "construction_zone_marker_id_int"))) if config.getConfig_Str("HERE_MAPLET_CONE_BARREL", "construction_zone_cone_type_enum") == "CONE": localStaticObject.type_and_confidence.type = object_detection_pb2.StaticObjectDetection.TypeAndConfidence.CONE pass # THIS IS NOT REQUESTED BY HERE MAPLET #localStaticObject.type_and_confidence.confidence_percent.value = 67 localStaticObject.type_and_confidence.color = base_pb2.GCE_RED # generation of the necessary elements # handover of the necessary elements # main message hand over to the local Object detecion # please note, that the static and moveable objects are repeated elements # this means, you can add as many objects as you need. localObjectDetection.static_object_detection.extend([localStaticObject]) localObjectDetection.movable_object_detection.extend([localMovingObject]) return localObjectDetection
def defineSignFacesCategory(): localSignFaces = traffic_regulation_pb2.TrafficRegulationCategory() # The HERE Maplet spec says, that you want to collect the following items: # (1) Sign ID # (2) timestamp # (3) Center Point of detected traffic sign # (4) covariance matrix for the position reported # (5) orientation # (6) height, width and shape of the traffic sign # (1) will be defined via the event envelope # (2) will be defined via the event envelope # (3) will be given via the message "sign recognition" in position and accuracy # (4) will be given via the message "sign recognition" in position and accuracy # (5) will be given via the message "sign recognition" in the "rotation and accuracy" # (6) will be given via the message "size and accuracy" ... shape will be an enum in there as well # again, we generate these items several times (configurable) and set some meaningful random fake values # here we define the mandatory event envelope for the localization # There is a little bug in the Sensoris spec, as no content is defined in the category envelope # but we define it, to comply signfacesCategoryEnvelope = base_pb2.CategoryEnvelope() localSignFaces.envelope.CopyFrom(signfacesCategoryEnvelope) NumOfTrafficSignsInSensorisMessage = config.getConfig_Int( "run_config", "numOfSignFaces_perHEREMaplet") iterator = int(0) while iterator < NumOfTrafficSignsInSensorisMessage: localSignFaces.sign_recognition.extend([defineTrafficSign()]) iterator += 1 return localSignFaces
def main(): # The SENSORIS-Message basically consists of 3 elements # #1 version # #2 submitter # #3 data message # # These three elements will be generated here # Please go deeper into the python files to see, how these elements are internally generated # this is the SENSORIS message itself mySensorisMessage = data_pb2.DataMessages() # Filling #1 (version) mySensorisMessage.version.CopyFrom( define_Version.DefineSENSORISVersion( config.getConfig_Int("general", "major_version"), config.getConfig_Int("general", "minor_version"), config.getConfig_Int("general", "patch_version"))) # Filling #2 (submitter) mySensorisMessage.submitter.extend([ define_Submitter.DefineSENSORISSubmitter( config.getConfig_Str("submitter", "OEM_brand"), config.getConfig_Str("submitter", "OEM_vehicle_type"), config.getConfig_Str("submitter", "OEM_ecu_sw_version"), config.getConfig_Str("submitter", "OEM_ecu_hw_version")) ]) # Filling #3 (data message) # This is the MAJOR part of SENSORIS! mySensorisMessage.data_message.extend( [define_DataMessage.DefineSENSORISDataMessage()]) print mySensorisMessage.__unicode__() # writes the protobuf stream on a binary file on disk with open('generatedSENSORISmessage.bin', 'wb') as f: f.write(mySensorisMessage.SerializeToString()) # display the size of the written file statinfo = os.stat('generatedSENSORISmessage.bin') print "Size of written SENSORIS protobuf message is " + str( statinfo.st_size) + " Bytes" # here we check, if we can read the just dumped data mySENSORISmessage_rewrite = data_pb2.DataMessages() with open('generatedSENSORISmessage.bin', 'rb') as f: mySENSORISmessage_rewrite.ParseFromString(f.read()) # now we take the binary file from the disk an zip it output_message_zip = zipfile.ZipFile('generatedSENSORISmessage.zip', 'w') output_message_zip.write('generatedSENSORISmessage.bin', compress_type=zipfile.ZIP_DEFLATED) output_message_zip.close() # display the size of the compressed written file statinfo = os.stat('generatedSENSORISmessage.zip') print "Size of written SENSORIS protobuf message is " + str( statinfo.st_size) + " Bytes (compressed via zip)" return
def defineSENSORISEnvelope(): # the Envelope consists for three elements # #1 (identifiers) # #2 (adapted factor) # #3 (vehicle dimensions) # generating a local container for the content localEnvelope = data_pb2.DataMessage.Envelope() localIdentifyer = base_pb2.MessageEnvelopeIds() localVehicleDimensions = spatial_pb2.BoundingBox.Metric() # filling the identifiers with life localIdentifyer.session_id.value = str(uuid.uuid4()) # why is the message_id a number, but the rest a string? localIdentifyer.message_id.value = config.getConfig_Int( "general_message_config", "message_id") localIdentifyer.vehicle_fleet_id.value = str(uuid.uuid4()) localIdentifyer.vehicle_id.value = str(uuid.uuid4()) localIdentifyer.driver_id.value = str(uuid.uuid4()) # 2.1 defining the minimum vehicle dimensions # this is practially a bounding box around the vehicle localminposition = spatial_pb2.Position.Metric() # as an example, we take the values of an Audi A8 from year 2017 # length: 5135mm (maximum: 5265mm) # width: 1945mm (maximum: 1949mm) # height: 1460mm (maximum: 1473mm) localminposition.x_m.value = config.getConfig_Int( "vehicle_dimensions", "minimal_vehicle_length_mm") localminposition.y_m.value = config.getConfig_Int( "vehicle_dimensions", "minimal_vehicle_width_mm") localminposition.z_m.value = config.getConfig_Int( "vehicle_dimensions", "minimal_vehicle_height_mm") # 2.1 defining the minimum vehicle dimensions # this is practially a bounding box around the vehicle localmaxposition = spatial_pb2.Position.Metric() localmaxposition.x_m.value = config.getConfig_Int( "vehicle_dimensions", "maximal_vehicle_length_mm") localmaxposition.y_m.value = config.getConfig_Int( "vehicle_dimensions", "maximal_vehicle_width_mm") localmaxposition.z_m.value = config.getConfig_Int( "vehicle_dimensions", "maximal_vehicle_height_mm") localVehicleDimensions.min_position.CopyFrom(localminposition) localVehicleDimensions.max_position.CopyFrom(localmaxposition) localMessageFactor = data_pb2.DataMessage.Envelope.Factor() # localMessageFactor.field_mask = 1 localMessageFactor.factor = config.getConfig_Int("general_message_config", "scale_factor") # scale factor 3 means, that you interpret all values in "meter" as "millimeter" # example: vehicle width=2,5135m is represented as width 2513 # putting it all together localEnvelope.adapted_factor.extend([localMessageFactor]) localEnvelope.ids.CopyFrom(localIdentifyer) localEnvelope.vehicle_dimensions.CopyFrom(localVehicleDimensions) return localEnvelope