Esempio n. 1
0
    def __init__(self,
                 RandomGen_seed,
                 CF,
                 RSE_tree,
                 regions,
                 msg_limit=800000):
        """
        Initializes a PDM module

        :param RandomGen_seed: The random seed
        """
        self.random_generator = Random_generator(RandomGen_seed)
        self.CF = CF
        self.regions = regions

        self.random_generator.add_generator_int('psn', 0,
                                                32767)  #range based on J2735
        self.random_generator.add_generator_int('GapDistance',
                                                CF.Strategy["GapMinDistance"],
                                                CF.Strategy["GapMaxDistance"])
        self.random_generator.add_generator_int('GapTimeout',
                                                CF.Strategy["GapMinTime"],
                                                CF.Strategy["GapMaxTime"])

        #Buffer Manager for PDM Snapshots
        self.PDMBuffer = CLBuffer(CF.Strategy['TotalCapacity'])
        self.PDM_list = []

        #Limit of message list before printing to a file
        self.msg_limit = msg_limit
        self.headerPDM = True

        self.PDM_col_order = [
            "DSRC_MessageID",
            "x",
            "y",
            "localtime",
            "num",
            "VID",
            "PSN",
            "ss_num",
            "msg_num",
            "spd",
            "accel",
            "lastRSE",
            "type",
            "transtime",
            "transTo",
            'deltime',
            'delreason',
            'transmission_received_time',
            'link',
            'yawrate',
        ]

        if self.regions is not None:
            for Event in self.regions.Event_titles:
                self.PDM_col_order.append(Event)
Esempio n. 2
0
    def __init__(self,
                 CF,
                 RSEs,
                 RSE_tree,
                 RandomGen_seed,
                 Regions,
                 SPOT_tree,
                 msg_limit=800000,
                 link_included=False):
        """
        Initializes TCA_Algorithm module

        :param CF: Dictionary of Control File defined attributes
        :param RSEs: List of RSEs
        :param RSE_tree: Location tree of RSEs
        :param RandomGen: Seed value for randomization
        :param Regions: Regions class
        :param SPOT_tree: Location tree of SPOT devices
        :param msg_limit: Limit of snapshot list before outputting to a file
        """

        self.RSEs = RSEs
        self.RSE_tree = RSE_tree
        self.CF = CF
        self.regions = Regions

        self.random_generator = Random_generator(RandomGen_seed)

        self.random_generator.add_generator_int('LossPercent', 1, 100)
        self.random_generator.add_generator_int('TypePercent', 1, 100)

        self.BSM = BSM(self.random_generator.generate_seed(), self.CF,
                       self.regions)
        self.CAM = CAM(self.random_generator.generate_seed(), self.CF)
        self.SPOT = SPOT(self.random_generator.generate_seed(), self.CF,
                         SPOT_tree)
        self.PDM = PDM(self.random_generator.generate_seed(), self.CF,
                       RSE_tree, self.regions)

        self.msgs = {
            'BSM': self.BSM,
            'CAM': self.CAM,
            'SPOT': self.SPOT,
            'PDM': self.PDM
        }

        self.tbl = DataStorage(self.random_generator,
                               accel_included=True,
                               link_included=link_included)

        #Each Vehicle RSE list
        self.VehicleRSE = {}

        #Limit of message list before printing to a file
        self.msg_limit = msg_limit
Esempio n. 3
0
    def __init__(self, RandomGen_seed, CF, SPOT_tree, msg_limit = 800000):

        """
        Initializes an ITS Spot module

        :param RandomGen_seed: The random seed
        """
        self.random_generator = Random_generator(RandomGen_seed)
        self.CF = CF

        self.Travelmsgs = []
        self.BehaviorMsgs = []
        self.SPOT_tree = SPOT_tree
        self.SPOTBuffer = SPOTBuffer()

        self.header = True
        self.Travel_col_order = ['localtime', 'vehicle_ID', 'x', 'y', 'spd']
        self.Behavior_col_order = self.Travel_col_order + ['accel', 'heading', 'yawrate']
        #Limit of message list before printing to a file
        self.msg_limit = msg_limit

        self.FT_CONVERSION = 12 * 2.54 / 100 # converts feet to meters
        self.ACCEL_CONVERSION = 1 / 32.1740485564 # converts ft/s2 to g
        self.SPOT_SPD_CONVERSION = 1.609344 # converts mph to km/hr for ITS Spot Output
        self.SPOT_accel_threshold = self.CF.Strategy['SPOTaccelThreshold'] * 32.1740485564 # Convert g to ft/s^2 for ITS Spot Output
        self.SPOT_yawrate_threshold = self.CF.Strategy['SPOTyawrateThreshold'] * 32.1740485564 # Convert g to ft/s^2 for ITS Spot Output
