def __init__(self, racecar_name, racecar_info, race_type): """ To capture the video of evaluation done during the training phase Args: racecar_info (dict): Information of the agent """ self.racecar_info = racecar_info racecar_index = get_racecar_idx(racecar_name) self.racecar_index = racecar_index if racecar_index else 0 # Store the font which we will use to write the phase with self.training_phase_font = utils.get_font('Amazon_Ember_RgIt', 35) # The track image as iconography self.track_icongraphy_img = utils.get_track_iconography_image() # Track image offset self.track_loc_offset = XYPixelLoc.TRACK_IMG_WITHOUT_OFFSET_LOC.value # Gradient overlay image width, height = IconographicImageSize.FULL_IMAGE_SIZE.value image = np.zeros(height * width * 4) image.resize(height, width, 4) self.gradient_img = self._plot_track_on_gradient(image) self.gradient_alpha_rgb_mul, self.one_minus_gradient_alpha = utils.get_gradient_values( self.gradient_img) # Top camera information top_camera_info = utils.get_top_camera_info() self.top_view_graphics = TopViewGraphics( top_camera_info.horizontal_fov, top_camera_info.padding_pct, top_camera_info.image_width, top_camera_info.image_height, racecar_info)
def test_get_racecar_idx(racecar_name, racecar_num): """This function checks the functionality of get_racecar_idx function in markov/utils.py Args: racecar_name (String): The name of racecar racecar_num: If single car race, returns None else returns the racecar number """ assert utils.get_racecar_idx(racecar_name) == racecar_num
def start_race(self): """ Start the race (evaluation) for the current racer. """ LOG.info( "[virtual event manager] Starting race for racer %s", self._current_racer.racerAlias ) # update the car on current model if does not use f1 or tron type of shell if const.F1 not in self._body_shell_type.lower(): self._model_updater.update_model_color( self._current_car_model_state.model_name, self._current_racer.carConfig.carColor ) # send request if self._is_save_mp4_enabled: self._subscribe_to_save_mp4( VirtualEventVideoEditSrvRequest( display_name=self._current_racer.racerAlias, racecar_color=self._current_racer.carConfig.carColor, ) ) # Update CameraManager by adding cameras into the current namespace. By doing so # a single follow car camera will follow the current active racecar. self._camera_manager.add( self._main_cameras[VIRTUAL_EVENT], self._current_car_model_state.model_name ) self._camera_manager.add(self._sub_camera, self._current_car_model_state.model_name) configure_environment_randomizer() # strip index for park position self._park_position_idx = get_racecar_idx(self._current_car_model_state.model_name) # set the park position in track and do evaluation # Before each evaluation episode (single lap for non-continuous race and complete race for # continuous race), a new copy of park_positions needs to be loaded into track_data because # a park position will be pop from park_positions when a racer car need to be parked. # unpause the physics in current world self._model_updater.unpause_physics() LOG.info("[virtual event manager] Unpaused physics in current world.") if ( self._prev_model_name is not None and self._prev_model_name != self._current_car_model_state.model_name ): # disable the links on the prev car # we are doing it here because we don't want the car to float around # after the link is disabled prev_car_model_state = ModelState() prev_car_model_state.model_name = self._prev_model_name LOG.info("[virtual event manager] Unpaused model for current car.") if self._is_continuous: self._track_data.park_positions = [self._park_positions[self._park_position_idx]] self._current_graph_manager.evaluate(EnvironmentSteps(1)) else: for _ in range(self._number_of_trials): self._track_data.park_positions = [self._park_positions[self._park_position_idx]] self._current_graph_manager.evaluate(EnvironmentSteps(1))
def __init__(self, racecar_name, racecars_info, race_type): """ This class is used for head to head racing where there are more than one agent Args: racecar_name (str): The agent name with 45degree camera view racecars_info (dict): All the agents information race_type (str): The type of race. This is used to know if its race type or evaluation """ self.racecar_name = racecar_name self.racecars_info = racecars_info racecar_index = get_racecar_idx(racecar_name) self.racecar_index = racecar_index if racecar_index else 0 self.race_type = race_type # Store the font which we will use to write the phase with self.amazon_ember_regular_20px = utils.get_font( 'AmazonEmber-Regular', 20) self.amazon_ember_regular_16px = utils.get_font( 'AmazonEmber-Regular', 16) self.amazon_ember_heavy_30px = utils.get_font('AmazonEmber-Heavy', 30) self.amazon_ember_light_18px = utils.get_font('AmazonEmber-Light', 18) self.amazon_ember_light_20px = utils.get_font('AmazonEmber-Light', 20) self.amazon_ember_light_italic_20px = utils.get_font( 'AmazonEmber-LightItalic', 20) self.is_racing = rospy.get_param("VIDEO_JOB_TYPE", "") == "RACING" self.is_league_leaderboard = rospy.get_param("LEADERBOARD_TYPE", "") == "LEAGUE" self.leaderboard_name = rospy.get_param("LEADERBOARD_NAME", "") self._total_laps = int(rospy.get_param("NUMBER_OF_TRIALS", 0)) # The track image as iconography self.track_icongraphy_img = utils.get_track_iconography_image() # Track image offset self.track_loc_offset = XYPixelLoc.TRACK_IMG_WITH_OFFSET_LOC.value if self.is_league_leaderboard \ else XYPixelLoc.TRACK_IMG_WITHOUT_OFFSET_LOC.value gradient_img_path = TrackAssetsIconographicPngs.HEAD_TO_HEAD_OVERLAY_PNG_LEAGUE_LEADERBOARD.value \ if self.is_league_leaderboard else TrackAssetsIconographicPngs.HEAD_TO_HEAD_OVERLAY_PNG.value self.gradient_img = self._plot_track_on_gradient(gradient_img_path) self.gradient_alpha_rgb_mul, self.one_minus_gradient_alpha = utils.get_gradient_values( self.gradient_img) # Top camera information top_camera_info = utils.get_top_camera_info() self.top_view_graphics = TopViewGraphics( top_camera_info.horizontal_fov, top_camera_info.padding_pct, top_camera_info.image_width, top_camera_info.image_height, racecars_info)
def __init__(self, racecar_name, racecar_info, race_type): """ Initializing the required data for the head to bot, time-trail. This is used for single agent Arguments: racecars_info (list): list of dict having information of the agent race_type (str): Since this class is reused for all the different race_type """ self.racecar_info = racecar_info self.race_type = race_type racecar_index = get_racecar_idx(racecar_name) self.racecar_index = racecar_index if racecar_index else 0 # Store the font which we will use to write the phase with self.amazon_ember_regular_20px = utils.get_font( 'AmazonEmber-Regular', 20) self.amazon_ember_regular_16px = utils.get_font( 'AmazonEmber-Regular', 16) self.amazon_ember_heavy_30px = utils.get_font('AmazonEmber-Heavy', 30) self.amazon_ember_light_18px = utils.get_font('AmazonEmber-Light', 18) self.amazon_ember_light_20px = utils.get_font('AmazonEmber-Light', 20) self.amazon_ember_light_italic_20px = utils.get_font( 'AmazonEmber-LightItalic', 20) self.is_racing = rospy.get_param("VIDEO_JOB_TYPE", "") == "RACING" self.is_league_leaderboard = rospy.get_param("LEADERBOARD_TYPE", "") == "LEAGUE" self.leaderboard_name = rospy.get_param("LEADERBOARD_NAME", "") self._total_laps = int(rospy.get_param("NUMBER_OF_TRIALS", 0)) # The track image as iconography self.track_icongraphy_img = utils.get_track_iconography_image() # Track image offset self.track_loc_offset = XYPixelLoc.TRACK_IMG_WITH_OFFSET_LOC.value if self.is_league_leaderboard \ else XYPixelLoc.TRACK_IMG_WITHOUT_OFFSET_LOC.value # Gradient overlay image gradient_img_path = TrackAssetsIconographicPngs.OBSTACLE_OVERLAY_PNG_LEAGUE_LEADERBOARD.value \ if self.is_league_leaderboard else TrackAssetsIconographicPngs.OBSTACLE_OVERLAY_PNG.value self.gradient_img = self._plot_track_on_gradient(gradient_img_path) self.gradient_alpha_rgb_mul, self.one_minus_gradient_alpha = utils.get_gradient_values( self.gradient_img) # Top camera information top_camera_info = utils.get_top_camera_info() self.top_view_graphics = TopViewGraphics( top_camera_info.horizontal_fov, top_camera_info.padding_pct, top_camera_info.image_width, top_camera_info.image_height, racecar_info)
def __init__(self, config_dict, run_phase_sink, metrics): '''config_dict (dict): containing all the keys in ConfigParams run_phase_sink (RunPhaseSubject): Sink to receive notification of a change in run phase metrics (EvalMetrics/TrainingMetrics): Training or evaluation metrics ''' # reset rules manager self._metrics = metrics self._is_continuous = config_dict[ const.ConfigParams.IS_CONTINUOUS.value] self._reset_rules_manager = construct_reset_rules_manager(config_dict) self._ctrl_status = dict() self._ctrl_status[ AgentCtrlStatus.AGENT_PHASE.value] = AgentPhase.RUN.value self._config_dict = config_dict self._done_condition = config_dict.get( const.ConfigParams.DONE_CONDITION.value, any) self._number_of_resets = config_dict[ const.ConfigParams.NUMBER_OF_RESETS.value] self._off_track_penalty = config_dict[ const.ConfigParams.OFF_TRACK_PENALTY.value] self._collision_penalty = config_dict[ const.ConfigParams.COLLISION_PENALTY.value] self._pause_duration = 0.0 self._reset_count = 0 self._curr_crashed_object_name = '' # simapp_version speed scale self._speed_scale_factor_ = get_speed_factor( config_dict[const.ConfigParams.VERSION.value]) # Store the name of the agent used to set agents position on the track self._agent_name_ = config_dict[const.ConfigParams.AGENT_NAME.value] # Set start lane. This only support for two agents H2H race self._agent_idx_ = get_racecar_idx(self._agent_name_) # Get track data self._track_data_ = TrackData.get_instance() if self._agent_idx_ is not None: self._start_lane_ = self._track_data_.inner_lane \ if self._agent_idx_ % 2 else self._track_data_.outer_lane else: self._start_lane_ = self._track_data_.center_line # Store the name of the links in the agent, this should be const self._agent_link_name_list_ = config_dict[ const.ConfigParams.LINK_NAME_LIST.value] # Store the reward function self._reward_ = config_dict[const.ConfigParams.REWARD.value] # Create publishers for controlling the car self._velocity_pub_dict_ = OrderedDict() self._steering_pub_dict_ = OrderedDict() for topic in config_dict[const.ConfigParams.VELOCITY_LIST.value]: self._velocity_pub_dict_[topic] = rospy.Publisher(topic, Float64, queue_size=1) for topic in config_dict[const.ConfigParams.STEERING_LIST.value]: self._steering_pub_dict_[topic] = rospy.Publisher(topic, Float64, queue_size=1) #Create default reward parameters self._reward_params_ = const.RewardParam.make_default_param() #Create the default metrics dictionary self._step_metrics_ = StepMetrics.make_default_metric() # Dictionary of bools indicating starting position behavior self._start_pos_behavior_ = \ {'change_start' : config_dict[const.ConfigParams.CHANGE_START.value], 'alternate_dir' : config_dict[const.ConfigParams.ALT_DIR.value]} # Dictionary to track the previous way points self._prev_waypoints_ = { 'prev_point': Point(0, 0), 'prev_point_2': Point(0, 0) } # Normalized distance of new start line from the original start line of the track. start_ndist = 0.0 # Normalized start position offset w.r.t to start_ndist, which is the start line of the track. start_pos_offset = config_dict.get( const.ConfigParams.START_POSITION.value, 0.0) self._start_line_ndist_offset = start_pos_offset / self._track_data_.get_track_length( ) # Dictionary containing some of the data for the agent # - During the reset call, every value except start_ndist will get wiped out by self._clear_data # (reset happens prior to every episodes begin) # - If self._start_line_ndist_offset is not 0 (usually some minus value), # then initial current_progress suppose to be non-zero (usually some minus value) as progress # suppose to be based on start_ndist. # - This will be correctly calculated by first call of utils.compute_current_prog function. # As prev_progress will be initially 0.0 and physical position is not at start_ndist, # utils.compute_current_prog will return negative progress if self._start_line_ndist_offset is negative value # (meaning behind start line) and will return positive progress if self._start_line_ndist_offset is # positive value (meaning ahead of start line). self._data_dict_ = { 'max_progress': 0.0, 'current_progress': 0.0, 'prev_progress': 0.0, 'steps': 0.0, 'start_ndist': start_ndist, 'prev_car_pose': 0.0 } #Load the action space self._action_space_, self._json_actions_ = \ load_action_space(config_dict[const.ConfigParams.ACTION_SPACE_PATH.value]) #! TODO evaluate if this is the best way to reset the car # Adding the reward data publisher self.reward_data_pub = RewardDataPublisher(self._agent_name_, self._json_actions_) # subscriber to time to update camera position self.camera_manager = CameraManager.get_instance() # True if the agent is in the training phase self._is_training_ = False # Register to the phase sink run_phase_sink.register(self) # Make sure velocity and angle are set to 0 send_action(self._velocity_pub_dict_, self._steering_pub_dict_, 0.0, 0.0) # start_dist should be hypothetical start line (start_ndist) plus # start position offset (start_line_ndist_offset). start_pose = self._start_lane_.interpolate_pose( (self._data_dict_['start_ndist'] + self._start_line_ndist_offset) * self._track_data_.get_track_length(), finite_difference=FiniteDifference.FORWARD_DIFFERENCE) self._track_data_.initialize_object(self._agent_name_, start_pose, \ ObstacleDimensions.BOT_CAR_DIMENSION) self.make_link_points = lambda link_state: Point( link_state.pose.position.x, link_state.pose.position.y) self.reference_frames = ['' for _ in self._agent_link_name_list_] self._pause_car_model_pose = None self._park_position = DEFAULT_PARK_POSITION AbstractTracker.__init__(self, TrackerPriority.HIGH)
def __init__(self, racecar_name, racecars_info, race_type): """ This class is used for head to head racing where there are more than one agent Args: racecar_name (str): The agent name with 45degree camera view racecars_info (dict): All the agents information race_type (str): The type of race. This is used to know if its race type or evaluation """ self.racecar_name = racecar_name self.racecars_info = racecars_info racecar_index = get_racecar_idx(racecar_name) self.racecar_index = racecar_index if racecar_index else 0 self.race_type = race_type # Store the font which we will use to write the phase with self.formula1_display_regular_12px = utils.get_font( 'Formula1-Display-Regular', 12) self.formula1_display_regular_14px = utils.get_font( 'Formula1-Display-Regular', 14) self.formula1_display_regular_16px = utils.get_font( 'Formula1-Display-Regular', 16) self.formula1_display_wide_12px = utils.get_font( 'Formula1-Display-Wide', 12) self.formula1_display_bold_16px = utils.get_font( 'Formula1-Display-Bold', 16) self.total_laps = int(rospy.get_param("NUMBER_OF_TRIALS", 0)) self.is_league_leaderboard = rospy.get_param("LEADERBOARD_TYPE", "") == "LEAGUE" self.leaderboard_name = rospy.get_param("LEADERBOARD_NAME", "") # The track image as iconography self.track_icongraphy_img = utils.get_track_iconography_image() # Track image offset self.track_loc_offset = XYPixelLoc.TRACK_IMG_WITHOUT_OFFSET_LOC.value # Default image of top view gradient_default_img_path = TrackAssetsIconographicPngs.F1_OVERLAY_DEFAULT_PNG.value self.gradient_default_img = self._plot_track_on_gradient( gradient_default_img_path) self.gradient_default_alpha_rgb_mul, self.one_minus_gradient_default_alpha = utils.get_gradient_values( self.gradient_default_img) # Midway track gradient gradient_midway_img_path = TrackAssetsIconographicPngs.F1_OVERLAY_MIDWAY_PNG.value self.gradient_midway_img = self._plot_track_on_gradient( gradient_midway_img_path) self.gradient_midway_alpha_rgb_mul, self.one_minus_gradient_midway_alpha = utils.get_gradient_values( self.gradient_midway_img) # Finisher track gradient gradient_finisher_img_path = TrackAssetsIconographicPngs.F1_OVERLAY_FINISHERS_PNG.value self.gradient_finisher_img = self._plot_track_on_gradient( gradient_finisher_img_path) self.gradient_finisher_alpha_rgb_mul, self.one_minus_gradient_finisher_alpha = utils.get_gradient_values( self.gradient_finisher_img) # Top camera gradient num_racers = len(self.racecars_info) if num_racers <= 8: # TODO: Add one box image and use 1 box image if number of racers are <= 4. gradient_top_camera_img_path = TrackAssetsIconographicPngs.F1_OVERLAY_TOPVIEW_2BOX_PNG.value elif num_racers <= 12: gradient_top_camera_img_path = TrackAssetsIconographicPngs.F1_OVERLAY_TOPVIEW_3BOX_PNG.value else: raise Exception( "More than 12 racers are not supported for Grand Prix") gradient_top_camera_img = utils.get_image( gradient_top_camera_img_path, IconographicImageSize.FULL_IMAGE_SIZE.value) gradient_top_camera_img = cv2.cvtColor(gradient_top_camera_img, cv2.COLOR_RGBA2BGRA) self.gradient_top_camera_alpha_rgb_mul, self.one_minus_gradient_top_camera_alpha = utils.get_gradient_values( gradient_top_camera_img) # Top camera information top_camera_info = utils.get_top_camera_info() self.edited_topview_pub = rospy.Publisher('/deepracer/topview_stream', ROSImg, queue_size=1) self.top_view_graphics = TopViewGraphics( top_camera_info.horizontal_fov, top_camera_info.padding_pct, top_camera_info.image_width, top_camera_info.image_height, racecars_info, race_type) self.hex_car_colors = [ val['racecar_color'].split('_')[-1] for val in racecars_info ] self._racer_color_code_rect_img = list() self._racer_color_code_slash_img = list() for car_color in self.hex_car_colors: # Rectangular png of racers racer_color_code_rect = "{}_{}".format( TrackAssetsIconographicPngs.F1_AGENTS_RECT_DISPLAY_ICON_PNG. value, car_color) self._racer_color_code_rect_img.append( utils.get_image( racer_color_code_rect, IconographicImageSize. F1_RACER_RECT_DISPLAY_ICON_SIZE.value)) # Slash png of racers racer_color_code_slash = "{}_{}".format( TrackAssetsIconographicPngs.F1_AGENTS_SLASH_DISPLAY_ICON_PNG. value, car_color) racer_color_code_slash_img = utils.get_image( racer_color_code_slash, IconographicImageSize.F1_RACER_SLASH_DISPLAY_ICON_SIZE.value) self._racer_color_code_slash_img.append( cv2.cvtColor(racer_color_code_slash_img, cv2.COLOR_RGBA2BGRA))
def __init__(self, config_dict, run_phase_sink, metrics): '''agent_name - String containing the name of the agent config_dict - Dictionary containing all the keys in ConfigParams run_phase_sink - Sink to recieve notification of a change in run phase ''' # reset rules manager self._metrics = metrics self._is_continuous = config_dict[ const.ConfigParams.IS_CONTINUOUS.value] self._is_reset = False self._reset_rules_manager = construct_reset_rules_manager(config_dict) self._ctrl_status = dict() self._ctrl_status[ AgentCtrlStatus.AGENT_PHASE.value] = AgentPhase.RUN.value self._config_dict = config_dict self._done_condition = config_dict.get( const.ConfigParams.DONE_CONDITION.value, any) self._number_of_resets = config_dict[ const.ConfigParams.NUMBER_OF_RESETS.value] self._off_track_penalty = config_dict[ const.ConfigParams.OFF_TRACK_PENALTY.value] self._collision_penalty = config_dict[ const.ConfigParams.COLLISION_PENALTY.value] self._pause_duration = 0.0 self._reset_count = 0 self._curr_crashed_object_name = None self._last_crashed_object_name = None # simapp_version speed scale self._speed_scale_factor_ = get_speed_factor( config_dict[const.ConfigParams.VERSION.value]) # Store the name of the agent used to set agents position on the track self._agent_name_ = config_dict[const.ConfigParams.AGENT_NAME.value] # Set start lane. This only support for two agents H2H race self._agent_idx_ = get_racecar_idx(self._agent_name_) # Get track data self._track_data_ = TrackData.get_instance() if self._agent_idx_ is not None: self._start_lane_ = self._track_data_.inner_lane \ if self._agent_idx_ % 2 else self._track_data_.outer_lane else: self._start_lane_ = self._track_data_.center_line # Store the name of the links in the agent, this should be const self._agent_link_name_list_ = config_dict[ const.ConfigParams.LINK_NAME_LIST.value] # Store the reward function self._reward_ = config_dict[const.ConfigParams.REWARD.value] # Create publishers for controlling the car self._velocity_pub_dict_ = OrderedDict() self._steering_pub_dict_ = OrderedDict() for topic in config_dict[const.ConfigParams.VELOCITY_LIST.value]: self._velocity_pub_dict_[topic] = rospy.Publisher(topic, Float64, queue_size=1) for topic in config_dict[const.ConfigParams.STEERING_LIST.value]: self._steering_pub_dict_[topic] = rospy.Publisher(topic, Float64, queue_size=1) #Create default reward parameters self._reward_params_ = const.RewardParam.make_default_param() #Creat the default metrics dictionary self._step_metrics_ = StepMetrics.make_default_metric() # Dictionary of bools indicating starting position behavior self._start_pos_behavior_ = \ {'change_start' : config_dict[const.ConfigParams.CHANGE_START.value], 'alternate_dir' : config_dict[const.ConfigParams.ALT_DIR.value]} # Dictionary to track the previous way points self._prev_waypoints_ = { 'prev_point': Point(0, 0), 'prev_point_2': Point(0, 0) } # Normalize start position in meter to normalized start_ndist in percentage start_ndist = config_dict.get(const.ConfigParams.START_POSITION.value, 0.0) / \ self._track_data_.get_track_length() # Dictionary containing some of the data for the agent self._data_dict_ = { 'max_progress': 0.0, 'current_progress': 0.0, 'prev_progress': 0.0, 'steps': 0.0, 'start_ndist': start_ndist } #Load the action space self._action_space_, self._json_actions_ = \ load_action_space(config_dict[const.ConfigParams.ACTION_SPACE_PATH.value]) #! TODO evaluate if this is the best way to reset the car # Adding the reward data publisher self.reward_data_pub = RewardDataPublisher(self._agent_name_, self._json_actions_) # subscriber to time to update camera position self.camera_manager = CameraManager.get_instance() # True if the agent is in the training phase self._is_training_ = False # Register to the phase sink run_phase_sink.register(self) # Make sure velicty and angle are set to 0 send_action(self._velocity_pub_dict_, self._steering_pub_dict_, 0.0, 0.0) start_pose = self._track_data_.center_line.interpolate_pose( self._data_dict_['start_ndist'] * self._track_data_.get_track_length(), finite_difference=FiniteDifference.FORWARD_DIFFERENCE) self._track_data_.initialize_object(self._agent_name_, start_pose, \ ObstacleDimensions.BOT_CAR_DIMENSION) self.make_link_points = lambda link_state: Point( link_state.pose.position.x, link_state.pose.position.y) self.reference_frames = ['' for _ in self._agent_link_name_list_] self._pause_car_model_pose = None self._park_position = DEFAULT_PARK_POSITION AbstractTracker.__init__(self, TrackerPriority.HIGH)
def __init__(self, racecar_name, racecars_info): # # We have no guarantees as to when gazebo will load the model, therefore we need # to wait until the model is loaded and markov packages has spawned all the models # rospy.wait_for_service('/robomaker_markov_package_ready') self._agents_metrics.append(DoubleBuffer(clear_data_on_get=False)) self.racecar_name = racecar_name self.racecars_info = racecars_info racecar_index = get_racecar_idx(racecar_name) self.racecar_index = racecar_index if racecar_index else 0 self.agent_name = utils.racecar_name_to_agent_name(racecars_info, racecar_name) # init cv bridge self.bridge = CvBridge() # This determines what kind of image editing should be done based on the race type self.is_training = rospy.get_param("JOB_TYPE") == 'TRAINING' self.job_type_image_edit = self._get_image_editing_job_type() if self.is_training: # String indicating the current phase self._current_training_phase = DoubleBuffer(clear_data_on_get=False) self._current_training_phase.put('Initializing') # Subscriber to get the phase of the training (Ideal, training, evaluation) rospy.Subscriber('/agent/training_phase', String, self._training_phase_cb) # Fetching main camera frames, start consumer thread and producer thread for main camera frame main_camera_topic = "/{}/{}/zed/rgb/image_rect_color".format(self.racecar_name, "main_camera") # All KVS related initialization self._kvs_frame_buffer = DoubleBuffer(clear_data_on_get=False) # Publish to KVS stream topic self.kvs_pub = rospy.Publisher('/{}/deepracer/kvs_stream'.format(self.racecar_name), ROSImg, queue_size=1) # All Mp4 related initialization self._mp4_queue.append(Queue()) self._mp4_edited_frame_queue.append(Queue(MAX_FRAMES_IN_QUEUE)) self._mp4_condition_lock.append(Condition()) # Initialize save mp4 ROS service for the markov package to signal when to # start and stop collecting video frames camera_info = utils.get_cameratype_params(self.racecar_name, self.agent_name) self.save_to_mp4_obj = SaveToMp4(camera_infos=[camera_info[CameraTypeParams.CAMERA_PIP_PARAMS], camera_info[CameraTypeParams.CAMERA_45DEGREE_PARAMS], camera_info[CameraTypeParams.CAMERA_TOPVIEW_PARAMS]], fourcc=Mp4Parameter.FOURCC.value, fps=Mp4Parameter.FPS.value, frame_size=Mp4Parameter.FRAME_SIZE.value) rospy.Service('/{}/save_mp4/subscribe_to_save_mp4'.format(self.racecar_name), Empty, self.subscribe_to_save_mp4) rospy.Service('/{}/save_mp4/unsubscribe_from_save_mp4'.format(self.racecar_name), Empty, self.unsubscribe_to_save_mp4) # Publish to save mp4 topic self.mp4_main_camera_pub = rospy.Publisher('/{}/deepracer/main_camera_stream'.format(self.racecar_name), ROSImg, queue_size=1) # ROS service to get video metrics rospy.wait_for_service("/{}/{}".format(self.agent_name, "mp4_video_metrics")) self.mp4_video_metrics_srv = ServiceProxyWrapper("/{}/{}".format(self.agent_name, "mp4_video_metrics"), VideoMetricsSrv) self.is_save_mp4_enabled = False rospy.Subscriber(main_camera_topic, ROSImg, self._producer_frame_thread) Thread(target=self._consumer_mp4_frame_thread).start() Thread(target=self._kvs_publisher).start() Thread(target=self._mp4_publisher).start()
def __init__(self, racecar_name, racecar_info, race_type): """ Initializing the required data for the head to bot, time-trail. This is used for single agent Arguments: racecar_name (str): racecar name in string racecars_info (list): list of dict having information of the agent race_type (str): Since this class is reused for all the different race_type """ # race duration in milliseconds self._world_name = rospy.get_param("WORLD_NAME") self.num_sectors = int(rospy.get_param("NUM_SECTORS", "3")) self.race_duration = int( rospy.get_param("RACE_DURATION", DEFAULT_RACE_DURATION)) * 1000 self.racecar_info = racecar_info self.race_type = race_type racecar_index = get_racecar_idx(racecar_name) self.racecar_index = racecar_index if racecar_index else 0 # Store the font which we will use to write the phase with self.amazon_ember_regular_28px = utils.get_font( 'AmazonEmber-Regular', 28) self.amazon_ember_regular_14px = utils.get_font( 'AmazonEmber-Regular', 14) # The track image as iconography self.track_icongraphy_img = utils.get_track_iconography_image() # Track image offset self.track_loc_offset = VirtualEventXYPixelLoc.TRACK_IMG_VIRTUAL_EVENT_LOC.value self._track_x_min = None self._track_x_max = None self._track_y_min = None self._track_y_max = None # Gradient overlay image with track and virtual event mock gradient_img_path = VirtualEventIconographicPngs.OVERLAY_PNG.value self.gradient_img = self._plot_track_on_gradient(gradient_img_path) # Time remaining text loc_x, loc_y = VirtualEventXYPixelLoc.TIME_REMAINING_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="TIME REMAINING", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Speed text loc_x, loc_y = VirtualEventXYPixelLoc.SPEED_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="m/s", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # Reset text loc_x, loc_y = VirtualEventXYPixelLoc.RESET_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="RESET", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # current lap time text loc_x, loc_y = VirtualEventXYPixelLoc.CURRENT_LAP_TIME_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="CURRENT LAP TIME", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # best lap time text loc_x, loc_y = VirtualEventXYPixelLoc.BEST_LAP_TIME_TEXT.value self.gradient_img = utils.write_text_on_image( image=self.gradient_img, text="BEST LAP TIME", loc=(loc_x, loc_y), font=self.amazon_ember_regular_14px, font_color=RaceCarColorToRGB.White.value, font_shadow_color=RaceCarColorToRGB.Black.value) # apply graident self.gradient_alpha_rgb_mul, self.one_minus_gradient_alpha = utils.get_gradient_values( self.gradient_img) # Top camera information top_camera_info = utils.get_top_camera_info() self.top_view_graphics = TopViewGraphics( top_camera_info.horizontal_fov, top_camera_info.padding_pct, top_camera_info.image_width, top_camera_info.image_height, racecar_info, is_virtual_event=True) # virtual event image editting state machine self._image_edit_fsm = FSM(initial_state=VirtualEventWaitState()) # if best sector time download from s3 failed. Then, initialize best sector time as None # and not display sector color self._sector_times = {} # declare sector images self._sectors_img_dict = {} for idx in range(self.num_sectors): sector = SECTOR_X_FORMAT.format(idx + 1) sector_color_img_dict = utils.init_sector_img_dict( world_name=self._world_name, sector=sector) self._sectors_img_dict[sector] = sector_color_img_dict # use the s3 bucket and prefix for yaml file stored as environment variable because # here is SimApp use only. For virtual event there is no s3 bucket and prefix past # through yaml file. All are past through sqs. For simplicity, reuse the yaml s3 bucket # and prefix environment variable. self._virtual_event_best_sector_time = VirtualEventBestSectorTime( bucket=os.environ.get("YAML_S3_BUCKET", ''), s3_key=get_s3_key(os.environ.get("YAML_S3_PREFIX", ''), SECTOR_TIME_S3_POSTFIX), region_name=os.environ.get("APP_REGION", "us-east-1"), local_path=SECTOR_TIME_LOCAL_PATH) self._sector_times.update( self._virtual_event_best_sector_time.get_sector_time( num_sectors=self.num_sectors)) # declare default best personal and current persoanl time to inf for idx in range(self.num_sectors): sector = SECTOR_X_FORMAT.format(idx + 1) self._sector_times[SECTOR_TIME_FORMAT_DICT[ TrackSectorTime.BEST_PERSONAL].format(sector)] = float("inf") self._sector_times[SECTOR_TIME_FORMAT_DICT[ TrackSectorTime.CURRENT_PERSONAL].format(sector)] = float( "inf") self._curr_lap_time = 0 self._last_eval_time = 0 self._curr_progress = 0 self._last_progress = 0 self._current_lap = 1 # Initializing the fader behaviour to pre-compute the gradient values final_fading_image = utils.get_image( VirtualEventIconographicPngs.FINAL_FADING_IMAGE_50ALPHA.value, IconographicImageSize.FULL_IMAGE_SIZE.value) final_fading_image = cv2.cvtColor(final_fading_image, cv2.COLOR_RGBA2BGRA) self._fader_obj = Fader( final_fading_image, fading_min_percent=VirtualEventFader.FADING_MIN_PERCENT.value, fading_max_percent=VirtualEventFader.FADING_MAX_PERCENT.value, num_frames=VirtualEventFader.NUM_FRAMES.value)
def __init__(self, racecar_name, racecars_info, is_publish_to_kvs_stream): # # We have no guarantees as to when gazebo will load the model, therefore we need # to wait until the model is loaded and markov packages has spawned all the models # rospy.wait_for_service('/robomaker_markov_package_ready') self._agents_metrics.append(DoubleBuffer(clear_data_on_get=False)) self.racecar_name = racecar_name self.racecars_info = racecars_info racecar_index = get_racecar_idx(racecar_name) self.racecar_index = racecar_index if racecar_index else 0 self.agent_name = utils.racecar_name_to_agent_name( racecars_info, racecar_name) self._is_publish_to_kvs_stream = is_publish_to_kvs_stream # init cv bridge self.bridge = CvBridge() # This determines what kind of image editing should be done based on the race type self.is_training = rospy.get_param("JOB_TYPE") == 'TRAINING' self.race_type = rospy.get_param("RACE_TYPE", RaceType.TIME_TRIAL.value) self.is_f1_race_type = self.race_type == RaceType.F1.value # # Two job types are required because in the F1 editing we have static variables # to compute the gap and ranking. With Mp4 stacking frames, these values would be already updated by KVS. # If same class is used then during the finish phase you see all the racers information at once # and not updated real time when racers finish the lap. # %TODO seperate out the kvs and Mp4 functionality # self.job_type_image_edit_mp4 = self._get_image_editing_job_type() if self.is_training: # String indicating the current phase self._current_training_phase = DoubleBuffer( clear_data_on_get=False) self._current_training_phase.put('Initializing') # Subscriber to get the phase of the training (Ideal, training, evaluation) rospy.Subscriber('/agent/training_phase', String, self._training_phase_cb) # Fetching main camera frames, start consumer thread and producer thread for main camera frame main_camera_topic = "/{}/{}/zed/rgb/image_rect_color".format( self.racecar_name, "main_camera") # All Mp4 related initialization self._mp4_queue.append(Queue.Queue()) # Initialize save mp4 ROS service for the markov package to signal when to # start and stop collecting video frames camera_info = utils.get_cameratype_params(self.racecar_name, self.agent_name, self.is_f1_race_type) self.save_to_mp4_obj = SaveToMp4( camera_infos=[ camera_info[CameraTypeParams.CAMERA_PIP_PARAMS], camera_info[CameraTypeParams.CAMERA_45DEGREE_PARAMS], camera_info[CameraTypeParams.CAMERA_TOPVIEW_PARAMS] ], fourcc=Mp4Parameter.FOURCC.value, fps=Mp4Parameter.FPS.value, frame_size=Mp4Parameter.FRAME_SIZE.value) rospy.Service( '/{}/save_mp4/subscribe_to_save_mp4'.format(self.racecar_name), Empty, self.subscribe_to_save_mp4) rospy.Service( '/{}/save_mp4/unsubscribe_from_save_mp4'.format(self.racecar_name), Empty, self.unsubscribe_to_save_mp4) # Publish to save mp4 topic self.mp4_main_camera_pub = rospy.Publisher( '/{}/deepracer/main_camera_stream'.format(self.racecar_name), ROSImg, queue_size=1) # ROS service to get video metrics rospy.wait_for_service("/{}/{}".format(self.agent_name, "mp4_video_metrics")) self.mp4_video_metrics_srv = ServiceProxyWrapper( "/{}/{}".format(self.agent_name, "mp4_video_metrics"), VideoMetricsSrv) self.is_save_mp4_enabled = False # Only F1 race requires top camera frames edited self.top_camera_mp4_pub = None if self.is_f1_race_type and self.racecar_index == 0: self._top_camera_frame_buffer = DoubleBuffer( clear_data_on_get=False) top_camera_topic = "/sub_camera/zed/rgb/image_rect_color" rospy.Subscriber(top_camera_topic, ROSImg, self._top_camera_cb) self.top_camera_mp4_pub = rospy.Publisher( '/{}/topcamera/deepracer/mp4_stream'.format(racecar_name), ROSImg, queue_size=1) self._main_camera_frame_buffer = DoubleBuffer(clear_data_on_get=False) rospy.Subscriber(main_camera_topic, ROSImg, self._producer_frame_thread) Thread(target=self._consumer_mp4_frame_thread).start() # Leaderboard jobs do not require KVS streams if self._is_publish_to_kvs_stream: self.job_type_image_edit_kvs = self._get_image_editing_job_type() # Publish to KVS stream topic self.kvs_pub = rospy.Publisher('/{}/deepracer/kvs_stream'.format( self.racecar_name), ROSImg, queue_size=1) Thread(target=self._kvs_publisher).start()