def __init__(self, car_model, estimator_type): ''' Allowable combinations of car_model and estimator_type are ("simple", "fcn") ("simple", "analytical") ("complex", "fcn") No analytical solution for complex internal model. ''' if (estimator_type not in {"analytical", "fcn"}): raise Exception( f"Illegal estimator_type, f{estimator_type}, must be 'analytical' or 'fcn'" ) if (car_model not in {"simple", "complex"}): raise Exception( f"Illegal estimator_type, f{estimator_type}, must be 'simple' or 'complex'" ) if (estimator_type == 'analytical' and car_model == 'complex'): raise Exception("No analytical estimator for complex car model") self.estimator_type = estimator_type ''' If using a fcn load parameters from Brakind Distance directory two inputs (intitial velocity, stopping distance), output must be between 0 and 1 ''' if (estimator_type == "fcn"): self.fcn = nn.fcn(model_name=os.path.join(self.bd_fp(), f"{car_model}_bd"), num_inputs=2, out_range=(0, 1)) ''' If using analytical approach get coefficients from controller model (pedal weights, friction constant, and rolling bias) ''' if (estimator_type == "analytical"): ci = controller_model.Car_Interface() self.brake_weight = ci.brake_weight self.rolling_bias = ci.rolling_bias self.friction_constant = ci.friction_constant
def __init__(self, mode, car_model="simple"): self.mode = mode self.car_model = car_model ''' Initialize the interface that will be used to manage motion dynamics. ''' self.interface = controller.Car_Interface(car_model) ''' If we are testing system ID then we will initialize an instance of the controller model, which we will interact with side by side along with the actual interface. ''' if (self.mode == "sysID_test"): import car_iface.controller_model as controller_model self.interface_model = controller_model.Car_Interface(car_model) ''' pedal_type intitialized to None peda_type can later be "accelerate", "brake", or "release" amount is relevant for both "accelerate" and "brake" and represents the magnitude of pedal depression. TIME_UNIT is a constant and represents how often we update the car's state. ''' self.pedal_type = None self.amount = 0.0 self.TIME_UNIT = self.interface.dt ''' Build up is used to allow for increasing pedal depression the longer you hold a control. That is when you press as you hold "accelerate" or "brake" the pedal depression will increase from 0 to 1 over time. When we are doing SystemID we will not follow the build up principle and apply random depression quantities, to make sure we are covering all possible scenarios. ''' if (not (self.mode == "sysID_data" or self.mode == "sysID_test")): self.build_up = 0 self.bu_to_amt = lambda: 1 - 1 / ((self.build_up / 20) + 1) ''' If we are collecting data for System ID we intialize a file path for where we will save the data points (including reference to the internal car model). If there is a preexisting data points file we will load it and add to it, as opposed to starting from scratch. We will also keep track how long ago we last saved the collected data. ''' if (self.mode == "sysID_data"): import settings cur_dir = os.path.dirname(__file__) internal_path = os.path.join(cur_dir, '../../internal_only/sysid/') if settings.use_internal_if_available and os.path.exists( internal_path): self.data_points_file_path = internal_path else: if (car_model == "simple"): self.data_points_file_path = os.path.join( cur_dir, '../hw/sysid/') elif (car_model == "complex"): self.data_points_file_path = os.path.join( cur_dir, '../demos/week3/') self.data_points_file_path = os.path.join( self.data_points_file_path, f'{car_model}_data_points.json') if (os.path.exists(self.data_points_file_path)): self.data_points = json.load( open(self.data_points_file_path, "r")) else: self.data_points = [] self.saved_data = 0 ''' If we are testing System ID we will keep track of a rolling average of the discrepancy between the actual controller and the controller model. The average will be taken over the last ERROR_WINDOW times. The maximum average error will be tracked as well. ''' if (self.mode == "sysID_test"): self.ERROR_WINDOW = 100 self.errors = [] self.max_mean_error = None