Esempio n. 4
0
    def __init__(self, RandomGen_seed, CF, msg_limit=800000):
        """
        Initializes a CAM module

        :param RandomGen_seed: The random seed
        """
        self.random_generator = Random_generator(RandomGen_seed)
        self.CF = CF

        #Limit of message list before printing to a file
        self.msg_limit = msg_limit

        self.CAM_list = []
        self.headerCAM = True

        self.random_generator.add_generator_int(
            'Station_ID', 1, 4294967295)  #based ITS-S standard
Esempio n. 5
0
    def __init__(self, RandomGen_seed, CF, regions, msg_limit=800000):
        """
        Initializes a BSM module

        :param RandomGen_seed: The random seed
        """
        self.random_generator = Random_generator(RandomGen_seed)
        self.CF = CF
        self.regions = regions

        self.random_generator.add_generator_bit('BSM_Tmp_ID', 32)
        self.random_generator.add_generator_int('LossPercent', 1, 100)

        #Limit of message list before printing to a file
        self.msg_limit = msg_limit

        self.BSM_list = []
        self.headerBSM = True

        self.BSM_col_order = [
            'DSRC_MessageID',
            'Vehicle_ID',
            'BSM_tmp_ID',
            'transtime',
            'x',
            'y',
            'spd',
            'accel',
            'heading',
            'brakeStatus',
            'brakePressure',
            'hardBraking',
            'transTo',
            'transmission_received_time',
        ]

        if self.regions is not None:
            for Event in self.regions.Event_titles:
                self.BSM_col_order.append(Event)
Esempio n. 6
0
    def __init__(self, title, point1, point2, loss, latency):
        """
        Defines a cellular region with a title, the upper left and bottom right point
        :param title: Title of the region
        :param point1: x,y coordinate of the upper left
        :param point2: x,y coordinate of the bottom right
        :param loss: The loss percentage of snapshots transmitted in this cellular region
        :param latency: the latency or delay time in seconds for snapshot transmission
        """
        Region.__init__(self, title, point1, point2)

        self.loss = loss
        self.latency = latency
        self.RandomGen = Random_generator()
Esempio n. 7
0
    def __init__(self, seed):
        """
        This class holds all the event and cellular regions for the TCA, as well as any default values
        :param seed: A random seed for the Random Number Generators
        """

        self.RandomGen = Random_generator(seed)

        #Cellular fields
        self.cell_regions = []
        self.default_latency = 0  # Default: Zero seconds
        self.default_loss = 0  # Default: 0% loss percent
        self.min_PDM_to_transmit = 4  # Default: 4 snapshots required for transmission

        #Event region fields
        self.Event_regions = []
        self.Event_titles = set()
Esempio n. 8
0
    def __init__(self, title, point1, point2, times, events):
        """
        Defines an event region with a title, the upper left and bottom right point
        :param title: Title of the region
        :param point1: x,y coordinate of the upper left
        :param point2: x,y coordinate of the bottom right
        :param times: A list of times the event region is active
        :param events: A dictionary of events within the defined region
        """
        Region.__init__(self, title, point1, point2)
        self.times = times
        self.events = {}

        for event in events:
            self.events[event['title']] = {
                'recheck': event['recheck'],
                'next_check': times[0][0],
                'prev_check': 0,
                'random_generator': Random_generator(),
                'probability_type': event['probability_type'],
                'time_off': event['time_off'],
                'next_off': 0,
            }
            if event['probability_type'] == 'probability':
                self.events[
                    event['title']]['random_generator'].add_generator_int(
                        'rand_probability', 0, 100)
                self.events[
                    event['title']]['probability'] = event['probability']
            elif event['probability_type'] == 'mean':
                self.events[
                    event['title']]['random_generator'].add_generator_mean(
                        'rand_mean', event['mean'], event['sd'])
            elif event['probability_type'] == 'poisson':
                self.events[
                    event['title']]['random_generator'].add_generator_int(
                        'rand_probability', 0, 100)
                self.events[
                    event['title']]['random_generator'].add_generator_poisson(
                        'recheck', event['recheck'])
                self.events[
                    event['title']]['probability'] = event['probability']
