def from_dict(cls, dict: Dict):
     road_bbox = RoadBoundingBox(dict['road_bbox_size'])
     res = BeamNGMember([tuple(t) for t in dict['control_nodes']],
                        [tuple(t) for t in dict['sample_nodes']],
                        dict['num_spline_nodes'], road_bbox)
     res.distance_to_boundary = dict['distance_to_boundary']
     return res
Example #2
0
 def __init__(self,
              num_control_nodes=15,
              max_angle=MAX_ANGLE,
              seg_length=SEG_LENGTH,
              num_spline_nodes=NUM_SPLINE_NODES,
              initial_node=(0.0, 0.0, -28.0, 8.0),
              bbox_size=(-250, 0, 250, 500)):
     assert num_control_nodes > 1 and num_spline_nodes > 0
     assert 0 <= max_angle <= 360
     assert seg_length > 0
     assert len(initial_node) == 4 and len(bbox_size) == 4
     self.num_control_nodes = num_control_nodes
     self.num_spline_nodes = num_spline_nodes
     self.initial_node = initial_node
     self.max_angle = max_angle
     self.seg_length = seg_length
     self.road_bbox = RoadBoundingBox(bbox_size)
     assert not self.road_bbox.intersects_vertices(
         self._get_initial_point())
     assert self.road_bbox.intersects_sides(self._get_initial_point())
