def CheckRange(self, veh_data, tp): """ Check for ITS Spot devices in range of the current vehicle :param veh_data: The current vehicle data :param tp: The current time period """ Inrange_SPOTdevices = self.SPOT_tree.find_range(veh_data['location_x'], veh_data['location_y']) clear_SPOT_buffer = False for SPOT in Inrange_SPOTdevices: if veh_data['vehicle_ID'] in self.SPOTBuffer.ActiveBuffers.keys(): travelSPOTs, behaviorSPOTs = self.SPOTBuffer.TransmitSPOTBuffer(veh_data) if (len(travelSPOTs)+len(behaviorSPOTs)) > 0: self.Travelmsgs.extend(travelSPOTs) self.BehaviorMsgs.extend(behaviorSPOTs) clear_SPOT_buffer = True veh_data['SPOT_trans_tp'] = tp if self.CF.Control["OutputLevel"] >= 2: logger.debug("%s ITS Spot messages transmitted at time %d from vehicle ID: %s" % \ ((len(travelSPOTs)+len(behaviorSPOTs)), veh_data["time"], veh_data['vehicle_ID'])) if clear_SPOT_buffer: self.SPOTBuffer.ClearBuffer(veh_data['vehicle_ID'])
def change_PSN(veh_data, tp): """ Sets the given vehicle's PSN to a new random value and resets PSN change triggers :param veh_data: The vehicle whose PSN is changed :param tp: The time period that the change occurrs in """ veh_data['PSN'] = self.random_generator['psn'] veh_data['PSN_distance_to_change'] = veh_data[ 'total_dist_traveled'] + self.CF.Strategy[ "DistanceBetweenPSNSwitches"] veh_data['PSN_time_to_end_of_PSN'] = tp + self.CF.Strategy[ 'TimeBetweenPSNSwitches'] if self.CF.Control["OutputLevel"] >= 2: logger.debug( "PSN changed to %d for vehicle ID %s at time %s because of RSE transmission" % (veh_data['PSN'], veh_data['vehicle_ID'], tp))
def start_gap(veh_data, tp): """ Starts a new privacy gap for the given vehicle :param veh_data: The vehicle entering the privacy gap :param tp: The time period that the privacy gap starts in """ veh_data['PSN'] = -1 veh_data['PSN_time_to_end_gap'] = tp + self.random_generator[ 'GapTimeout'] veh_data['PSN_distance_to_end_of_gap'] = veh_data[ 'total_dist_traveled'] + self.random_generator['GapDistance'] if self.CF.Control["OutputLevel"] >= 2: logger.debug( "Vehicle ID %s at time %s enters PSN privacy gap because of RSE transmission" % (veh_data['vehicle_ID'], tp)) veh_data['privacy_gap_start'] = tp veh_data['in_privacy_gap'] = True
def CheckTravelRecords(self, veh_data): """ Checks to see if the vehicle has triggered any of the requirements for producing an ITS Spot travel record :param veh_data: The vehicle data of the vehicle transmitting the message :return: True if the vehicle triggers an ITS Spot Travel Record, false otherwise """ # Travel Records: Check that vehicle has traveled 200m since the beginning or since the last ITS Spot or changed heading by 45 degrees if veh_data['prev_tp_travel_SPOT'] is None and (veh_data['total_dist_traveled'] * self.FT_CONVERSION) >= 200: #convert feet to meters if self.CF.Control['OutputLevel'] >= 2: logger.debug('Travel SPOT generated at time: %s for vehicle ID: %s because initial distance traveled of: %s meters' % (veh_data['time'], \ veh_data['vehicle_ID'], (veh_data['total_dist_traveled'] * self.FT_CONVERSION))) return True if veh_data['prev_tp_travel_SPOT'] is not None: if abs(Get_Heading_Change(veh_data['prev_SPOT_heading'], veh_data['heading'])) >= 45: if self.CF.Control['OutputLevel'] >= 2: logger.debug('Travel SPOT generated at time: %s for vehicle ID: %s because heading change of: %s degrees' % (veh_data['time'], veh_data['vehicle_ID'],\ Get_Heading_Change(veh_data['prev_SPOT_heading'], veh_data['heading']))) return True elif (abs(veh_data['prev_SPOT_distance'] - veh_data['total_dist_traveled']) * self.FT_CONVERSION) >= 200: # convert feet to meters if self.CF.Control['OutputLevel'] >= 2: logger.debug('Travel SPOT generated at time: %s for vehicle ID: %s because distance traveled of: %s meters' % (veh_data['time'], veh_data['vehicle_ID'], \ (abs(veh_data['prev_SPOT_distance'] - veh_data['total_dist_traveled']) * self.FT_CONVERSION))) return True return False
def RSETransmitPDM(self, veh_data, RSE): """ Calls Transmit PDM to transmit to an RSE :param veh_data: The vehicle transmitting the message :param RSE: The RSE being transmitted to """ if (veh_data["time"] != 0): if self.CF.Control["OutputLevel"] >= 2: logger.debug( "%s PDMs transmitted at time %s to RSE:%s from vehicle:%s" % (self.PDM.PDMBuffer.BufferCount(veh_data['vehicle_ID']), veh_data["time"], RSE, veh_data['vehicle_ID'])) self.PDM.PDMBuffer.TransmitPDM( veh_data=veh_data, transTo=RSE, isCellular=False, tp=veh_data['time'], Snapshots=self.PDM.PDM_list, CF=self.CF, latency=self.RSEs.RSEList[RSE]['latency'])
def CheckMessage(self, veh_data, tp): """ Check to see if the current vehicle has triggered an ITS Spot message :param veh_data: The vehicle data of the vehicle transmitting the message :param tp: the current time period """ # Check vehicle distance traveled and heading to determine if generating a Travel Record SPOT if (tp % 1.0 == 0) and self.CheckTravelRecords(veh_data): self.Generate(veh_data = veh_data, SPOT_type = 1) veh_data['prev_tp_travel_SPOT'] = tp # If sensing frequency is valid, check for Behavior Record SPOT if SPOT_time(tp, self.CF.Strategy['SPOTBehaviorSensingFrequency']): # Behavior Records: Check if acceleration greater than -0.25g or yaw rate > +-8.5 deg/s if veh_data['accel_instantaneous'] is not None: accel = veh_data['accel_instantaneous'] else: accel = veh_data['average_acceleration'] if accel <= self.SPOT_accel_threshold: # Check to see if this is the start of a new time period if veh_data['SPOT_accel_tp'] is None: veh_data['SPOT_accel_tp'] = tp # Check to see if there is a new deceleration peak (current accel < recorded max) if accel < veh_data['max_SPOT_accel']: veh_data['max_SPOT_accel'] = accel veh_data['SPOT_accel_X'] = veh_data['location_x'] veh_data['SPOT_accel_Y'] = veh_data['location_y'] veh_data['SPOT_accel_v'] = veh_data['speed'] veh_data['SPOT_accel_heading'] = veh_data['heading'] veh_data['SPOT_accel_yawrate'] = veh_data['yawrate'] # Else, check to see if a threshold period just finished else: if veh_data['SPOT_accel_tp'] is not None: if self.CF.Control['OutputLevel'] >= 2: logger.debug('Behavior SPOT generated at time: %s for vehicle ID: %s because deceleration of: %s g' % (veh_data['time'], veh_data['vehicle_ID'], \ (veh_data['max_SPOT_accel'] * self.ACCEL_CONVERSION))) # Generate SPOT self.Generate(veh_data = veh_data, SPOT_type = 2, accel = veh_data['max_SPOT_accel']) veh_data['prev_tp_accel_SPOT'] = veh_data['SPOT_accel_tp'] # Reset max accel to zero veh_data['max_SPOT_accel'] = 0.0 veh_data['SPOT_accel_tp'] = None veh_data['SPOT_accel_X'] = 0.0 veh_data['SPOT_accel_Y'] = 0.0 veh_data['SPOT_accel_v'] = 0.0 veh_data['SPOT_accel_heading'] = 0.0 veh_data['SPOT_accel_yawrate'] = 0.0 if veh_data['yawrate'] is not None and abs(veh_data['yawrate']) > self.SPOT_yawrate_threshold: # Check to see if this is the start of a new time period if veh_data['SPOT_yawrate_tp'] == None: veh_data['SPOT_yawrate_tp'] = tp # Check to see if there is a new peak (current yaw rate > recorded max) if abs(veh_data['max_SPOT_yawrate']) < abs(veh_data['yawrate']): veh_data['max_SPOT_yawrate'] = veh_data['yawrate'] veh_data['SPOT_yawrate_X'] = veh_data['location_x'] veh_data['SPOT_yawrate_Y'] = veh_data['location_y'] veh_data['SPOT_yawrate_v'] = veh_data['speed'] veh_data['SPOT_yawrate_heading'] = veh_data['heading'] veh_data['SPOT_yawrate_accel'] = accel # Else, check to see if a threshold period just finished (max yawrate > 0) else: if veh_data['SPOT_yawrate_tp'] is not None: # Check to make sure an ITS Spot behavior record wasn't already taken for acceleration if (veh_data['prev_tp_accel_SPOT'] is None) or (round(veh_data['SPOT_yawrate_tp']) != round(veh_data['prev_tp_accel_SPOT'])): if self.CF.Control['OutputLevel'] >= 2: logger.debug('Behavior SPOT generated at time: %s for vehicle ID: %s because yawrate of: %s deg/sec' % (veh_data['time'], veh_data['vehicle_ID'], \ veh_data['max_SPOT_yawrate'])) # Generate SPOT self.Generate(veh_data = veh_data, SPOT_type = 2, yawrate = veh_data['max_SPOT_yawrate']) veh_data['prev_tp_yawrate_SPOT'] = tp elif self.CF.Control['OutputLevel'] >= 3: logger.debug('Behavior SPOT not generated at time: %s for vehicle ID: %s due to yawrate because ITS Spot already taken for acceleration' % (veh_data['time'], veh_data['vehicle_ID'])) # Reset max yaw rate to zero # Reset max accel to zero veh_data['max_SPOT_yawrate'] = 0.0 veh_data['SPOT_yawrate_tp'] = None veh_data['SPOT_yawrate_X'] = 0.0 veh_data['SPOT_yawrate_Y'] = 0.0 veh_data['SPOT_yawrate_v'] = 0.0 veh_data['SPOT_yawrate_heading'] = 0.0 veh_data['SPOT_yawrate_accel'] = 0.0
def PSNCheck(self, veh_data, tp): """ If the given vehicle has transmitted a message in the given time, changes PSN or activates privacy gap If privacy gaps are enabled, checks to see if the given vehicle has expired PSN and enters privacy gap if so If the given vehicle is in a privacy gap, checks to see if the gap has expired and if so vehicle is given new PSN :param veh_data: The vehicle to check :param tp: The time period in seconds to check """ def change_PSN(veh_data, tp): """ Sets the given vehicle's PSN to a new random value and resets PSN change triggers :param veh_data: The vehicle whose PSN is changed :param tp: The time period that the change occurrs in """ veh_data['PSN'] = self.random_generator['psn'] veh_data['PSN_distance_to_change'] = veh_data[ 'total_dist_traveled'] + self.CF.Strategy[ "DistanceBetweenPSNSwitches"] veh_data['PSN_time_to_end_of_PSN'] = tp + self.CF.Strategy[ 'TimeBetweenPSNSwitches'] if self.CF.Control["OutputLevel"] >= 2: logger.debug( "PSN changed to %d for vehicle ID %s at time %s because of RSE transmission" % (veh_data['PSN'], veh_data['vehicle_ID'], tp)) def start_gap(veh_data, tp): """ Starts a new privacy gap for the given vehicle :param veh_data: The vehicle entering the privacy gap :param tp: The time period that the privacy gap starts in """ veh_data['PSN'] = -1 veh_data['PSN_time_to_end_gap'] = tp + self.random_generator[ 'GapTimeout'] veh_data['PSN_distance_to_end_of_gap'] = veh_data[ 'total_dist_traveled'] + self.random_generator['GapDistance'] if self.CF.Control["OutputLevel"] >= 2: logger.debug( "Vehicle ID %s at time %s enters PSN privacy gap because of RSE transmission" % (veh_data['vehicle_ID'], tp)) veh_data['privacy_gap_start'] = tp veh_data['in_privacy_gap'] = True #Change PSN or activate privacy gap if vehicle has transmitted to an RSE and is PDM equipped if veh_data['dsrc_transmit_pdm'] and ( veh_data['prev_time_PDM_dsrc_transmit'] == tp): if self.CF.Strategy["GapMaxDistance"] == 0 or self.CF.Strategy[ "GapMaxTime"] == 0: change_PSN(veh_data, tp) else: start_gap(veh_data, tp) #4.1 check whether the distance and time has expired of current PSN if not in gap if (veh_data['in_privacy_gap'] == False) \ and (tp >= veh_data['PSN_time_to_end_of_PSN']) \ and (veh_data['total_dist_traveled'] >= veh_data['PSN_distance_to_change']): #4.4 Check for Gap (Note if CF.Strategy["Gap"]=0 then no Gaps are added) if self.CF.Strategy["Gap"] == 1: start_gap(veh_data, tp) else: change_PSN(veh_data, tp) #4.5 Check to see if privacy gap has expired; generate new PSN if veh_data['in_privacy_gap'] and \ (veh_data['total_dist_traveled'] >= veh_data['PSN_distance_to_end_of_gap']) or \ (tp >= veh_data['PSN_time_to_end_gap']): change_PSN(veh_data, tp) veh_data['in_privacy_gap'] = False if self.CF.Control["OutputLevel"] >= 2: logger.debug( "PSN changed to %d for vehicle ID %s at time %s because privacy gap expired" % (veh_data['PSN'], veh_data['vehicle_ID'], tp))
def Generate(self, veh_data, type, time): """ Creates a PDM and adds it to the PDM list :param veh_data: The vehicle to create a PDM for :param type: The vehicle type creating the PDM :param time: The time the PDM is being created """ if self.CF.Control["OutputLevel"] >= 3: logger.debug("PDM type %d created in vehicle %s" % (type, veh_data['vehicle_ID'])) #9.0 Update Snapshot log if veh_data['vehicle_ID'] in self.PDMBuffer.ActiveBuffers.keys(): lastRSE = self.PDMBuffer.GetLastRSE(veh_data['vehicle_ID']) else: lastRSE = 0 #Add Snap Shot to Main SS List SS = { 'VID': veh_data['vehicle_ID'], 'num': len(self.PDM_list) + 1, 'time': time, 'localtime': time, 'PSN': veh_data['PSN'], 'spd': veh_data['speed'], 'x': veh_data['location_x'], 'y': veh_data['location_y'], 'type': type, 'lastRSE': lastRSE, 'transtime': -1, 'transTo': -1, 'deltime': 0, 'delreason': 0, 'transmission_received_time': -1, 'link': veh_data['link'], 'yawrate': veh_data['yawrate'], } # Add acceleration to the PDM Snapshot if veh_data['accel_instantaneous'] is not None: SS['instant_accel'] = veh_data['accel_instantaneous'] else: SS['avg_accel'] = veh_data['average_acceleration'] # Add any event values to the PDM Snapshot if self.regions is not None: for Event in self.regions.Event_titles: SS[Event] = veh_data[Event] self.PDM_list.append(SS) #9.1 Manage Vehicle Buffer Contents if (veh_data["in_privacy_gap"] != True) and (SS["PSN"] != -1): self.PDMBuffer.AddSS(veh_data=veh_data, SS=SS, locT=time, Snapshots=self.PDM_list, CF=self.CF) else: self.PDMBuffer.DeleteSSinLog(SS=SS, locT=time, reason=3, Snapshots=self.PDM_list)
def CheckMessage(self, veh, tp): """ Checks the defined PDM snapshot triggers for the given vehicle in the given time to see if a PDM should be generated :param veh: The vehicle to check :param tp: The time period to check in """ PDM_generated = False #Only vehicles that have been active in the network for the user-defined amount of time or distance #The default J2735 values are: 500m or 120 seconds if (veh['total_dist_traveled'] >= self.CF.Strategy['DistanceBeforePDMCollection']) or \ (veh['total_time_in_network'] >= self.CF.Strategy['TimeBeforePDMCollection']): #2.1 Stop Trigger #2.1.1 if veh['speed'] > 0: veh['time_motionless'] = 0 else: veh['time_motionless'] += 1 #Query all vehicles whose Motionless value is greater than Stop Threshold that haven't taken a Stop SS #since the StopLag time and mark that a stop snapshot was taken and update the time since last stop and distance #since last stop. if ((veh['time_motionless'] > self.CF.Strategy['StopThreshold']) and \ (veh['looking_for_start'] == False)): veh['looking_for_start'] = True veh['time_of_last_stop'] = tp self.Generate(veh_data=veh, type=1, time=tp) PDM_generated = True #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #2.2 Start Trigger #2.2.1 #Query all vehicles that currently have their looking for a start value set to true and whose speed #is greater than Start Threshold and mark that a start snapshot was taken and revert looking for a #start to false if (veh['looking_for_start']) and ( veh['speed'] >= self.CF.Strategy['StartThreshold']): veh['looking_for_start'] = False veh['time_of_start_snapshot'] = tp self.Generate(veh_data=veh, type=2, time=tp) PDM_generated = True #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #2.3 Periodic Trigger #2.3.1 and #2.3.2 (speed exception) #Query all vehicles that have not taken a start or stop snapshot, do not have their looking for #a start value set for true and whose time until their next periodic snapshot is <= the current time #and mark that a periodic snapshot was taken and re-calculate the time until the next periodic. if (veh['looking_for_start'] == False) and (veh['time_to_next_periodic'] <= tp) and \ (PDM_generated == False): veh['time_of_periodic_snapshot'] = tp self.Generate(veh_data=veh, type=3, time=tp) if self.CF.Control["OutputLevel"] >= 2: logger.debug( 'Periodic SS Created for Vehicle ID %s at time:%s' % (veh['vehicle_ID'], tp)) #check for when the next check should be if veh['speed'] <= self.CF.Strategy["LowSpeedThreshold"]: IncreaseTime = self.CF.Strategy["ShortSpeedInterval"] elif veh['speed'] >= self.CF.Strategy["HighSpeedThreshold"]: IncreaseTime = self.CF.Strategy["LongSpeedInterval"] else: #Speed Interpolation slope = (veh['speed'] - self.CF.Strategy["LowSpeedThreshold"]) / \ (self.CF.Strategy["HighSpeedThreshold"] - self.CF.Strategy["LowSpeedThreshold"]) IncreaseTime = round( self.CF.Strategy["ShortSpeedInterval"] + slope * (self.CF.Strategy["LongSpeedInterval"] - self.CF.Strategy["ShortSpeedInterval"])) #increase time counter veh['time_to_next_periodic'] = tp + IncreaseTime
def CheckCellular(self, veh_data, tp): """ Checks to see if a PDM or BSM message can be sent via cellular for the given vehicle in the given time :param veh_data: The vehicle to check :param tp: The time period to check in """ if self.CF.Control["OutputLevel"] >= 3: logger.debug( 'Checking for vehicles with enough snapshots in their buffer to transmit via cellular' ) #Set Default values if no region if self.regions is None: latency = 0.0 loss_percent = 0.0 mintransmit_PDM = 1 else: latency = self.regions.default_latency loss_percent = self.regions.default_loss mintransmit_PDM = self.regions.min_PDM_to_transmit region_name = 'Cellular_Default' if veh_data['BSM_equipped'] and (veh_data['dsrc_transmit_bsm'] == False ) and veh_data['cellular_enabled']: if float(self.CF.Strategy['BSMFrequencyCellular']) > 0.0: if veh_data['prev_time_BSM_cellular_transmit'] + float( self.CF.Strategy['BSMFrequencyCellular']) <= tp: if self.random_generator['LossPercent'] > loss_percent: self.BSM.GenerateTransmit(veh_data=veh_data, transTo=region_name, isCellular=True, isRSE=False) veh_data['prev_time_BSM_cellular_transmit'] = tp else: if self.random_generator['LossPercent'] > loss_percent: self.BSM.GenerateTransmit(veh_data=veh_data, transTo=region_name, isCellular=True, isRSE=False) if veh_data['PDM_equipped'] and ( tp % 1 == 0) and veh_data['cellular_enabled']: if float(veh_data['prev_time_PDM_cellular_transmit']) + float( self.CF.Strategy['PDMFrequencyCellular']) <= tp: if self.CF.Control["OutputLevel"] >= 3: logger.debug('Checking for cellular region at time %d' % veh_data['time']) #Check if vehicle is within a defined cellular region if self.regions is not None: for region in self.regions.cell_regions: if region.in_region(veh_data['location_x'], veh_data['location_y']): #Assign the defined regions loss percentage and latency latency = float(region.latency) loss_percent = float(region.loss) region_name = region.title break if self.CF.Control["OutputLevel"] >= 3: logger.debug( 'Checking for minimum number of SS to transmit') #If PDM buffer has the minimum number of snapshots if (self.PDM.PDMBuffer.BufferCount(veh_data['vehicle_ID']) >= mintransmit_PDM): if veh_data["time"] != 0: #By random number generator, determine if snapshot transmission is successful. Else delete snapshots. if self.random_generator['LossPercent'] > loss_percent: if self.CF.Control["OutputLevel"] >= 2: logger.debug("%s SS transmitted at time %d via cellular from vehicle ID: %s" % \ (self.PDM.PDMBuffer.BufferCount(veh_data['vehicle_ID']), veh_data["time"], veh_data['vehicle_ID'])) self.PDM.PDMBuffer.TransmitPDM( veh_data=veh_data, transTo=region_name, isCellular=True, tp=veh_data["time"], Snapshots=self.PDM.PDM_list, latency=latency, CF=self.CF) else: #Delete reason 5: transmission lost self.PDM.PDMBuffer.ClearBuffer( vehicleID=veh_data['vehicle_ID'], locT=veh_data["time"], Snapshots=self.PDM.PDM_list, reason=5, transmitted_to=-1, transTime=veh_data["time"]) veh_data['prev_time_PDM_cellular_transmit'] = veh_data[ "time"]
def CheckDSRC(self, veh_data, tp, range_data): """ Checks to see if a PDM, BSM or CAM message can be sent via DSRC for the given vehicle in the given time :param veh_data: The vehicle to check :param tp: The time period to check in """ #Select vehicles that are active and DSRC enabled (exclusively or dual) if ((tp % 1 ==0) and (veh_data['PDM_equipped']) and (veh_data['in_privacy_gap'] == False)) \ or (veh_data['BSM_equipped']) or (veh_data['CAM_equipped']): transmit_BSM = False transmit_PDM = False if len(range_data[veh_data['vehicle_ID']]) > 0: if veh_data['BSM_equipped']: if (float(veh_data['prev_time_BSM_dsrc_transmit']) + float(self.CF.Strategy['BSMFrequencyDSRC'])) <= tp: transmit_BSM = True if (tp % 1 == 0) and veh_data['PDM_equipped']: if (float(veh_data['prev_time_PDM_dsrc_transmit']) + float(self.CF.Strategy['PDMFrequencyDSRC'])) <= tp: transmit_PDM = True for roadside_equipment in range_data[veh_data['vehicle_ID']]: if self.CF.Control["OutputLevel"] >= 3: logger.debug( 'Time: %s Vehicle ID: %s - Checking RSE: %s' % (tp, veh_data['vehicle_ID'], roadside_equipment)) if veh_data['BSM_equipped'] and transmit_BSM: if self.random_generator['LossPercent'] > self.RSEs.RSEList[ roadside_equipment]['loss_rate']: self.BSM.GenerateTransmit(veh_data=veh_data, transTo=roadside_equipment, isCellular=False, isRSE=True) veh_data['dsrc_transmit_bsm'] = True veh_data['prev_time_BSM_dsrc_transmit'] = tp if transmit_PDM and (veh_data['vehicle_ID'] in self.PDM. PDMBuffer.ActiveBuffers.keys()) > 0: if self.PDM.PDMBuffer.BufferCount( veh_data['vehicle_ID'] ) >= self.CF.Strategy['MinNumberofPDMtoTransmitViaDSRC']: if self.random_generator[ 'LossPercent'] > self.RSEs.RSEList[ roadside_equipment]['loss_rate']: veh_data['dsrc_transmit_pdm'] = True veh_data['prev_time_PDM_dsrc_transmit'] = tp self.RSETransmitPDM(veh_data, roadside_equipment) else: #Delete reason 5: transmission lost self.PDM.PDMBuffer.ClearBuffer( vehicleID=veh_data['vehicle_ID'], locT=tp, Snapshots=self.PDMs, reason=5, transmitted_to=-1, transTime=-1) if veh_data['CAM_equipped']: if self.CAM.CheckMessage(veh_data, tp): if self.random_generator[ 'LossPercent'] > self.RSEs.RSEList[ roadside_equipment]['loss_rate']: if self.CF.Control['OutputLevel'] >= 2: logger.debug( 'Time: %s Vehicle ID: %s - Transmitting CAM to RSE: %s' % (tp, veh_data['vehicle_ID'], roadside_equipment)) self.CAM.GenerateTransmit( veh_data=veh_data, transTo=roadside_equipment, tp=tp)