Esempio n. 9
0
class BSM(object):
    def __init__(self, RandomGen_seed, CF, regions, msg_limit=800000):
        """
        Initializes a BSM module

        :param RandomGen_seed: The random seed
        """
        self.random_generator = Random_generator(RandomGen_seed)
        self.CF = CF
        self.regions = regions

        self.random_generator.add_generator_bit('BSM_Tmp_ID', 32)
        self.random_generator.add_generator_int('LossPercent', 1, 100)

        #Limit of message list before printing to a file
        self.msg_limit = msg_limit

        self.BSM_list = []
        self.headerBSM = True

        self.BSM_col_order = [
            'DSRC_MessageID',
            'Vehicle_ID',
            'BSM_tmp_ID',
            'transtime',
            'x',
            'y',
            'spd',
            'accel',
            'heading',
            'brakeStatus',
            'brakePressure',
            'hardBraking',
            'transTo',
            'transmission_received_time',
        ]

        if self.regions is not None:
            for Event in self.regions.Event_titles:
                self.BSM_col_order.append(Event)

#-------------------------------------------------------------------------

    def CheckBrakes(self, veh_data):
        """
        Checks brake status of given vehicle using instantaneous acceleration

        :param veh_data: Vehicle whose brakes to check
        """

        # Set brake_status as applied if decelerating more than the defined threshold
        veh_data['brake_status'] = '0000'
        if veh_data['average_acceleration'] <= self.CF.Strategy['BrakeThreshold'] \
                and veh_data['average_acceleration'] is not None:
            veh_data['brake_status'] = '1111'

        # Only set the brake pressure if instantaneous acceleration is available
        if veh_data['accel_instantaneous'] != None:

            if veh_data['accel_instantaneous'] <= 0:
                veh_data['brake_pressure'] = veh_data['accel_instantaneous']
            else:
                veh_data['brake_pressure'] = 0.0

        # Set the hard braking (1: true, 0: false) if decelerating greater than 0.4g (J2735 standard) or approx. 12.9 ft/s^2
        veh_data['hard_braking'] = 0
        if veh_data['average_acceleration'] <= -12.869619 \
            and veh_data['average_acceleration'] is not None:
            veh_data['hard_braking'] = 1

#-------------------------------------------------------------------------

    def GenerateTransmit(self,
                         veh_data,
                         transTo,
                         latency=0,
                         isCellular=False,
                         isRSE=False):
        """
        Creates BSM message and adds it to the BSM list

        :param veh_data: The vehicle data of the vehicle transmitting the message
        :param transTo: The RSE or Cellular Region being transmitted to
        :param latency: The latency between sending and receiving the message, default is 0
        :param isCellular: True if the vehicle is sending the message by Cellular, default is False
        :param isRSE: True if the vehicle is sending the message by RSE, default is False
        """

        if veh_data['BSM_equipped']:
            transmitted = True

            #Check if vehicle is within a defined cellular region
            if self.regions is not None and isCellular:
                if len(self.regions.cell_regions) > 0:
                    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)
                            if self.random_generator['LossPercent'] < float(
                                    region.loss):
                                transmitted = False
                            transTo = region.title

            if transmitted:
                BSM = {
                    'Vehicle_ID': veh_data['vehicle_ID'],
                    'BSM_tmp_ID': veh_data['BSM_tmp_ID'],
                    'localtime': veh_data['time'],
                    'spd': veh_data['speed'],
                    'x': veh_data['location_x'],
                    'y': veh_data['location_y'],
                    'transtime': veh_data['time'],
                    'transTo': transTo,
                    'avg_accel': veh_data['average_acceleration'],
                    'brakeStatus': veh_data["brake_status"],
                    'brakePressure': veh_data['brake_pressure'],
                    'hardBraking': veh_data['hard_braking'],
                    'transmission_received_time': veh_data['time'] + latency,
                    'heading': veh_data['heading'],
                }
                if veh_data['accel_instantaneous'] != None:
                    BSM["instant_accel"] = veh_data['accel_instantaneous']

                # if veh_data['link'] is not None:
                #     BSM['link'] = veh_data['link']

                if self.regions is not None:
                    for region_name in self.regions.Event_titles:
                        BSM[region_name] = veh_data[region_name]

                #Add BSM to the Main BSM list
                self.BSM_list.append(BSM)