Example #3
0
class RoadGenerator:
    """Generate random roads given the configuration parameters"""

    MAX_ANGLE = 80
    NUM_SPLINE_NODES = 20
    NUM_INITIAL_SEGMENTS_THRESHOLD = 2
    NUM_UNDO_ATTEMPTS = 20
    SEG_LENGTH = 25

    def __init__(self,
                 num_control_nodes=15,
                 max_angle=MAX_ANGLE,
                 seg_length=SEG_LENGTH,
                 num_spline_nodes=NUM_SPLINE_NODES,
                 initial_node=(0.0, 0.0, -28.0, 8.0),
                 bbox_size=(-250, 0, 250, 500)):
        assert num_control_nodes > 1 and num_spline_nodes > 0
        assert 0 <= max_angle <= 360
        assert seg_length > 0
        assert len(initial_node) == 4 and len(bbox_size) == 4
        self.num_control_nodes = num_control_nodes
        self.num_spline_nodes = num_spline_nodes
        self.initial_node = initial_node
        self.max_angle = max_angle
        self.seg_length = seg_length
        self.road_bbox = RoadBoundingBox(bbox_size)
        assert not self.road_bbox.intersects_vertices(
            self._get_initial_point())
        assert self.road_bbox.intersects_sides(self._get_initial_point())

    def generate_control_nodes(self,
                               visualise=False,
                               attempts=NUM_UNDO_ATTEMPTS) -> List[Tuple4F]:
        condition = True
        while condition:
            nodes = [self._get_initial_control_node(), self.initial_node]

            # i is the number of valid generated control nodes.
            i = 0

            # When attempt >= attempts and the skeleton of the road is still invalid,
            # the construction of the skeleton starts again from the beginning.
            # attempt is incremented every time the skeleton is invalid.
            attempt = 0

            while i < self.num_control_nodes and attempt <= attempts:
                nodes.append(
                    self._get_next_node(nodes[-2], nodes[-1],
                                        self._get_next_max_angle(i)))
                road_polygon = RoadPolygon.from_nodes(nodes)

                # budget is the number of iterations used to attempt to add a valid next control node
                # before also removing the previous control node.
                budget = self.num_control_nodes - i
                assert budget >= 1

                if visualise:
                    fig = plot_road_bbox(self.road_bbox)
                    plot_road_polygon(road_polygon,
                                      title="RoadPolygon i=%s" % i,
                                      fig=fig)

                intersect_boundary = self.road_bbox.intersects_boundary(
                    road_polygon.polygons[-1])
                is_valid = road_polygon.is_valid() and (
                    ((i == 0) and intersect_boundary) or
                    ((i > 0) and not intersect_boundary))
                while not is_valid and budget > 0:
                    nodes.pop()
                    budget -= 1
                    attempt += 1

                    nodes.append(
                        self._get_next_node(nodes[-2], nodes[-1],
                                            self._get_next_max_angle(i)))
                    road_polygon = RoadPolygon.from_nodes(nodes)

                    intersect_boundary = self.road_bbox.intersects_boundary(
                        road_polygon.polygons[-1])
                    is_valid = road_polygon.is_valid() and (
                        ((i == 0) and intersect_boundary) or
                        ((i > 0) and not intersect_boundary))
                    if visualise:
                        fig = plot_road_bbox(self.road_bbox)
                        plot_road_polygon(road_polygon,
                                          title="RoadPolygon i=%s" % i,
                                          fig=fig)

                if is_valid:
                    i += 1
                else:
                    assert budget == 0
                    nodes.pop()
                    if len(nodes) > 2:
                        nodes.pop()
                        i -= 1

                assert RoadPolygon.from_nodes(nodes).is_valid()
                assert 0 <= i <= self.num_control_nodes
            print(len(nodes))
            print(self.num_control_nodes)
            # The road generation ends when there are the control nodes plus the two extra nodes needed by the current Catmull-Rom model
            if len(nodes) - 2 == self.num_control_nodes:
                condition = False
        return nodes

    def generate(self, visualise=False) -> BeamNGMember:
        control_nodes = self.generate_control_nodes(visualise)
        sample_nodes = catmull_rom(control_nodes, self.num_spline_nodes)
        road = BeamNGMember(control_nodes, sample_nodes, self.num_spline_nodes,
                            self.road_bbox)
        while not road.is_valid():
            control_nodes = self.generate_control_nodes(visualise)
            sample_nodes = catmull_rom(control_nodes, self.num_spline_nodes)
            road = BeamNGMember(control_nodes, sample_nodes,
                                self.num_spline_nodes, self.road_bbox)
        return road

    def _get_initial_point(self) -> Point:
        return Point(self.initial_node[0], self.initial_node[1])

    def _get_initial_control_node(self) -> Tuple4F:
        x0, y0, z, width = self.initial_node
        x, y = self._get_next_xy(x0, y0, 270)
        assert not (self.road_bbox.bbox.contains(Point(x, y)))

        return x, y, z, width

    def _get_next_node(self, first_node, second_node: Tuple4F,
                       max_angle) -> Tuple4F:
        v = np.subtract(second_node, first_node)
        start_angle = int(np.degrees(np.arctan2(v[1], v[0])))
        angle = randint(start_angle - max_angle, start_angle + max_angle)
        x0, y0, z0, width0 = second_node
        x1, y1 = self._get_next_xy(x0, y0, angle)
        return x1, y1, z0, width0

    def _get_next_xy(self, x0: float, y0: float, angle: float) -> Tuple2F:
        angle_rad = math.radians(angle)
        return x0 + self.seg_length * math.cos(
            angle_rad), y0 + self.seg_length * math.sin(angle_rad)

    def _get_next_max_angle(self,
                            i: int,
                            threshold=NUM_INITIAL_SEGMENTS_THRESHOLD) -> float:
        if i < threshold or i == self.num_control_nodes - 1:
            return 0
        else:
            return self.max_angle
