public void SendTextToNLU(EventMessageObject asrRequestMessageObject) { string asrRequest = (string)asrRequestMessageObject.MessageBody; PrintMessageBody(asrRequestMessageObject); nlu.UnderstandRequest(asrRequest); }
//Gibt ein Präfix gefolgt vom Inhalt der EventMessage im debugTextfeld aus private void PrintMessageBody(EventMessageObject _eventMessageObject) { string messageBody; try { messageBody = (string)_eventMessageObject.MessageBody; } catch (Exception e) { Debug.LogError("Falscher Typ des Message Bodys Objekts" + e.Message); messageBody = "ERROR"; } string messageType = _eventMessageObject.Type; if (messageType.Equals(EventManager.keywordDetectedEvent)) { debugText.text = "Keyword detected: " + messageBody; } else if (messageType.Equals(EventManager.asrRequerstDetectedEvent)) { debugText.text = "ASR Request detected: " + messageBody; } else if (messageType.Equals(EventManager.nluAnswerDetectedEvent)) { debugText.text = "NLU answer detected: " + messageBody; } }
/* public static void TriggerEvent (string eventName, Object args ) * { * UnityEventWithParameter thisEvent = null; * if (instance.eventDictonary.TryGetValue(eventName, out thisEvent)) * { * thisEvent.Invoke(); * } * }*/ public static void TriggerEvent(string eventName, EventMessageObject args) { UnityEventWithParameter thisEvent = null; if (instance.eventDictonary.TryGetValue(eventName, out thisEvent)) { thisEvent.Invoke(args); } }
private void SSTErrorHandling(EventMessageObject args) //Prüfe bei Fehlern der SST den ASR Zustand und starte ggf. WakeWordEngine { //Prüfe #Kommandos in Schlange -> keine + kein aktiver Wechsel-> gehe zu WWE; sonst: Ausgabe aller Befehle + Handle je nachdem was drin steht if (ASRModeSwitchQueue.Count == 0 && WakeWordState != SpeechSystemStatus.Running && !isSwitchingASRMode) //Zurückwechseln zur WWE notwendig, da sonst keine ASR Technik mehr aktiv ist { Debug.LogErrorFormat("Die Schlange war leer als der Fehler auftrag {0}. Füge deshalb Wechsel zu WWE hinzu ", args.MessageBody); ASRModeSwitchQueue.Enqueue(SwitchToWWE); } else if (ASRModeSwitchQueue.Count > 0) { Debug.LogError("Benötige weitere Fehlerbehandlung da STT Fehler auftrat als die Schalange wie folgt gefüllt war:"); int i = 0; foreach (AsrSwitchDelegate command in ASRModeSwitchQueue) { Debug.LogErrorFormat("Befehl {0} befindet sich an Position {1}", command.Method.Name, i); i++; } } else { Debug.LogErrorFormat("Schlange war leer bei ASR Fehleranzeige. Aber keine Wechsel hinzugefügt da entweder STT oder Wechsel aktiv."); } }
public void AddWWERequestToQueue(EventMessageObject args) { Debug.LogFormat("Wechsel zu WWE angefordert. Message: {0}", args.MessageBody.ToString()); ASRModeSwitchQueue.Enqueue(SwitchToWWE); }
public void HandleIntent(EventMessageObject nluAnswer) { AIResponse nluResponse = (AIResponse)nluAnswer.MessageBody; Debug.Log("##### Habe folgenden Intent erkannt und möchte ihn jetzt verarbeiten: " + nluResponse.Result.Metadata.IntentName); //Dialog Delegation prüfen Debug.Log("Überprüfe ob noch Slots fehlen: "); //AIOutputContext context = nluResponse.Result.GetContext(); AIOutputContext[] context = nluResponse.Result.Contexts; bool slotsMissing = false; foreach (AIOutputContext con in context) { Debug.Log(con.Name); if (con.Name.Contains("dialog_context")) { slotsMissing = true; } } if (slotsMissing) { wasInDialogDelegationLastRound = true; //damit nächster Intent sieht, ob DialogDelegation zuvor aktiv war slotMissingRounds++; Debug.Log("Es fehlen noch Slotbelegungen. Ich gebe die Kontrolle an TTS"); //Debug.Log("WWE Status " + asr.WakeWordState); //Debug.Log("STT Status " + asr.DictationState); EventManager.TriggerEvent(EventManager.keywordDetectedEvent, new EventMessageObject(EventManager.keywordDetectedEvent, "Slots fehlen")); //actions.DisplayText(debugText, nluResponse.Result.Fulfillment.Speech); string cancelInfo = ""; if (slotMissingRounds > 1) { cancelInfo = "Du kannst ungewollte Anfragen jederzeit beenden, indem du abbrechen sagst."; } WindowsVoice.speak(string.Format("{0} {1}", cancelInfo, nluResponse.Result.Fulfillment.Speech), delay: 0f); } //ansonsten rufe die Handler auf else { slotMissingRounds = 0; Debug.Log("Alle Slots gefüllt:"); Dictionary <String, System.Object> dic = nluResponse.Result.Parameters; foreach (String key in dic.Keys) { Debug.Log(string.Format("Parameter: {0}", key)); } actions.DisplayText(debugText, nluResponse.Result.Fulfillment.Speech); String intent = nluResponse.Result.Metadata.IntentName; Result nluResultObj = nluResponse.Result; //Ausgabe der Dialogflow Response -> Metadata.EndConversation Boolean bestimmt ob als Frage oder Aussage //***Kann in Unity JSON Objekt bisher nicht abgerufen werden -> Parameter: endConversation simuliert ihn bool canceledDialogDelegation = nluResponse.Result.ResolvedQuery.Equals("abbrechen") && wasInDialogDelegationLastRound ? true:false; //Dialogflow eigenes Abbrechen simuliert endConversation nicht if (nluResultObj.Fulfillment.Speech != "") { if (nluResultObj.GetStringParameter("endConversation").Equals("true") || canceledDialogDelegation) //***evtl. muss hier eine Abfrage rein die beim default fallback auch das mikrofon schließt { actions.Speak(nluResultObj.Fulfillment.Speech); } else //ansonsten öffne das Mikrofon wieder { actions.AskQuestion(nluResultObj.Fulfillment.Speech); } } String action = nluResponse.Result.Action; bool noActionIntent = false; //wird true falls der Intent keine Action enthält oder diese nicht implementiert ist switch (action) { /*case IPAAction.askQuestion: * actions.AskQuestion(nluResultObj.GetStringParameter("speak")); * break; * * * case IPAAction.speak: * actions.Speak(nluResultObj.GetStringParameter("speak")); * break;*/ //Intents zur Fahrzeugsteuerung case IPAAction.moveCar: String groesseneinheit = nluResultObj.GetStringParameter("Groesseneinheit"); String direction = nluResultObj.GetStringParameter("MoveDirection"); actions.MoveCar(groesseneinheit, direction); break; case IPAAction.stopCar: actions.StopCarMovement(); break; case IPAAction.takeCarControl: actions.TakeCarControl(); break; case IPAAction.getCarControlBack: actions.GetCarControlBack(); break; case IPAAction.takePlateControl: actions.TakePlateControl(); break; case IPAAction.getPlateControlBack: actions.GetPlateControlBack(); break; //Map Manipulation Intents: case IPAAction.openMap: actions.OpenMap(); break; case IPAAction.closeMap: actions.CloseMap(); actions.SetMinimapFokusOnCar(); break; case IPAAction.saveNavigationPoint: actions.SaveNavigationPoint(minimapLocationIcon); break; case IPAAction.deleteNavigationPoint: int zielNummer2 = Int32.Parse(nluResultObj.GetStringParameter("navigationNumber")); actions.DeleteNavigationPoint(zielNummer2); break; case IPAAction.changeMapFixedStep: groesseneinheit = nluResponse.Result.GetStringParameter("Groesseneinheit"); direction = nluResponse.Result.GetStringParameter("Direction"); if (direction.Length == 0) { direction = nluResponse.Result.GetStringParameter("MoveDirection"); } actions.ChangMapFixedStep(groesseneinheit, direction); break; case IPAAction.focusOnCar: actions.SetMinimapFokusOnCar(); break; //Navigation Intents: case IPAAction.startNavigation: int zielNummer = Int32.Parse(nluResultObj.GetStringParameter("navigationNumber")); if (sharedData.savedPlacesOnMap.Count > zielNummer - 1) { Vector3 target = sharedData.savedPlacesOnMap[zielNummer - 1].transform.position; actions.StartNavigation(target); } else { WindowsVoice.speak(string.Format("Ich konnte keinen Ort mit Nummer {0} finden.", zielNummer), 3); } break; case IPAAction.endNavigation: actions.EndNavigation(); break; //Intents zur Unterstützung der Teststreckenerstellung case IPAAction.restartTraining: SceneManager.LoadScene("Level1Training"); // Todo:Index auf Namen der Szene ändern break; case IPAAction.setCheckpoint: actions.SetTrainingCheckpoint(sharedData.currentFrameCount); actions.Speak("Sicherungspunkt erstellt bei Frame:" + sharedData.currentFrameCount); break; case IPAAction.discardCheckpoint: actions.SetTrainingCheckpoint(0); break; case IPAAction.endTrainingRouteCreation: actions.EndTraining(); /*sharedData.trainingRouteRecordingStopped = true; //Beendet hinzufügen neuer Framestrokes in AlternateCarController * * * //Entferne PlayerControl und Ball * sharedData.SetPlayerControl(false); * GameObject.FindGameObjectWithTag("Ball").SetActive(false); * if (String.IsNullOrEmpty(sharedData.playerName)) * { * Debug.LogError("Fehler bei Namenserfassung. Öffne Texteingabe."); * GameObject.Find("NameQuestionCanvas").GetComponent<Canvas>().enabled = true; * }*/ break; case IPAAction.performanceAndDifficultyMeasured: bool performanceOK = nluResultObj.GetStringParameter("Performance").Equals("gut") ? true : false; if (sharedData.debugMode && performanceOK) { //Debug.LogError(WindowsVoice.statusMessage); sharedData.trainingRouteDifficulty = nluResultObj.GetStringParameter("Difficulty") + "/"; //sobald gesetzt schreibt AlternateCarController die Route entsprechend ca Codezeile 500 //Beende verzögert StartCoroutine(SharedFields.DelayedQuit(10f)); } else { Debug.LogError(nluResultObj.GetStringParameter("Performance")); actions.Speak("Verwerfe Strecke aufgrund schlechter Performance. Beende Programm"); IEnumerator co = SharedFields.DelayedQuit(10f); StartCoroutine(co); //Application.Quit(); } break; case IPAAction.wantToSetContext: int firstFreeContext = context.Length; AIOutputContext[] newContext = new AIOutputContext[firstFreeContext + 1]; AIOutputContext contextToInsert = new AIOutputContext(); contextToInsert.Name = "TestContext"; contextToInsert.Lifespan = 3; newContext[firstFreeContext] = contextToInsert; context = newContext; Debug.Log("So sollte es aussehen:"); foreach (AIOutputContext con in context) { Debug.Log(con.Name); if (con.Name.Contains("dialog_context")) { slotsMissing = true; } } Debug.Log("Trigger SpeechCommandRecognized to send new Context to Dialogflow"); EventManager.TriggerEvent(EventManager.asrRequerstDetectedEvent, new EventMessageObject(EventManager.asrRequerstDetectedEvent, string.Format("Rueckantwort Kontext einfuegen"))); break; case IPAAction.setContext: Debug.Log("Habe Kontext gesetzt."); foreach (AIOutputContext con in context) { Debug.Log(con.Name); if (con.Name.Contains("dialog_context")) { slotsMissing = true; } } break; //PlayerInfo case IPAAction.setPlayerName: //var outText = NewJSon::Newtonsoft.Json.JsonConvert.SerializeObject(nluResultObj.GetJsonParameter("UserName"), jsonSettings); //Debug.LogError(outText); string name = ""; //Sonderbehandlung falls Dialogflow Entitie givenName benutzt -> bekomme neues Dict statt String Dictionary <string, object> parameterDict = nluResultObj.Parameters; Type t = parameterDict["UserName"].GetType(); bool isDict = t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Dictionary <,>); Dictionary <string, object> givenNameEntitie; if (isDict) { givenNameEntitie = (Dictionary <string, object>)parameterDict["UserName"]; try { name = (string)givenNameEntitie["given-name"]; } catch (KeyNotFoundException) { name = (string)givenNameEntitie["MapStringsToName"]; } } else { name = nluResultObj.GetStringParameter("UserName"); } //Debug.LogErrorFormat("is dict? {0}", isDict); //Debug.LogError( parameterDict["UserName"].GetType()); Debug.LogError("Haben folgenden Namen erkannt: " + name); if (String.IsNullOrEmpty(name)) { Debug.LogError("******Name konnte nicht gesetzt werden. Baue erneute Nachfrage ein?"); } actions.SetPlayerName(name); Debug.LogError("Der neue Name ist: " + sharedData.playerName); break; case IPAAction.rename: EventManager.TriggerEvent(EventManager.asrRequerstDetectedEvent, new EventMessageObject(EventManager.asrRequerstDetectedEvent, "Spielerwechsel")); break; //Allgemeine Befehle: case IPAAction.repeatAnswer: actions.Speak(lastIPAspeech); break; case IPAAction.repeatLastAction: if (repeatableTasksDict.ContainsKey(lastIPAAction)) { EventManager.TriggerEvent(EventManager.asrRequerstDetectedEvent, new EventMessageObject(EventManager.asrRequerstDetectedEvent, repeatableTasksDict[lastIPAAction])); } break; case IPAAction.undo: string undoAction = ""; Debug.LogError("Last Action was: " + lastIPAAction); if (symmetricTasksDict.ContainsKey(lastIPAAction)) { undoAction = symmetricTasksDict[lastIPAAction]; } else if (symmetricTasksDict.ContainsValue(lastIPAAction)) { foreach (KeyValuePair <string, string> keyValue in symmetricTasksDict) { if (keyValue.Value.Equals(lastIPAAction)) { undoAction = keyValue.Key; } } } else { Debug.LogErrorFormat("Der letzte Task hatte keine Implementierung eines symmetrischen Gegenparts"); WindowsVoice.speak("Der letzte Task hatte keine Implementierung eines symmetrischen Gegenparts", 2); } if (eventTriggerStringForActionDict.ContainsKey(undoAction)) { string voiceCommandForUndoAction = eventTriggerStringForActionDict[undoAction]; EventManager.TriggerEvent(EventManager.asrRequerstDetectedEvent, new EventMessageObject(EventManager.asrRequerstDetectedEvent, voiceCommandForUndoAction)); } else { actions.Speak("Ich kann die letzte Aktion nicht rueckgängig machen. Die eingetragenen Funktionspaare funktionieren nur in die andere Richtung."); } break; case IPAAction.wantMoreHelp: //Ermittle zuletzt thematisierte Kategorie und simuliere eine entsprechende Anfrage an die NLU int navigationHelpSessionCount = 0; int mlTrainingHelpSessionCount = 0; int driveHelpSessionCount = 0; foreach (AIOutputContext currentContext in nluResponse.Result.Contexts) { string contextName = currentContext.Name; if (contextName.Equals("mltraininghelprequested")) { Debug.Log("habe training kontext"); mlTrainingHelpSessionCount += (int)currentContext.Lifespan; } else if (context.Equals("navigationhelprequested")) { Debug.Log("habe navigation kontext"); navigationHelpSessionCount += (int)currentContext.Lifespan; } else if (context.Equals("drivehelprequested")) { Debug.Log("habe drive kontext"); driveHelpSessionCount += (int)currentContext.Lifespan; } } if (navigationHelpSessionCount > Math.Max(mlTrainingHelpSessionCount, driveHelpSessionCount)) { EventManager.TriggerEvent(EventManager.asrRequerstDetectedEvent, new EventMessageObject(EventManager.asrRequerstDetectedEvent, "Ich brauche Hilfe in der Kategorie Fahren.")); } else if (mlTrainingHelpSessionCount > Math.Max(navigationHelpSessionCount, driveHelpSessionCount)) { EventManager.TriggerEvent(EventManager.asrRequerstDetectedEvent, new EventMessageObject(EventManager.asrRequerstDetectedEvent, "Hilf mir beim trainieren")); } else if (driveHelpSessionCount > Math.Max(navigationHelpSessionCount, mlTrainingHelpSessionCount)) { EventManager.TriggerEvent(EventManager.asrRequerstDetectedEvent, new EventMessageObject(EventManager.asrRequerstDetectedEvent, "Hilf mir beim Navigieren")); } else { Debug.LogFormat("Konnte kein Event auslösen: navigationHelpSessionCount {0} mlTrainingHelpSessionCount{1}, driveHelpSessionCount {2}", navigationHelpSessionCount, mlTrainingHelpSessionCount, driveHelpSessionCount); } break; case IPAAction.continueGame: actions.ContinueGame(); break; case IPAAction.pauseGame: actions.PauseGame(); break; case IPAAction.quitGame: Application.Quit(); break; default: Debug.Log(string.Format("Der Intent {0} wurde im IntentHandler nicht registiert.", intent)); noActionIntent = true; //WindowsVoice.speak("Diesen Intent kenne ich nicht", 0f); //wird von Fallback Intent in Block unten gemacht break; } //Die letzte Aktion soll von Intents ohne Action nicht überschrieben werden if (!noActionIntent) { lastIPAAction = action; } } lastIPAspeech = nluResponse.Result.Fulfillment.Speech; Debug.LogError(lastIPAspeech + " ist zuletzt gesagtes"); }