#-------------------------------------------------------------------------

    def tmp_ID_check(self, veh_data, tp):
        """
        Checks if the BSM ID needs to be updated

        :param veh_data:  The vehicle to check
        :param tp: The time period in seconds to check
        :return:
        """

        if tp >= veh_data['BSM_time_to_ID_chg']:
            veh_data['BSM_tmp_ID'] = self.random_generator['BSM_Tmp_ID']
            #TODO updated change time to user defined with default of 300 secs
            veh_data['BSM_time_to_ID_chg'] = tp + 300.0

#-------------------------------------------------------------------------

    def Write(self, clear_buffer=False):

        if (len(self.BSM_list) >= self.msg_limit) or clear_buffer:
            df = pd.DataFrame(self.BSM_list)
            df = df.sort(['transtime', 'Vehicle_ID'])
            df['avg_accel'] = df['avg_accel'].fillna(-9999.0)
            df['heading'] = df['heading'].fillna(-9999.0)
            df['spd'] = df['spd'].map(lambda x: '%.3f' % x)
            df['heading'] = df['heading'].map(lambda x: '%.1f' % x)
            df['DSRC_MessageID'] = '{0:0>2}'.format(2)

            # Use instantaneous acceleration if available from input data, otherwise use average acceleration
            if 'instant_accel' in df.columns:
                df.rename(columns={'instant_accel': 'accel'}, inplace=True)
                accel_col_name = 'Instant_Acceleration'
            else:
                df.rename(columns={'avg_accel': 'accel'}, inplace=True)
                accel_col_name = 'Avg_Acceleration'

            df['accel'] = df['accel'].map(lambda x: '%.3f' % x)
            #reorder data elements
            df = df[self.BSM_col_order]

            df.rename(columns={
                'vehicle_ID': 'Vehicle_ID',
                'localtime': 'Time_Taken',
                'accel': accel_col_name,
                'heading': 'Heading',
                'spd': 'Speed',
                'x': 'X',
                'y': 'Y',
                'yawrate': 'YawRate'
            },
                      inplace=True)

            df.to_csv(path_or_buf=self.CF.Control["BSMTransFile"],
                      index=False,
                      mode='a',
                      header=self.headerBSM)
            self.headerBSM = False
            self.BSM_list = []