Example #4
0
def initial_population_generator(path, config, problem):
    all_roads = [
        filename
        for filename in glob.glob(str(path) + "\*.json", recursive=True)
    ]
    type = config.Feature_Combination
    shuffle(all_roads)

    roads = all_roads

    original_set = list()

    individuals = []
    popsize = config.POPSIZE

    for road in roads:
        with open(road) as json_file:
            data = json.load(json_file)
            sample_nodes = data["road"]["nodes"]
            for node in sample_nodes:
                node[2] = -28.0
            sample_nodes = np.array(sample_nodes)
            records = data["records"]

        bbox_size = (-250.0, 0.0, 250.0, 500.0)
        road_bbox = RoadBoundingBox(bbox_size)
        member = BeamNGMember(data["control_nodes"],
                              [tuple(t) for t in sample_nodes], 20, road_bbox)
        member.config = config
        member.problem = problem
        simulation_id = time.strftime('%Y-%m-%d--%H-%M-%S', time.localtime())
        sim_name = member.config.simulation_name.replace(
            '$(id)', simulation_id)
        simulation_data = SimulationData(sim_name)
        states = []
        for record in records:
            state = VehicleState(timer=record["timer"],
                                 pos=record["pos"],
                                 dir=record["dir"],
                                 vel=record["vel"],
                                 steering=record["steering"],
                                 steering_input=record["steering_input"],
                                 brake=record["brake"],
                                 brake_input=record["brake_input"],
                                 throttle=record["throttle"],
                                 throttle_input=record["throttle_input"],
                                 wheelspeed=record["wheelspeed"],
                                 vel_kmh=record["vel_kmh"])

            sim_data_record = SimulationDataRecord(
                **state._asdict(),
                is_oob=record["is_oob"],
                oob_counter=record["oob_counter"],
                max_oob_percentage=record["max_oob_percentage"],
                oob_distance=record["oob_distance"])
            states.append(sim_data_record)

        simulation_data.params = SimulationParams(
            beamng_steps=data["params"]["beamng_steps"],
            delay_msec=int(data["params"]["delay_msec"]))

        simulation_data.road = DecalRoad.from_dict(data["road"])
        simulation_data.info = SimulationInfo()
        simulation_data.info.start_time = data["info"]["start_time"]
        simulation_data.info.end_time = data["info"]["end_time"]
        simulation_data.info.elapsed_time = data["info"]["elapsed_time"]
        simulation_data.info.success = data["info"]["success"]
        simulation_data.info.computer_name = data["info"]["computer_name"]
        simulation_data.info.id = data["info"]["id"]

        simulation_data.states = states
        if len(states) > 0:
            member.distance_to_boundary = simulation_data.min_oob_distance()
            member.simulation = simulation_data
            individual: BeamNGIndividual = BeamNGIndividual(member, config)
        #individual.evaluate()
        b = tuple()
        feature_dimensions = generate_feature_dimension(type)
        for ft in feature_dimensions:
            i = feature_simulator(ft.feature_simulator, individual)
            b = b + (i, )
        individuals.append([b, road, individual])

    starting_point = choice(individuals)
    original_set.append(starting_point)

    i = 0
    best_ind = individuals[0]
    while i < popsize - 1:
        max_dist = 0
        for ind in individuals:
            dist = get_min_distance_from_set(ind, original_set)
            if dist > max_dist:
                max_dist = dist
                best_ind = ind
        original_set.append(best_ind)
        i += 1

    base = config.initial_population_folder
    storage = SeedStorage(base)
    for index, road in enumerate(original_set):
        dst = storage.get_path_by_index(index + 1)
        ind = road[2]
        #copy(road[1], dst)
        with open(road[1]) as ff:
            json_file = json.load(ff)
        with open(dst, 'w') as f:
            f.write(
                json.dumps({
                    "control_nodes":
                    json_file["control_nodes"],
                    ind.m.simulation.f_params:
                    ind.m.simulation.params._asdict(),
                    ind.m.simulation.f_info:
                    ind.m.simulation.info.__dict__,
                    ind.m.simulation.f_road:
                    ind.m.simulation.road.to_dict(),
                    ind.m.simulation.f_records:
                    [r._asdict() for r in ind.m.simulation.states]
                }))
