Pause at waypoint until audio complete

Hi all! I’m working on setting up our Stretch RE1 as a tour guide of a newly renovated lab space at RPI. I’m having a bit of trouble getting the stretch to stop at each way point until the audio finishes playing, and then move on. I have something working, but it’s a bit of a dirty solution, so I was hoping someone could give a bit of advice on how to better accomplish this. For context, here is how I am currently doing it:

def audio_response_callback(self, future):
        goal_handle = future.result()
        if not goal_handle.accepted:
            self.get_logger().info('Audio Msg Declined')
            return

        self.get_logger().info('Audio Msg Accepted')
        self.ready_to_move = False
        self._get_result_future = goal_handle.get_result_async()
        self._get_result_future.add_done_callback(self.get_result_callback)

    def get_result_callback(self, future):
        self.audio_result = future.result().result
        self.ready_to_move = True
        if self.audio_result.finished == MercerAudio.Result.SUCCESS:
            self.get_logger().info("Audio played successfully")
        else:
            self.get_logger().info("Audio failed to play")

    def main(self):
        self.parse_pose_dict_to_poses()

        self.audio_result = None
        self.audio_msg = MercerAudio.Goal()
        self.audio_msg.file_path = self.audio_file_path + 'origin.wav'
        self.audio_future = self.audio_cue_client.send_goal_async(self.audio_msg)
        self.audio_future.add_done_callback(self.audio_response_callback)
        while self.audio_result is None:
            rclpy.spin_once(self, timeout_sec=1.0)
        self.get_logger().info("Audio finished playing!")

        for pose in self.route_poses:
            self.get_logger().info("Pose: {0}".format(pose['id']))
            self.audio_result = None
            self.result = TaskResult.UNKNOWN


            self.go_to_waypoint(pose['pose'])

            i = 0
            while not self.navigator.isTaskComplete():
                i += 1
                feedback = self.navigator.getFeedback()
                if feedback and i % 5 == 0:
                    self.get_logger().info('Executing current waypoint')
            
            self.get_logger().info("Result: {0}".format(self.result))
            if self.result == TaskResult.SUCCEEDED:
                self.get_logger().info("Navigation to waypoint successful!")
            else:
                if self.result == TaskResult.UNKNOWN:
                    while not self.navigator.isTaskComplete():
                        rclpy.spin_once(self, timeout_sec=1.0)
                        self.get_logger().info("Still spinning {0}".format(pose['id']))

            self.audio_msg = MercerAudio.Goal()
            self.audio_msg.file_path = self.audio_file_path + pose['id'] + '.wav'
            self.audio_future = self.audio_cue_client.send_goal_async(self.audio_msg)
            self.audio_future.add_done_callback(self.audio_response_callback)
            while self.audio_result is None:
                # self.get_logger().info("Waiting for audio to finish playing...")
                rclpy.spin_once(self, timeout_sec=0.2)

            server_reached = self.audio_cue_client.wait_for_server(timeout_sec=60.0)
            if not server_reached:
                self.get_logger().error('Unable to connect to audio action server. Timeout exceeded.')
                sys.exit()

            self.get_logger().info("Audio finished playing!")


        self.audio_msg = MercerAudio.Goal()
        self.audio_msg.file_path = self.audio_file_path + 'end.wav'
        self.audio_future = self.audio_cue_client.send_goal_async(self.audio_msg)
        self.audio_future.add_done_callback(self.audio_response_callback)
        self.get_logger().info("Navigation complete!")

It works, but only just. I’m reading in waypoints from a JSON file, and then based on the name of the waypoint, playing audio. Let me know what you guys think! Thanks!

Hey @byrnete, I’m not familiar with Mercer Audio, but a quick idea that might work is adding ~5 seconds of white noise at the end of each audio clip so the audio finishes playing completely.

Getting the robot to be a tour guide around your lab space is pretty cool. I hope you’ll post your war stories about getting it working.

Whoops! Forgot to describe the Mercer Audio node. This project is part of the Mercer XLab at RPI, hence the name of the node. It’s just an ActionServer I set up to play audio files. I’ll try that out next I work on it.
Sorry for the sporadic replies, the project is on hold for the time, so this is just in my downtime now.

I’ll definetely post about it! It ended up working fairly well for our first iteration. Next steps will likely be adding a web interface so anyone can run the Tour Demo, so I don’t need to be there every time. I’ll make a Share post soon!

1 Like