Esempio n. 10
0
class PDM(object):
    def __init__(self,
                 RandomGen_seed,
                 CF,
                 RSE_tree,
                 regions,
                 msg_limit=800000):
        """
        Initializes a PDM module

        :param RandomGen_seed: The random seed
        """
        self.random_generator = Random_generator(RandomGen_seed)
        self.CF = CF
        self.regions = regions

        self.random_generator.add_generator_int('psn', 0,
                                                32767)  #range based on J2735
        self.random_generator.add_generator_int('GapDistance',
                                                CF.Strategy["GapMinDistance"],
                                                CF.Strategy["GapMaxDistance"])
        self.random_generator.add_generator_int('GapTimeout',
                                                CF.Strategy["GapMinTime"],
                                                CF.Strategy["GapMaxTime"])

        #Buffer Manager for PDM Snapshots
        self.PDMBuffer = CLBuffer(CF.Strategy['TotalCapacity'])
        self.PDM_list = []

        #Limit of message list before printing to a file
        self.msg_limit = msg_limit
        self.headerPDM = True

        self.PDM_col_order = [
            "DSRC_MessageID",
            "x",
            "y",
            "localtime",
            "num",
            "VID",
            "PSN",
            "ss_num",
            "msg_num",
            "spd",
            "accel",
            "lastRSE",
            "type",
            "transtime",
            "transTo",
            'deltime',
            'delreason',
            'transmission_received_time',
            'link',
            'yawrate',
        ]

        if self.regions is not None:
            for Event in self.regions.Event_titles:
                self.PDM_col_order.append(Event)

    #-------------------------------------------------------------------------

    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))

    # Check Snapshot Trigger
    #-------------------------------------------------------------------------
    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 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 Write(self, clear_buffer=False, LastTP=None):

        if clear_buffer:
            for ID in self.PDMBuffer.ActiveBuffers.keys():
                self.PDMBuffer.ClearBuffer(vehicleID=ID,
                                           locT=LastTP + 2,
                                           Snapshots=self.PDM_list,
                                           reason=2,
                                           transmitted_to=-1,
                                           transTime=-1)

        if (len(self.PDM_list) >= self.msg_limit) or clear_buffer:
            df = pd.DataFrame(self.PDM_list)
            df = df.sort(['localtime', 'num', 'VID'])

            df['spd'] = df['spd'].map(lambda x: '%.3f' % x)
            df['DSRC_MessageID'] = '{0:0>2}'.format(9)

            # Use instantaneous acceleration if available from input data, otherwise use average acceleration
            if 'instant_accel' in df.columns:
                df.rename(columns={'instant_accel': 'accel'}, inplace=True)
                accel_col_name = 'Instant_Acceleration'
            else:
                df['avg_accel'] = df['avg_accel'].fillna(-9999.000)
                df.rename(columns={'avg_accel': 'accel'}, inplace=True)
                accel_col_name = 'Avg_Acceleration'

            df['accel'] = df['accel'].map(lambda x: '%.3f' % x)

            #reorder data elements
            df = df[self.PDM_col_order]

            df.rename(columns={
                'VID': 'Vehicle_ID',
                'localtime': 'Time_Taken',
                'spd': 'Speed',
                'accel': accel_col_name,
                'x': 'Location_X',
                'y': 'Location_Y',
                'lastRSE': 'Last_RSE',
                'type': 'Msg_Type',
                'transtime': 'Transmit_Time',
                'transTo': 'Transmit_To',
                'deltime': 'Delete_Time',
                'delreason': 'Delete_Reason',
                'num': 'SS_count',
                'ss_num': 'Vehicle_SS_Number',
                'msg_num': 'Message_SS_Number',
                'transmission_received_time': 'Received_Time',
            },
                      inplace=True)

            PDM_all_col = [
                'DSRC_MessageID', 'Vehicle_ID', 'Time_Taken', 'PSN', 'Speed',
                accel_col_name, 'Location_X', 'Location_Y', 'yawrate',
                'Msg_Type', 'Transmit_To', 'Transmit_Time', 'Received_Time',
                'Message_SS_Number', 'Vehicle_SS_Number', 'SS_count',
                'Delete_Time', 'Delete_Reason'
            ]
            if self.regions is not None:
                for Event in self.regions.Event_titles:
                    PDM_all_col.append(Event)

            df.to_csv(path_or_buf=self.CF.Control["PDMAllFile"],
                      index=False,
                      mode='a',
                      header=self.headerPDM,
                      columns=PDM_all_col)

            #Remove non-transmitted messages
            df = df[(df["Delete_Reason"] == 0) & (df["Transmit_Time"] != 0)]

            PDM_trans_col = [
                'DSRC_MessageID',
                'Time_Taken',
                'PSN',
                'Speed',
                accel_col_name,
                'Location_X',
                'Location_Y',
                'yawrate',
                'Msg_Type',
                'Transmit_To',
                'Transmit_Time',
                'Received_Time',
                'Message_SS_Number',
                'Vehicle_SS_Number',
            ]
            if self.regions is not None:
                for Event in self.regions.Event_titles:
                    PDM_trans_col.append(Event)

            df.to_csv(path_or_buf=self.CF.Control["PDMTransFile"],
                      index=False,
                      mode='a',
                      header=self.headerPDM,
                      columns=PDM_trans_col)

            self.headerPDM = False
            self.PDM_list = []