Example #5
0
class RoadGenerator:
    """A class that is able to generate random roads given some parameters, such as
    the number of segments."""

    # Initial setup
    #num_control_nodes = 15
    #INITIAL_SEGMENTS_MAX_ANGLE = 90
    #NUM_INITIAL_SEGMENTS_THRESHOLD = 4
    #NUM_UNDO_ATTEMPTS = 20
    #max_angle=360
    #seg_length=50
    #num_spline_nodes=20
    #START_ANGLE = 45

    START_ANGLE = 60
    INITIAL_SEGMENTS_MAX_ANGLE = 60
    #MAX_ANGLE = 160
    MAX_ANGLE = 60

    NUM_SPLINE_NODES = 20
    NUM_INITIAL_SEGMENTS_THRESHOLD = 4
    NUM_UNDO_ATTEMPTS = 20
    SEG_LENGTH = 25

    def __init__(self,
                 num_control_nodes=15,
                 max_angle=MAX_ANGLE,
                 seg_length=SEG_LENGTH,
                 num_spline_nodes=NUM_SPLINE_NODES,
                 initial_node=(0.0, 0.0, -28.0, 8.0),
                 bbox_size=(-250, 0, 250, 500)):
        assert num_control_nodes > 1 and num_spline_nodes > 0
        assert 0 <= max_angle <= 360
        assert seg_length > 0
        assert len(initial_node) == 4 and len(bbox_size) == 4
        self.num_control_nodes = num_control_nodes
        self.num_spline_nodes = num_spline_nodes
        self.initial_node = initial_node
        self.max_angle = max_angle
        self.seg_length = seg_length
        self.road_bbox = RoadBoundingBox(bbox_size)
        assert not self.road_bbox.intersects_vertices(
            self._get_initial_point())
        assert self.road_bbox.intersects_sides(self._get_initial_point())

    def generate_control_nodes(self,
                               visualise=False,
                               attempts=NUM_UNDO_ATTEMPTS) -> List[Tuple4F]:
        while True:
            nodes = [self._get_initial_control_node(), self.initial_node]

            # i is the number of valid generated control nodes.
            i = 0

            # When attempt >= attempts and the skeleton of the road is still invalid,
            # the construction of the skeleton starts again from the beginning.
            # attempt is incremented every time the skeleton is invalid.
            attempt = 0

            while i < self.num_control_nodes:
                nodes.append(
                    self._get_next_node(nodes[-1],
                                        self._get_next_max_angle(i)))
                road_polygon = RoadPolygon.from_nodes(nodes)

                if visualise:
                    fig = plot_road_bbox(self.road_bbox)
                    plot_road_polygon(road_polygon,
                                      title="RoadPolygon i=%s" % i,
                                      fig=fig)

                # budget is the number of iterations used to attempt to add a valid next control node
                # before also removing the previous control node.
                budget = self.num_control_nodes - i
                assert budget >= 1

                is_valid = road_polygon.is_valid()
                while not is_valid and budget > 0:
                    nodes.pop()
                    budget = budget - 1
                    attempt += 1

                    nodes.append(
                        self._get_next_node(nodes[-1],
                                            self._get_next_max_angle(i)))
                    road_polygon = RoadPolygon.from_nodes(nodes)
                    is_valid = road_polygon.is_valid()

                    if visualise:
                        fig = plot_road_bbox(self.road_bbox)
                        plot_road_polygon(road_polygon,
                                          title="RoadPolygon i=%s" % i,
                                          fig=fig)

                if not is_valid:
                    assert budget == 0
                    nodes.pop()
                    if len(nodes) > 2:
                        nodes.pop()
                        i -= 1
                else:
                    i += 1

                assert RoadPolygon.from_nodes(nodes).is_valid()
                assert 0 <= i <= self.num_control_nodes

                if i >= 2 and self.road_bbox.intersects_boundary(
                        road_polygon.polygons[-1]):
                    break

                if attempt >= attempts:
                    break

            if attempt < attempts:
                return nodes

    def generate(self, visualise=False) -> BeamNGMember:
        control_nodes = self.generate_control_nodes(visualise)
        sample_nodes = catmull_rom(control_nodes, self.num_spline_nodes)
        road = BeamNGMember(control_nodes, sample_nodes, self.num_spline_nodes,
                            self.road_bbox)
        while not road.is_valid():
            control_nodes = self.generate_control_nodes(visualise)
            sample_nodes = catmull_rom(control_nodes, self.num_spline_nodes)
            road = BeamNGMember(control_nodes, sample_nodes,
                                self.num_spline_nodes, self.road_bbox)
        return road

    def _get_initial_point(self) -> Point:
        return Point(self.initial_node[0], self.initial_node[1])

    def _get_initial_control_node(self) -> Tuple4F:
        init_max_angle = self._get_next_max_angle(0)
        x, y, z, width = self._get_next_node(self.initial_node,
                                             init_max_angle,
                                             start_angle=240)
        #x, y, z, width = self._get_next_node(self.initial_node, self.max_angle)
        while self.road_bbox.bbox.contains(Point(x, y)):
            #x, y, _, _ = self._get_next_node(self.initial_node, self.max_angle)
            x, y, _, _ = self._get_next_node(self.initial_node,
                                             init_max_angle,
                                             start_angle=240)
        return x, y, z, width

    def _get_next_node(self,
                       initial_node: Tuple4F,
                       max_angle,
                       start_angle=START_ANGLE) -> Tuple4F:
        angle = randint(start_angle, max_angle + start_angle)
        x0, y0, z0, width0 = initial_node
        x1, y1 = self._get_next_xy(x0, y0, angle)
        return x1, y1, z0, width0

    def _get_next_xy(self, x0: float, y0: float, angle: float) -> Tuple2F:
        angle_rad = math.radians(angle)
        return x0 + self.seg_length * math.cos(
            angle_rad), y0 + self.seg_length * math.sin(angle_rad)

    def _get_next_max_angle(self,
                            i: int,
                            threshold=NUM_INITIAL_SEGMENTS_THRESHOLD) -> float:
        if i < threshold:
            return self.INITIAL_SEGMENTS_MAX_ANGLE
        else:
            return self.max_angle
