From 44c8681e123b44a888d83573aa2713614abad7ed Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Wed, 24 Jul 2024 21:49:24 +0100 Subject: [PATCH 1/9] Delete local_speech_recovery --- .../states/local_speech_recognition.py | 216 ------------------ 1 file changed, 216 deletions(-) delete mode 100644 tasks/receptionist/src/receptionist/states/local_speech_recognition.py diff --git a/tasks/receptionist/src/receptionist/states/local_speech_recognition.py b/tasks/receptionist/src/receptionist/states/local_speech_recognition.py deleted file mode 100644 index 5f79f4d83..000000000 --- a/tasks/receptionist/src/receptionist/states/local_speech_recognition.py +++ /dev/null @@ -1,216 +0,0 @@ -import jellyfish as jf - - -available_names = [ - "adel", - "angel", - "axel", - "charlie", - "jane", - "jules", - "morgan", - "paris", - "robin", - "simone", -] -available_single_drinks = [ - "cola", - "milk", -] -available_double_drinks = [ - "iced", - "tea", - "pack", - "juice", - "orange", - "red", - "wine", - "tropical", -] -double_drinks_dict = { - "iced": "iced tea", - "tea": "iced tea", - "pack": "juice pack", - "orange": "orange juice", - "red": "red wine", - "wine": "red wine", - "tropical": "tropical juice", - # "juice": ["orange juice", "tropical juice", "juice pack"], -} -available_drinks = list( - set(available_single_drinks).union(set(available_double_drinks)) -) -excluded_words = [ - "my", - "name", - "is", - "and", - "favourite", - "drink", - "you", - "can", - "call", - "me", -] - - -def speech_recovery(sentence): - sentence_split = sentence.split() - sentence_list = list(set(sentence_split) - set(excluded_words)) - print(f"final name: {handle_name(sentence_list, True)}") - print(f"final drink: {handle_drink(sentence_list, True)}") - - -def handle_name(sentence_list, last_resort): - result = handle_similar_spelt(sentence_list, available_names, 1) - if result != "unknown": - print(f"name (spelt): {result}") - return result - else: - result = handle_similar_sound(sentence_list, available_names, 0) - print(f"name (sound): {result}") - if not last_resort or result != "unknown": - return result - else: - print("Last resort name") - return handle_closest_spelt(sentence_list, available_names) - - -def handle_drink(sentence_list, last_resort): - result = infer_second_drink(sentence_list) - if result != "unknown": - return result - result = handle_similar_spelt(sentence_list, available_drinks, 1) - if result != "unknown": - print(f"drink (spelt): {result}") - else: - result = handle_similar_sound(sentence_list, available_drinks, 0) - print(f"drink (sound): {result}") - if result != "unknown": - if result in available_single_drinks: - print(f"final attempt drink: {result}") - return result - else: - sentence_list.append(result) - return infer_second_drink(sentence_list) - else: - if not last_resort: - return "unknown" - else: - print("Last resort drink") - closest_spelt = handle_closest_spelt(sentence_list, available_drinks) - if closest_spelt in available_single_drinks: - print(f"final attempt during last resort drink: {closest_spelt}") - return closest_spelt - else: - sentence_list.append(closest_spelt) - return infer_second_drink(closest_spelt) - - -def handle_similar_spelt(sentence_list, available_words, distance_threshold): - for input_word in sentence_list: - for available_word in available_words: - distance = get_damerau_levenshtein_distance(input_word, available_word) - if distance <= distance_threshold: - return available_word - return "unknown" - - -def handle_similar_sound(sentence_list, available_words, distance_threshold): - for input_word in sentence_list: - for available_word in available_words: - distance = get_levenshtein_soundex_distance(input_word, available_word) - if distance <= distance_threshold: - print(input_word, available_word) - return available_word - return "unknown" - - -def infer_second_drink(sentence_list): - for input_word in sentence_list: - if input_word == "juice": - choices = ["pack", "orange", "tropical"] - closest_word = handle_closest_spelt(sentence_list, choices) - if closest_word == "pack": - return "juice pack" - elif closest_word == "orange": - return "orange juice" - else: - return "tropical juice" - for available_word in available_double_drinks: - if input_word == available_word: - return double_drinks_dict[input_word] - return "unknown" - - -def handle_closest_spelt(sentence_list, choices): - closest_distance = float("inf") - closest_word = None - for input_word in sentence_list: - for available_word in choices: - distance = get_damerau_levenshtein_distance(input_word, available_word) - if distance < closest_distance: - closest_distance = distance - closest_word = available_word - return closest_word - - -def get_damerau_levenshtein_distance(word_1, word_2): - return jf.damerau_levenshtein_distance(word_1, word_2) - - -def get_levenshtein_soundex_distance(word_1, word_2): - soundex_word_1 = jf.soundex(word_1) - soundex_word_2 = jf.soundex(word_2) - return jf.levenshtein_distance(soundex_word_1, soundex_word_2) - - -# print(get_damerau_levenshtein_distance("juice", "shoes")) -# print(get_levenshtein_soundex_distance("juice", "shoes")) - - -# print(jf.levenshtein_distance(jf.metaphone("my"), jf.metaphone("tea"))) - -# print(jf.soundex("juice"), jf.soundex("shoes")) - -# print(jf.levenshtein_distance(jf.soundex("jane"), jf.soundex("axasel"))) - -# available_names = ["adel", "angel", "axel", "charlie", "jane", "jules", "morgan", "paris", "robin", "simone"] -# available_single_drinks = ["cola", "milk",] -# available_double_drinks = ["iced", "tea", "juice", "pack", "orange", "red", "wine", "tropical"] -# double_drinks_dict = {"iced" : "iced tea", -# "tea": "iced tea", -# "pack" : "juice pack", -# "orange" : "orange juice", -# "red" : "red wine", -# "wine" : "red wine", -# "tropical" : "tropical juice", -# "juice": ["orange juice", "tropical juice", "juice pack"], -# } - -# available_names_and_drinks = list(set(available_names).union(set(available_single_drinks)).union(set(available_double_drinks))) - -# sentence = "my name is axl and my favourite drink is orange shoes" - -# dataList = set(sentence.split()).union(set(available_names_and_drinks)) - - -if __name__ == "__main__": - sentence = "my name is jay and my favourite drink is mill" - speech_recovery(sentence) - print("======") - sentence = "my name is jayne and my favourite drink is oras juice" - speech_recovery(sentence) - print("======") - sentence = "my name is axl and my favourite drink is tropical ef" - speech_recovery(sentence) - print("======") - sentence = "my name is axl and my favourite drink is p jews" - speech_recovery(sentence) - print("======") - sentence = "my name is axasel and my favourite drink is orange juice juice" - speech_recovery(sentence) - print("======") - sentence = "my name is morgen and my favourite drink is mll" - speech_recovery(sentence) - print("======") From b0d087b4f2239a922c951109639f4b1a43645ff7 Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Thu, 25 Jul 2024 00:14:22 +0100 Subject: [PATCH 2/9] Comment speech_recovery --- .../receptionist/states/speech_recovery.py | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/tasks/receptionist/src/receptionist/states/speech_recovery.py b/tasks/receptionist/src/receptionist/states/speech_recovery.py index 42748dcc5..1c6c24cb5 100644 --- a/tasks/receptionist/src/receptionist/states/speech_recovery.py +++ b/tasks/receptionist/src/receptionist/states/speech_recovery.py @@ -1,3 +1,8 @@ +""" +State for recovering the speech transcribed via whisper (name and drink) by using +the spelling and pronounciation of a word. +""" + import rospy import smach import string @@ -13,6 +18,15 @@ def __init__( last_resort: bool, input_type: str = "", ): + """Recover the correct name and / or drink by parsing the transcription. + + Args: + guest_id (str): ID of the guest (identifying the guest) + last_resort (bool): Whether the program must recover a name or drink + input_type (str, optional): The type of information to try and extract useful information + (drink or name) + """ + smach.State.__init__( self, outcomes=["succeeded", "failed"], @@ -95,6 +109,17 @@ def __init__( ] def execute(self, userdata: UserData) -> str: + """Optimise the transcription, then attempt to recover the drink or / and name. + + Args: + userdata (UserData): State machine userdata assumed to contain a key + called "guest transcription" with the transcription of the guest's name or + favourite drink or both. + + Returns: + str: state outcome. Updates the userdata with the parsed information (drink or name), under + the parameter "guest data". + """ filtered_sentence = userdata.guest_transcription.lower().translate( str.maketrans("", "", string.punctuation) ) @@ -137,6 +162,16 @@ def execute(self, userdata: UserData) -> str: return "succeeded" def _handle_name(self, sentence_list, last_resort): + """Attempt to recover the name in the transcription. First recover via spelling, then pronounciation. + Enter last resort if necessary and recover the closest spelt name. + + Args: + sentence_list (List[str]): Transcription split up as a list of strings. + last_resort (bool): Whether the program must recover a name + + Returns: + str: Recovered name. 'unknown' is returned if no name is recovered. + """ result = self._handle_similar_spelt(sentence_list, self._available_names, 1) if result != "unknown": print(f"name (spelt): {result}") @@ -151,6 +186,17 @@ def _handle_name(self, sentence_list, last_resort): return self._handle_closest_spelt(sentence_list, self._available_names) def _handle_drink(self, sentence_list, last_resort): + """Attempt to recover the drink in the transcription. For phrases containing two words, try to infer the + second word in the phrase. If this fails, attempt to recover the drink via spelling, then pronounciation. + Enter last resort if necessary and recover the closest spelt drink. + + Args: + sentence_list (List[str]): Transcription split up as a list of strings. + last_resort (bool): Whether the program must recover a drink + + Returns: + str: Recovered drink. 'unknown' is returned if no drink is recovered. + """ result = self._infer_second_drink(sentence_list) if result != "unknown": return result @@ -188,6 +234,17 @@ def _handle_drink(self, sentence_list, last_resort): return self._infer_second_drink(sentence_list) def _handle_similar_spelt(self, sentence_list, available_words, distance_threshold): + """Recover any word by spelling that has a similarity lower than the specified threshold + when comparing each word in the sentence list to the list of available words. + + Args: + sentence_list (List[str]): Transcription split up as a list of strings. + available_words (List[str]): List of available words to compare to (drinks or names) + distance_threshold (int): Similarity in terms of spelling distance required for a word to be recovered + + Returns: + str: Recovered word. 'unknown' is returned if no word is recovered. + """ for input_word in sentence_list: for available_word in available_words: distance = self._get_damerau_levenshtein_distance( @@ -198,6 +255,17 @@ def _handle_similar_spelt(self, sentence_list, available_words, distance_thresho return "unknown" def _handle_similar_sound(self, sentence_list, available_words, distance_threshold): + """Recover any word by pronounciation that has a similarity lower than the specified threshold + when comparing each word in the sentence list to the list of available words. + + Args: + sentence_list (List[str]): Transcription split up as a list of strings. + available_words (List[str]): List of available words to compare to (drinks or names) + distance_threshold (int): Similarity in terms of pronounciation distance required for a word to be recovered + + Returns: + str: Recovered word or phrase. 'unknown' is returned if no word is recovered. + """ for input_word in sentence_list: for available_word in available_words: distance = self._get_levenshtein_soundex_distance( @@ -209,6 +277,15 @@ def _handle_similar_sound(self, sentence_list, available_words, distance_thresho return "unknown" def _infer_second_drink(self, sentence_list): + """Infer the second word of a two-worded drink phrase and hence the entire phrase, if + a word contained in any of the two-worded drink phrases is detected. + + Args: + sentence_list (List[str]): Transcription split up as a list of strings. + + Returns: + str: Recovered drink phrase. 'unknown' is returned if no drink phrase is recovered. + """ for input_word in sentence_list: for available_word in self._available_double_drinks: if input_word == available_word: @@ -216,6 +293,16 @@ def _infer_second_drink(self, sentence_list): return "unknown" def _handle_closest_spelt(self, sentence_list, choices): + """Get the closest spelt word from the list of choices (drinks or names) + in the sentence list (transcription). + + Args: + sentence_list (List[str]): Transcription split up as a list of strings. + choice (List[str]): List of choices to compare to (drinks or names) + + Returns: + str: Recovered closest spelt word. + """ closest_distance = float("inf") closest_word = None for input_word in sentence_list: @@ -229,6 +316,15 @@ def _handle_closest_spelt(self, sentence_list, choices): return closest_word def _recover_dubbelfris(self, sentence_list): + """Recover the drink dubbelfris if any of the words in the sentence list (transcription) is + similar enough (lower than the threshold) in terms of pronounciation to the word. + + Args: + sentence_list (List[str]): Transcription split up as a list of strings. + + Returns: + bool: Whether dubbelfris has been recovered + """ for word in sentence_list: if self._get_levenshtein_soundex_distance("dubbelfris", word) < 3: print(word) @@ -237,9 +333,28 @@ def _recover_dubbelfris(self, sentence_list): return False def _get_damerau_levenshtein_distance(self, word_1, word_2): + """Get the damerau-levenshtein distance between two words for the similarity in spelling. + + Args: + word_1 (str): First word + word_2 (str): Second word + + Returns: + int: Damerau-levenshtein distance between the two words. + """ return jf.damerau_levenshtein_distance(word_1, word_2) def _get_levenshtein_soundex_distance(self, word_1, word_2): + """Get the levenshtein distance between the soundex encoding of two words for the similarity + in pronounciation. + + Args: + word_1 (str): First word + word_2 (str): Second word + + Returns: + int: Levenshtein distance between the soundex encoding of the two words. + """ soundex_word_1 = jf.soundex(word_1) soundex_word_2 = jf.soundex(word_2) return jf.levenshtein_distance(soundex_word_1, soundex_word_2) From d65808ec2eedca7bcb5486c128a72bc979cc114f Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Thu, 25 Jul 2024 00:15:27 +0100 Subject: [PATCH 3/9] Minor fix --- tasks/receptionist/src/receptionist/states/speech_recovery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/receptionist/src/receptionist/states/speech_recovery.py b/tasks/receptionist/src/receptionist/states/speech_recovery.py index 1c6c24cb5..dfd8f52f9 100644 --- a/tasks/receptionist/src/receptionist/states/speech_recovery.py +++ b/tasks/receptionist/src/receptionist/states/speech_recovery.py @@ -118,7 +118,7 @@ def execute(self, userdata: UserData) -> str: Returns: str: state outcome. Updates the userdata with the parsed information (drink or name), under - the parameter "guest data". + the parameter "guest_data". """ filtered_sentence = userdata.guest_transcription.lower().translate( str.maketrans("", "", string.punctuation) From e28fec7d0849ee59ea4697a4e861fa52acbd2830 Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Thu, 25 Jul 2024 00:17:01 +0100 Subject: [PATCH 4/9] Minor fix --- tasks/receptionist/src/receptionist/states/speech_recovery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/receptionist/src/receptionist/states/speech_recovery.py b/tasks/receptionist/src/receptionist/states/speech_recovery.py index dfd8f52f9..653ae496d 100644 --- a/tasks/receptionist/src/receptionist/states/speech_recovery.py +++ b/tasks/receptionist/src/receptionist/states/speech_recovery.py @@ -298,7 +298,7 @@ def _handle_closest_spelt(self, sentence_list, choices): Args: sentence_list (List[str]): Transcription split up as a list of strings. - choice (List[str]): List of choices to compare to (drinks or names) + choices (List[str]): List of choices to compare to (drinks or names) Returns: str: Recovered closest spelt word. From dbab829395cc716c568fb8489ec7b82c5b30e445 Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Thu, 25 Jul 2024 00:22:56 +0100 Subject: [PATCH 5/9] Add typing for parameters and return types --- .../src/receptionist/states/speech_recovery.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/tasks/receptionist/src/receptionist/states/speech_recovery.py b/tasks/receptionist/src/receptionist/states/speech_recovery.py index 653ae496d..478be81c5 100644 --- a/tasks/receptionist/src/receptionist/states/speech_recovery.py +++ b/tasks/receptionist/src/receptionist/states/speech_recovery.py @@ -161,7 +161,7 @@ def execute(self, userdata: UserData) -> str: else: return "succeeded" - def _handle_name(self, sentence_list, last_resort): + def _handle_name(self, sentence_list: List[str], last_resort: bool) -> str: """Attempt to recover the name in the transcription. First recover via spelling, then pronounciation. Enter last resort if necessary and recover the closest spelt name. @@ -185,7 +185,7 @@ def _handle_name(self, sentence_list, last_resort): print("Last resort name") return self._handle_closest_spelt(sentence_list, self._available_names) - def _handle_drink(self, sentence_list, last_resort): + def _handle_drink(self, sentence_list: List[str], last_resort: bool) -> str: """Attempt to recover the drink in the transcription. For phrases containing two words, try to infer the second word in the phrase. If this fails, attempt to recover the drink via spelling, then pronounciation. Enter last resort if necessary and recover the closest spelt drink. @@ -233,7 +233,7 @@ def _handle_drink(self, sentence_list, last_resort): sentence_list.append(closest_spelt) return self._infer_second_drink(sentence_list) - def _handle_similar_spelt(self, sentence_list, available_words, distance_threshold): + def _handle_similar_spelt(self, sentence_list: List[str], available_words: List[str], distance_threshold: int) -> str: """Recover any word by spelling that has a similarity lower than the specified threshold when comparing each word in the sentence list to the list of available words. @@ -254,7 +254,7 @@ def _handle_similar_spelt(self, sentence_list, available_words, distance_thresho return available_word return "unknown" - def _handle_similar_sound(self, sentence_list, available_words, distance_threshold): + def _handle_similar_sound(self, sentence_list: List[str], available_words: List[str], distance_threshold: int) -> str: """Recover any word by pronounciation that has a similarity lower than the specified threshold when comparing each word in the sentence list to the list of available words. @@ -276,7 +276,7 @@ def _handle_similar_sound(self, sentence_list, available_words, distance_thresho return available_word return "unknown" - def _infer_second_drink(self, sentence_list): + def _infer_second_drink(self, sentence_list: List[str]) -> str: """Infer the second word of a two-worded drink phrase and hence the entire phrase, if a word contained in any of the two-worded drink phrases is detected. @@ -292,7 +292,7 @@ def _infer_second_drink(self, sentence_list): return self._double_drinks_dict[input_word] return "unknown" - def _handle_closest_spelt(self, sentence_list, choices): + def _handle_closest_spelt(self, sentence_list: List[str], choices: List[str]) -> str: """Get the closest spelt word from the list of choices (drinks or names) in the sentence list (transcription). @@ -315,7 +315,7 @@ def _handle_closest_spelt(self, sentence_list, choices): closest_word = available_word return closest_word - def _recover_dubbelfris(self, sentence_list): + def _recover_dubbelfris(self, sentence_list: List[str]) -> bool: """Recover the drink dubbelfris if any of the words in the sentence list (transcription) is similar enough (lower than the threshold) in terms of pronounciation to the word. @@ -332,7 +332,7 @@ def _recover_dubbelfris(self, sentence_list): return True return False - def _get_damerau_levenshtein_distance(self, word_1, word_2): + def _get_damerau_levenshtein_distance(self, word_1: str, word_2: str) -> int: """Get the damerau-levenshtein distance between two words for the similarity in spelling. Args: @@ -344,7 +344,7 @@ def _get_damerau_levenshtein_distance(self, word_1, word_2): """ return jf.damerau_levenshtein_distance(word_1, word_2) - def _get_levenshtein_soundex_distance(self, word_1, word_2): + def _get_levenshtein_soundex_distance(self, word_1: str, word_2: str) -> int: """Get the levenshtein distance between the soundex encoding of two words for the similarity in pronounciation. From 4c78a9ce67f9d653f375148077b172c8c8ac5bf8 Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Thu, 25 Jul 2024 00:29:47 +0100 Subject: [PATCH 6/9] Reformat --- .../lasr_person_following/person_following.py | 6 +- .../src/carry_my_luggage/state_machine.py | 18 ++- .../gpsr/src/gpsr/states/object_comparison.py | 123 +++++++++++++++++- .../receptionist/states/speech_recovery.py | 36 +++-- 4 files changed, 162 insertions(+), 21 deletions(-) diff --git a/common/navigation/lasr_person_following/src/lasr_person_following/person_following.py b/common/navigation/lasr_person_following/src/lasr_person_following/person_following.py index 06f3a2782..208ee3680 100644 --- a/common/navigation/lasr_person_following/src/lasr_person_following/person_following.py +++ b/common/navigation/lasr_person_following/src/lasr_person_following/person_following.py @@ -350,7 +350,11 @@ def _check_finished(self) -> bool: ) transcription = self._transcribe_speech_client.get_result().sequence - return "yes" in transcription.lower() or "arrived" in transcription.lower() or "arrive" in transcription.lower() + return ( + "yes" in transcription.lower() + or "arrived" in transcription.lower() + or "arrive" in transcription.lower() + ) return True def _get_pose_on_path( diff --git a/tasks/carry_my_luggage/src/carry_my_luggage/state_machine.py b/tasks/carry_my_luggage/src/carry_my_luggage/state_machine.py index a04048e5b..8669c160a 100644 --- a/tasks/carry_my_luggage/src/carry_my_luggage/state_machine.py +++ b/tasks/carry_my_luggage/src/carry_my_luggage/state_machine.py @@ -193,11 +193,19 @@ def wait_cb(ud, msg): def start_pose_cb(ud): try: - ud.start_pose = rospy.wait_for_message("/robot_pose", PoseWithCovarianceStamped, timeout=rospy.Duration(5.0)).pose.pose + ud.start_pose = rospy.wait_for_message( + "/robot_pose", + PoseWithCovarianceStamped, + timeout=rospy.Duration(5.0), + ).pose.pose except rospy.ROSException: rospy.logerr("Failed to get robot pose") - ud.start_pose = Pose(position=Point(0., 0., 0.0), orientation=Quaternion(0., 0., 0., 1.)) + ud.start_pose = Pose( + position=Point(0.0, 0.0, 0.0), + orientation=Quaternion(0.0, 0.0, 0.0, 1.0), + ) return "succeeded" + smach.StateMachine.add( "GET_START_LOCATION", smach.CBState( @@ -205,7 +213,7 @@ def start_pose_cb(ud): outcomes=["succeeded"], output_keys=["start_pose"], ), - transitions={"succeeded": "SAY_STEP"} + transitions={"succeeded": "SAY_STEP"}, ) smach.StateMachine.add( @@ -261,8 +269,8 @@ def start_pose_cb(ud): ) smach.StateMachine.add( - "GO_TO_START", # todo: instead, get the start position within the state machine, and return to it at the end + "GO_TO_START", # todo: instead, get the start position within the state machine, and return to it at the end GoToLocation(), - remapping={"location" : "start_pose"}, + remapping={"location": "start_pose"}, transitions={"succeeded": "succeeded", "failed": "succeeded"}, ) diff --git a/tasks/gpsr/src/gpsr/states/object_comparison.py b/tasks/gpsr/src/gpsr/states/object_comparison.py index 4b82afe1d..e5fdc376a 100755 --- a/tasks/gpsr/src/gpsr/states/object_comparison.py +++ b/tasks/gpsr/src/gpsr/states/object_comparison.py @@ -19,16 +19,133 @@ class ObjectComparison(smach.StateMachine): # TODO: fill this in - _smallest_list: List[str] = ["dishwasher_tab", "candle", "strawberry", "tictac", "plum", "lemon", "pear", "peach", "orange", "apple", "sponges", "fork", "knife", "spoon", "banana", "dubbelfris", "cola", "ice_tea", "fanta", "milk", "pea_soup", "sausages", "cup", "stroopwafel", "soap", "curry", "water", "crisps", "liquorice", "candy", "hagelslag", "pancake_mix", "mayonaise", "bowl", "plate", "washcloth", "pringles", "big_coke" ] + _smallest_list: List[str] = [ + "dishwasher_tab", + "candle", + "strawberry", + "tictac", + "plum", + "lemon", + "pear", + "peach", + "orange", + "apple", + "sponges", + "fork", + "knife", + "spoon", + "banana", + "dubbelfris", + "cola", + "ice_tea", + "fanta", + "milk", + "pea_soup", + "sausages", + "cup", + "stroopwafel", + "soap", + "curry", + "water", + "crisps", + "liquorice", + "candy", + "hagelslag", + "pancake_mix", + "mayonaise", + "bowl", + "plate", + "washcloth", + "pringles", + "big_coke", + ] _biggest_list: List[str] = reversed(_smallest_list) _largest_list: List[str] = _biggest_list - _heaviest_list: List[str] = ["big_coke", "pea_soup", "milk", "mayonaise", "cola", "ice_tea", "fanta", "dubbelfris", "water", "pancake_mix", "curry", "soap", "sausages", "apple", "orange", "peach", "pear", "lemon", "plum", "banana", "stroopwafel", "cup", "bowl", "plate", "washcloth", "sponges", "pringles", "crisps", "hagelslag", "liquorice", "candy", "knife", "fork", "spoon", "candle", "strawberry", "tictac", "dishwasher_tab"] + _heaviest_list: List[str] = [ + "big_coke", + "pea_soup", + "milk", + "mayonaise", + "cola", + "ice_tea", + "fanta", + "dubbelfris", + "water", + "pancake_mix", + "curry", + "soap", + "sausages", + "apple", + "orange", + "peach", + "pear", + "lemon", + "plum", + "banana", + "stroopwafel", + "cup", + "bowl", + "plate", + "washcloth", + "sponges", + "pringles", + "crisps", + "hagelslag", + "liquorice", + "candy", + "knife", + "fork", + "spoon", + "candle", + "strawberry", + "tictac", + "dishwasher_tab", + ] _lightest_list: List[str] = reversed(_heaviest_list) - _thinnest_list: List[str] = ["knife", "fork", "spoon", "candle", "strawberry", "tictac", "dishwasher_tab", "liquorice", "candy", "crisps", "stroopwafel", "soap", "sponges", "washcloth", "plate", "bowl", "cup", "pancake_mix", "hagelslag", "curry", "mayonaise", "pea_soup", "sausages", "milk", "water", "dubbelfris", "cola", "ice_tea", "fanta", "big_coke", "apple", "orange", "peach", "pear", "lemon", "plum", "banana", "pringles"] + _thinnest_list: List[str] = [ + "knife", + "fork", + "spoon", + "candle", + "strawberry", + "tictac", + "dishwasher_tab", + "liquorice", + "candy", + "crisps", + "stroopwafel", + "soap", + "sponges", + "washcloth", + "plate", + "bowl", + "cup", + "pancake_mix", + "hagelslag", + "curry", + "mayonaise", + "pea_soup", + "sausages", + "milk", + "water", + "dubbelfris", + "cola", + "ice_tea", + "fanta", + "big_coke", + "apple", + "orange", + "peach", + "pear", + "lemon", + "plum", + "banana", + "pringles", + ] _query: Literal[ "biggest", "largest", "smallest", "heaviest", "lightest", "thinnest" diff --git a/tasks/receptionist/src/receptionist/states/speech_recovery.py b/tasks/receptionist/src/receptionist/states/speech_recovery.py index 478be81c5..3fdf91cd2 100644 --- a/tasks/receptionist/src/receptionist/states/speech_recovery.py +++ b/tasks/receptionist/src/receptionist/states/speech_recovery.py @@ -18,7 +18,7 @@ def __init__( last_resort: bool, input_type: str = "", ): - """Recover the correct name and / or drink by parsing the transcription. + """Recover the correct name and / or drink by parsing the transcription. Args: guest_id (str): ID of the guest (identifying the guest) @@ -26,7 +26,7 @@ def __init__( input_type (str, optional): The type of information to try and extract useful information (drink or name) """ - + smach.State.__init__( self, outcomes=["succeeded", "failed"], @@ -186,8 +186,8 @@ def _handle_name(self, sentence_list: List[str], last_resort: bool) -> str: return self._handle_closest_spelt(sentence_list, self._available_names) def _handle_drink(self, sentence_list: List[str], last_resort: bool) -> str: - """Attempt to recover the drink in the transcription. For phrases containing two words, try to infer the - second word in the phrase. If this fails, attempt to recover the drink via spelling, then pronounciation. + """Attempt to recover the drink in the transcription. For phrases containing two words, try to infer the + second word in the phrase. If this fails, attempt to recover the drink via spelling, then pronounciation. Enter last resort if necessary and recover the closest spelt drink. Args: @@ -233,9 +233,14 @@ def _handle_drink(self, sentence_list: List[str], last_resort: bool) -> str: sentence_list.append(closest_spelt) return self._infer_second_drink(sentence_list) - def _handle_similar_spelt(self, sentence_list: List[str], available_words: List[str], distance_threshold: int) -> str: - """Recover any word by spelling that has a similarity lower than the specified threshold - when comparing each word in the sentence list to the list of available words. + def _handle_similar_spelt( + self, + sentence_list: List[str], + available_words: List[str], + distance_threshold: int, + ) -> str: + """Recover any word by spelling that has a similarity lower than the specified threshold + when comparing each word in the sentence list to the list of available words. Args: sentence_list (List[str]): Transcription split up as a list of strings. @@ -254,9 +259,14 @@ def _handle_similar_spelt(self, sentence_list: List[str], available_words: List[ return available_word return "unknown" - def _handle_similar_sound(self, sentence_list: List[str], available_words: List[str], distance_threshold: int) -> str: - """Recover any word by pronounciation that has a similarity lower than the specified threshold - when comparing each word in the sentence list to the list of available words. + def _handle_similar_sound( + self, + sentence_list: List[str], + available_words: List[str], + distance_threshold: int, + ) -> str: + """Recover any word by pronounciation that has a similarity lower than the specified threshold + when comparing each word in the sentence list to the list of available words. Args: sentence_list (List[str]): Transcription split up as a list of strings. @@ -292,8 +302,10 @@ def _infer_second_drink(self, sentence_list: List[str]) -> str: return self._double_drinks_dict[input_word] return "unknown" - def _handle_closest_spelt(self, sentence_list: List[str], choices: List[str]) -> str: - """Get the closest spelt word from the list of choices (drinks or names) + def _handle_closest_spelt( + self, sentence_list: List[str], choices: List[str] + ) -> str: + """Get the closest spelt word from the list of choices (drinks or names) in the sentence list (transcription). Args: From 44239a39f5d97abc7a9ca13c946388cd0a8cf7ef Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Thu, 25 Jul 2024 00:38:29 +0100 Subject: [PATCH 7/9] Fix an unknown duplication --- .../src/receptionist/states/get_name_and_drink.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tasks/receptionist/src/receptionist/states/get_name_and_drink.py b/tasks/receptionist/src/receptionist/states/get_name_and_drink.py index 1808dc030..be3ceabfd 100644 --- a/tasks/receptionist/src/receptionist/states/get_name_and_drink.py +++ b/tasks/receptionist/src/receptionist/states/get_name_and_drink.py @@ -126,11 +126,6 @@ def __init__( last_resort: bool, param_key: str = "/receptionist/priors", ): - self, - guest_id: str, - last_resort: bool, - param_key: str = "/receptionist/priors", - ): self._guest_id = guest_id self._param_key = param_key From 40cf4a0f5a830aacd6fb9d1bc229dbae974f6e0e Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Thu, 25 Jul 2024 00:39:41 +0100 Subject: [PATCH 8/9] Reformat --- .../receptionist/states/get_name_and_drink.py | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/tasks/receptionist/src/receptionist/states/get_name_and_drink.py b/tasks/receptionist/src/receptionist/states/get_name_and_drink.py index be3ceabfd..3546e1583 100644 --- a/tasks/receptionist/src/receptionist/states/get_name_and_drink.py +++ b/tasks/receptionist/src/receptionist/states/get_name_and_drink.py @@ -78,7 +78,6 @@ def execute(self, userdata: UserData) -> str: return outcome - class PostRecoveryDecision(smach.State): def __init__( self, @@ -96,7 +95,6 @@ def __init__( self._possible_names = [name.lower() for name in prior_data["names"]] self._possible_drinks = [drink.lower() for drink in prior_data["drinks"]] - def execute(self, userdata: UserData) -> str: if not self._recovery_name_and_drink_required(userdata): if userdata.guest_data[self._guest_id]["name"] == "unknown": @@ -107,7 +105,6 @@ def execute(self, userdata: UserData) -> str: outcome = "failed" return outcome - def _recovery_name_and_drink_required(self, userdata: UserData) -> bool: """Determine whether both the name and drink requires recovery. @@ -167,11 +164,11 @@ def __init__( ) def __init__( - self, - guest_id: str, - last_resort: bool, - param_key: str = "/receptionist/priors", - ): + self, + guest_id: str, + last_resort: bool, + param_key: str = "/receptionist/priors", + ): self._guest_id = guest_id self._param_key = param_key @@ -182,26 +179,32 @@ def __init__( outcomes=["succeeded", "failed", "failed_name", "failed_drink"], input_keys=["guest_transcription", "guest_data"], output_keys=["guest_data", "guest_transcription"], - ) with self: smach.StateMachine.add( "PARSE_NAME_AND_DRINK", - self.ParseNameAndDrink(guest_id=self._guest_id, param_key=self._param_key), + self.ParseNameAndDrink( + guest_id=self._guest_id, param_key=self._param_key + ), transitions={"succeeded": "succeeded", "failed": "SPEECH_RECOVERY"}, ) smach.StateMachine.add( "SPEECH_RECOVERY", SpeechRecovery(self._guest_id, self._last_resort), - transitions={"succeeded": "succeeded", "failed": "POST_RECOVERY_DECISION"}, + transitions={ + "succeeded": "succeeded", + "failed": "POST_RECOVERY_DECISION", + }, ) smach.StateMachine.add( "POST_RECOVERY_DECISION", - self.PostRecoveryDecision(guest_id=self._guest_id, param_key=self._param_key), + self.PostRecoveryDecision( + guest_id=self._guest_id, param_key=self._param_key + ), transitions={ "failed": "failed", "failed_name": "failed_name", "failed_drink": "failed_drink", }, - ) \ No newline at end of file + ) From 76d0f58fa00b516a70a2be30c1563fa5ab48892a Mon Sep 17 00:00:00 2001 From: Haiwei L Date: Thu, 25 Jul 2024 00:46:38 +0100 Subject: [PATCH 9/9] Remove duplicated __init__ function in get_name_and_drink --- .../receptionist/states/get_name_and_drink.py | 46 ------------------- 1 file changed, 46 deletions(-) diff --git a/tasks/receptionist/src/receptionist/states/get_name_and_drink.py b/tasks/receptionist/src/receptionist/states/get_name_and_drink.py index 3546e1583..b20bd862e 100644 --- a/tasks/receptionist/src/receptionist/states/get_name_and_drink.py +++ b/tasks/receptionist/src/receptionist/states/get_name_and_drink.py @@ -162,49 +162,3 @@ def __init__( "failed_drink": "failed_drink", }, ) - - def __init__( - self, - guest_id: str, - last_resort: bool, - param_key: str = "/receptionist/priors", - ): - - self._guest_id = guest_id - self._param_key = param_key - self._last_resort = last_resort - - smach.StateMachine.__init__( - self, - outcomes=["succeeded", "failed", "failed_name", "failed_drink"], - input_keys=["guest_transcription", "guest_data"], - output_keys=["guest_data", "guest_transcription"], - ) - with self: - - smach.StateMachine.add( - "PARSE_NAME_AND_DRINK", - self.ParseNameAndDrink( - guest_id=self._guest_id, param_key=self._param_key - ), - transitions={"succeeded": "succeeded", "failed": "SPEECH_RECOVERY"}, - ) - smach.StateMachine.add( - "SPEECH_RECOVERY", - SpeechRecovery(self._guest_id, self._last_resort), - transitions={ - "succeeded": "succeeded", - "failed": "POST_RECOVERY_DECISION", - }, - ) - smach.StateMachine.add( - "POST_RECOVERY_DECISION", - self.PostRecoveryDecision( - guest_id=self._guest_id, param_key=self._param_key - ), - transitions={ - "failed": "failed", - "failed_name": "failed_name", - "failed_drink": "failed_drink", - }, - )