Esempio n. 11
0
class CAM(object):
    def __init__(self, RandomGen_seed, CF, msg_limit=800000):
        """
        Initializes a CAM module

        :param RandomGen_seed: The random seed
        """
        self.random_generator = Random_generator(RandomGen_seed)
        self.CF = CF

        #Limit of message list before printing to a file
        self.msg_limit = msg_limit

        self.CAM_list = []
        self.headerCAM = True

        self.random_generator.add_generator_int(
            'Station_ID', 1, 4294967295)  #based ITS-S standard

#-------------------------------------------------------------------------

    def CheckMessage(self, veh, tp):
        """
        Checks CAM snapshot triggers to see of a CAM should be generated

        :param veh: Vehicle to check for CAM for
        :param tp: Time period to check for CAM in
        :return: True if CAM should be generated
        """

        #Distance Change: The current position and position included in previous CAM exceeds 4 m (13.1234 feet)
        if veh['total_dist_traveled'] > veh['last_CAM_distance'] + 13.1234:
            return True

        #Speed Change: The absolute difference between current speed and speed included in previous CAM exceeds 0.5 m/s (1.11847 mph)
        if (veh['last_CAM_heading'] is None) or \
           (veh['speed'] > veh['last_CAM_speed'] + 1.11847) or \
           (veh['speed'] <= veh['last_CAM_speed'] - 1.11847):
            return True

        #Heading Change: The absolute difference between current direction of the originating ITS-S (towards North) and direction included in previous CAM exceeds 4 degrees;
        if veh['heading'] is not None:
            if veh['last_CAM_heading'] is None or (abs((
                (veh['last_CAM_heading'] - veh['heading'] + 180) % 360) - 180)
                                                   > 4):
                return True

        #Max time Change
        if tp - veh['last_CAM_time'] >= 1.0:
            return True

#-------------------------------------------------------------------------

    def GenerateTransmit(self, veh_data, transTo, tp):
        """
        Creates CAM message and adds it to the CAM list

        :param veh_data: Vehicle that is generating the message
        :param transTo: RSE that the message is transmitted to
        :param tp: The time the message is being generated
        """

        if veh_data['CAM_equipped']:
            # Hard coded values are set to CAM defaults
            CAM = {
                'Vehicle_ID': veh_data['vehicle_ID'],
                'protocolVersion': 1,
                'messageID': 2,
                'stationID': veh_data['CAM_Station_ID'],
                'generationDeltaTime':
                veh_data['time'] * 1000,  # Convert seconds to milliseconds
                'stationType': 5,
                'latitude': veh_data['location_x'],
                'longitude': veh_data['location_y'],
                'semiMajorConfidence': 4095,
                'semiMinorConfidence': 4095,
                'altitudeValue': 800001,
                'heading': veh_data['heading'],
                'headingConfidence': 127,
                'speed': (veh_data['speed'] * 0.44704),  # Convert mph to m/s
                'speedConfidence': 127,
                'driveDirection': 2,
                'curvatureValue': 30001,
                'curvatureConfidence': 7,
                'yawRateValue': veh_data['yawrate'],
                'yawRateConfidence': 8,
                'vehicleLengthValue': 1023,
                'vehicleLengthConfidence': 3,
                'vehicleWidth': 62
            }
            if veh_data['accel_instantaneous'] != None:
                CAM['longitudinalAcceleration'] = veh_data[
                    'accel_instantaneous'] * 0.3048  # Convert f/s2 to m/s2
            else:
                CAM['longitudinalAcceleration'] = 161

            #Add CAM to the Main CAM list
            self.CAM_list.append(CAM)

            veh_data['last_CAM_distance'] = veh_data['total_dist_traveled']
            veh_data['last_CAM_speed'] = veh_data['speed']
            veh_data['last_CAM_heading'] = veh_data['heading']
            veh_data['last_CAM_time'] = tp