Example #6
0
    def generate_random_solution_without_sim(self):
        """
        To ease the bootstrap of the algorithm, we can generate
        the first solutions in the feature space, so that we start
        filling the bins
        """
        # "Generate random solution"
        path = self.problem._seed_pool_strategy.get_seed()

        with open(path) as json_file:
            data = json.load(json_file)
            sample_nodes = data["road"]["nodes"]
            for node in sample_nodes:
                node[2] = -28.0
            sample_nodes = np.array(sample_nodes)
            records = data["records"]

        bbox_size = (-250.0, 0.0, 250.0, 500.0)
        road_bbox = RoadBoundingBox(bbox_size)
        member = BeamNGMember(data["control_nodes"],
                              [tuple(t) for t in sample_nodes],
                              len(data["control_nodes"]), road_bbox)
        member.config = self.config
        member.problem = self.problem
        simulation_id = time.strftime('%Y-%m-%d--%H-%M-%S', time.localtime())
        sim_name = member.config.simulation_name.replace(
            '$(id)', simulation_id)
        simulation_data = SimulationData(sim_name)
        states = []
        for record in records:
            state = VehicleState(timer=record["timer"],
                                 pos=record["pos"],
                                 dir=record["dir"],
                                 vel=record["vel"],
                                 steering=record["steering"],
                                 steering_input=record["steering_input"],
                                 brake=record["brake"],
                                 brake_input=record["brake_input"],
                                 throttle=record["throttle"],
                                 throttle_input=record["throttle_input"],
                                 wheelspeed=record["wheelspeed"],
                                 vel_kmh=record["vel_kmh"])

            sim_data_record = SimulationDataRecord(
                **state._asdict(),
                is_oob=record["is_oob"],
                oob_counter=record["oob_counter"],
                max_oob_percentage=record["max_oob_percentage"],
                oob_distance=record["oob_distance"])
            states.append(sim_data_record)

        simulation_data.params = SimulationParams(
            beamng_steps=data["params"]["beamng_steps"],
            delay_msec=int(data["params"]["delay_msec"]))

        simulation_data.road = DecalRoad.from_dict(data["road"])
        simulation_data.info = SimulationInfo()
        simulation_data.info.start_time = data["info"]["start_time"]
        simulation_data.info.end_time = data["info"]["end_time"]
        simulation_data.info.elapsed_time = data["info"]["elapsed_time"]
        simulation_data.info.success = data["info"]["success"]
        simulation_data.info.computer_name = data["info"]["computer_name"]
        simulation_data.info.id = data["info"]["id"]

        simulation_data.states = states
        if len(states) > 0:
            member.distance_to_boundary = simulation_data.min_oob_distance()
            member.simulation = simulation_data
            individual: BeamNGIndividual = BeamNGIndividual(
                member, self.config)
            individual.seed = path
        else:
            print("*********Bug************")
        return individual