예제 #1
0
class PerfectLaneDetectionOperator(erdos.Operator):
    """Operator that uses the simulator to perfectly detect lanes.

    Args:
        pose_stream (:py:class:`erdos.ReadStream`): Stream on which pose
            info is received.
        open_drive_stream (:py:class:`erdos.ReadStream`): Stream on which open
            drive string representations are received. The operator can
            construct HDMaps out of the open drive strings.
        detected_lane_stream (:py:class:`erdos.WriteStream`): Stream on which
            the operator writes
            :py:class:`~pylot.perception.messages.LanesMessage` messages.
        flags (absl.flags): Object to be used to access absl flags.
    """
    def __init__(self, pose_stream: ReadStream, open_drive_stream: ReadStream,
                 center_camera_stream: ReadStream,
                 detected_lane_stream: WriteStream, flags):
        pose_stream.add_callback(self.on_pose_update)
        center_camera_stream.add_callback(self.on_bgr_camera_update)
        erdos.add_watermark_callback([pose_stream, center_camera_stream],
                                     [detected_lane_stream],
                                     self.on_position_update)
        self._flags = flags
        self._logger = erdos.utils.setup_logging(self.config.name,
                                                 self.config.log_file_name)
        self._logger_lane = erdos.utils.setup_logging(
            self.config.name + "_lane", self.config.log_file_name + "_lane")
        self._bgr_msgs = deque()
        self._pose_msgs = deque()
        self._frame_cnt = 0

    @staticmethod
    def connect(pose_stream: ReadStream, open_drive_stream: ReadStream,
                center_camera_stream: ReadStream):
        detected_lane_stream = erdos.WriteStream()
        return [detected_lane_stream]

    def destroy(self):
        self._logger.warn('destroying {}'.format(self.config.name))

    def run(self):
        # Run method is invoked after all operators finished initializing.
        # Thus, we're sure the world is up-to-date here.
        if self._flags.execution_mode == 'simulation':
            from pylot.map.hd_map import HDMap
            from pylot.simulation.utils import get_map
            self._map = HDMap(
                get_map(self._flags.simulator_host, self._flags.simulator_port,
                        self._flags.simulator_timeout),
                self.config.log_file_name)
            from pylot.simulation.utils import get_world
            _, self._world = get_world(self._flags.simulator_host,
                                       self._flags.simulator_port,
                                       self._flags.simulator_timeout)

    def on_opendrive_map(self, msg: Message):
        """Invoked whenever a message is received on the open drive stream.

        Args:
            msg (:py:class:`~erdos.message.Message`): Message that contains
                the open drive string.
        """
        self._logger.debug('@{}: received open drive message'.format(
            msg.timestamp))
        from pylot.simulation.utils import map_from_opendrive
        self._map = map_from_opendrive(msg.data)

    def on_bgr_camera_update(self, msg: Message):
        self._logger.debug('@{}: received BGR frame'.format(msg.timestamp))
        self._bgr_msgs.append(msg)

    def on_pose_update(self, msg: Message):
        self._logger.debug('@{}: received pose message'.format(msg.timestamp))
        self._pose_msgs.append(msg)

    @erdos.profile_method()
    def on_position_update(self, timestamp: Timestamp,
                           detected_lane_stream: WriteStream):
        """Invoked on the receipt of an update to the position of the vehicle.

        Uses the position of the vehicle to get future waypoints and draw
        lane markings using those waypoints.

        Args:
            pose_msg: Contains the current location of the ego vehicle.
        """
        self._logger.debug('@{}: received watermark'.format(timestamp))
        if timestamp.is_top:
            return
        bgr_msg = self._bgr_msgs.popleft()
        pose_msg = self._pose_msgs.popleft()
        vehicle_location = pose_msg.data.transform.location
        self._frame_cnt += 1
        if self._map:
            lanes = self._map.get_all_lanes(vehicle_location)
            if self._flags.log_lane_detection_camera:
                camera_setup = bgr_msg.frame.camera_setup
                frame = np.zeros((camera_setup.height, camera_setup.width),
                                 dtype=np.dtype("uint8"))
                binary_frame = frame.copy()
                for lane in lanes:
                    lane.collect_frame_data(frame,
                                            binary_frame,
                                            camera_setup,
                                            inverse_transform=pose_msg.data.
                                            transform.inverse_transform())
                self._logger.debug('@{}: detected {} lanes'.format(
                    bgr_msg.timestamp, len(lanes)))
                if self._frame_cnt % self._flags.log_every_nth_message == 0:
                    instance_file_name = os.path.join(
                        self._flags.data_path,
                        '{}-{}.png'.format("lane",
                                           bgr_msg.timestamp.coordinates[0]))
                    binary_file_name = os.path.join(
                        self._flags.data_path,
                        '{}-{}.png'.format("binary_lane",
                                           bgr_msg.timestamp.coordinates[0]))
                    instance_img = Image.fromarray(frame)
                    binary_img = Image.fromarray(binary_frame)
                    instance_img.save(instance_file_name)
                    binary_img.save(binary_file_name)
                    self._logger_lane.debug(
                        '@{}: Created binary lane and lane images in {}'.
                        format(pose_msg.timestamp, self._flags.data_path))
            else:
                for lane in lanes:
                    lane.draw_on_world(self._world)
        else:
            self._logger.debug('@{}: map is not ready yet'.format(
                pose_msg.timestamp))
            lanes = []
        output_msg = LanesMessage(pose_msg.timestamp, lanes)
        detected_lane_stream.send(output_msg)