#-------------------------------------------------------------------------

    def Write(self, clear_all=False):

        if (len(self.CAM_list) >= self.msg_limit) or clear_all:
            col = [
                'Vehicle_ID', 'protocolVersion', 'messageID', 'stationID',
                'generationDeltaTime', 'stationType', 'latitude', 'longitude',
                'semiMajorConfidence', 'semiMinorConfidence', 'altitudeValue',
                'heading', 'headingConfidence', 'speed', 'speedConfidence',
                'driveDirection', 'longitudinalAcceleration', 'curvatureValue',
                'curvatureConfidence', 'yawRateValue', 'yawRateConfidence',
                'vehicleLengthValue', 'vehicleLengthConfidence', 'vehicleWidth'
            ]

            df_CAMs = pd.DataFrame(self.CAM_list, columns=col)
            df_CAMs['speed'] = df_CAMs['speed'].map(lambda x: '%.3f' % x)
            df_CAMs['yawRateValue'] = df_CAMs['yawRateValue'].fillna(32767)
            df_CAMs['heading'] = df_CAMs['heading'].fillna(360)

            df_CAMs = df_CAMs.sort(['generationDeltaTime'])
            df_CAMs.to_csv(path_or_buf=self.CF.Control["CAMTransFile"],
                           index=False,
                           mode='a',
                           header=self.headerCAM)
            self.headerCAM = False
            self.CAM_list = []
Esempio n. 12
0
class TCA_Algorithm:
    def __init__(self,
                 CF,
                 RSEs,
                 RSE_tree,
                 RandomGen_seed,
                 Regions,
                 SPOT_tree,
                 msg_limit=800000,
                 link_included=False):
        """
        Initializes TCA_Algorithm module

        :param CF: Dictionary of Control File defined attributes
        :param RSEs: List of RSEs
        :param RSE_tree: Location tree of RSEs
        :param RandomGen: Seed value for randomization
        :param Regions: Regions class
        :param SPOT_tree: Location tree of SPOT devices
        :param msg_limit: Limit of snapshot list before outputting to a file
        """

        self.RSEs = RSEs
        self.RSE_tree = RSE_tree
        self.CF = CF
        self.regions = Regions

        self.random_generator = Random_generator(RandomGen_seed)

        self.random_generator.add_generator_int('LossPercent', 1, 100)
        self.random_generator.add_generator_int('TypePercent', 1, 100)

        self.BSM = BSM(self.random_generator.generate_seed(), self.CF,
                       self.regions)
        self.CAM = CAM(self.random_generator.generate_seed(), self.CF)
        self.SPOT = SPOT(self.random_generator.generate_seed(), self.CF,
                         SPOT_tree)
        self.PDM = PDM(self.random_generator.generate_seed(), self.CF,
                       RSE_tree, self.regions)

        self.msgs = {
            'BSM': self.BSM,
            'CAM': self.CAM,
            'SPOT': self.SPOT,
            'PDM': self.PDM
        }

        self.tbl = DataStorage(self.random_generator,
                               accel_included=True,
                               link_included=link_included)

        #Each Vehicle RSE list
        self.VehicleRSE = {}

        #Limit of message list before printing to a file
        self.msg_limit = msg_limit

#-------------------------------------------------------------------------

    def pull_veh_data(self, veh, tp):
        """
        Returns vehicle data for specified time period.

        :param veh: The vehicle id for information to be retrieved
        :param tp: The time in seconds for information to be retrieved
        :return: The vehicle record for the vehicle at the specified time
        """

        vehicle_data = []

        for v in veh:
            vehicle_data.append(
                self.tbl.pull_veh_data(veh=v,
                                       CF=self.CF,
                                       RandomGen=self.random_generator,
                                       Regions=self.regions,
                                       tp=tp,
                                       msgs=self.msgs))
        return vehicle_data
        # return self.tbl.pull_veh_data(veh = veh, CF = self.CF, RandomGen = self.random_generator, Regions = self.regions, tp = tp)

    #-------------------------------------------------------------------------
    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)

    #-------------------------------------------------------------------------
    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'])