예제 #2
0
class PerfectLaneDetectionOperator(erdos.Operator):
    """Operator that uses the Carla world to perfectly detect lanes.

    Args:
        pose_stream (:py:class:`erdos.ReadStream`): Stream on which pose
            info is received.
        open_drive_stream (:py:class:`erdos.ReadStream`): Stream on which open
            drive string representations are received. The operator can
            construct HDMaps out of the open drive strings.
        detected_lane_stream (:py:class:`erdos.WriteStream`): Stream on which
            the operator writes
            :py:class:`~pylot.perception.messages.LanesMessage` messages.
        flags (absl.flags): Object to be used to access absl flags.
    """
    def __init__(self, pose_stream: ReadStream, open_drive_stream: ReadStream,
                 detected_lane_stream: WriteStream, flags):
        pose_stream.add_callback(self.on_position_update,
                                 [detected_lane_stream])
        self._flags = flags
        self._logger = erdos.utils.setup_logging(self.config.name,
                                                 self.config.log_file_name)

    @staticmethod
    def connect(pose_stream: ReadStream, open_drive_stream: ReadStream):
        detected_lane_stream = erdos.WriteStream()
        return [detected_lane_stream]

    def run(self):
        # Run method is invoked after all operators finished initializing,
        # including the CARLA operator, which reloads the world. Thus, if
        # we get the world here we're sure it is up-to-date.
        if self._flags.execution_mode == 'simulation':
            from pylot.map.hd_map import HDMap
            from pylot.simulation.utils import get_map
            self._map = HDMap(
                get_map(self._flags.carla_host, self._flags.carla_port,
                        self._flags.carla_timeout), self.config.log_file_name)
            from pylot.simulation.utils import get_world
            _, self._world = get_world(self._flags.carla_host,
                                       self._flags.carla_port,
                                       self._flags.carla_timeout)

    def on_opendrive_map(self, msg: Message):
        """Invoked whenever a message is received on the open drive stream.

        Args:
            msg (:py:class:`~erdos.message.Message`): Message that contains
                the open drive string.
        """
        self._logger.debug('@{}: received open drive message'.format(
            msg.timestamp))
        try:
            import carla
        except ImportError:
            raise Exception('Error importing carla.')
        self._logger.info('Initializing HDMap from open drive stream')
        from pylot.map.hd_map import HDMap
        self._map = HDMap(carla.Map('map', msg.data))

    @erdos.profile_method()
    def on_position_update(self, pose_msg: Message,
                           detected_lane_stream: WriteStream):
        """Invoked on the receipt of an update to the position of the vehicle.

        Uses the position of the vehicle to get future waypoints and draw
        lane markings using those waypoints.

        Args:
            pose_msg: Contains the current location of the ego vehicle.
        """
        self._logger.debug('@{}: received pose message'.format(
            pose_msg.timestamp))
        vehicle_location = pose_msg.data.transform.location
        if self._map:
            lanes = self._map.get_all_lanes(vehicle_location)
            for lane in lanes:
                lane.draw_on_world(self._world)
        else:
            self._logger.debug('@{}: map is not ready yet'.format(
                pose_msg.timestamp))
            lanes = []
        output_msg = LanesMessage(pose_msg.timestamp, lanes)
        detected_lane_stream.send(output_msg)