From 18cece4d8d5622f7b2a77e3cc73cbb9671a7594a Mon Sep 17 00:00:00 2001 From: Raffaele Colombo Date: Wed, 27 Sep 2023 17:27:03 +0200 Subject: [PATCH] added chatBot nwc --- app/r1Obr-orchestrator/CMakeLists.txt | 9 +- .../conf/chatBot_nwc_test.ini | 1 + .../conf/r1Obr-orchestrator_R1.ini | 7 +- .../conf/r1Obr-orchestrator_R1_demo.ini | 7 +- ...Obr-orchestrator_R1_noContinuousSearch.ini | 7 +- .../conf/robotInterface/chatBot_nwc_test.xml | 18 ++ .../speechSynthesizer_nwc_test.xml | 18 ++ .../conf/speechSynthesizer_nwc_test.ini | 1 + modules/r1Obr-orchestrator/inputManager.cpp | 157 ++++++++++++++++++ .../{input_collector.h => inputManager.h} | 28 +++- .../r1Obr-orchestrator/input_collector.cpp | 104 ------------ .../r1Obr-orchestrator/r1Obr-orchestrator.cpp | 27 +-- .../r1Obr-orchestrator/r1Obr-orchestrator.h | 13 +- 13 files changed, 260 insertions(+), 137 deletions(-) create mode 100644 app/r1Obr-orchestrator/conf/chatBot_nwc_test.ini create mode 100644 app/r1Obr-orchestrator/conf/robotInterface/chatBot_nwc_test.xml create mode 100644 app/r1Obr-orchestrator/conf/robotInterface/speechSynthesizer_nwc_test.xml create mode 100644 app/r1Obr-orchestrator/conf/speechSynthesizer_nwc_test.ini create mode 100644 modules/r1Obr-orchestrator/inputManager.cpp rename modules/r1Obr-orchestrator/{input_collector.h => inputManager.h} (62%) delete mode 100644 modules/r1Obr-orchestrator/input_collector.cpp diff --git a/app/r1Obr-orchestrator/CMakeLists.txt b/app/r1Obr-orchestrator/CMakeLists.txt index c958705..602a311 100644 --- a/app/r1Obr-orchestrator/CMakeLists.txt +++ b/app/r1Obr-orchestrator/CMakeLists.txt @@ -1,10 +1,11 @@ set(appname r1Obr-orchestrator) -file(GLOB conf ${CMAKE_CURRENT_SOURCE_DIR}/conf/*.ini) -file(GLOB templates ${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.template) -file(GLOB apps ${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.xml) +file(GLOB conf ${CMAKE_CURRENT_SOURCE_DIR}/conf/*.ini) +file(GLOB robotInterface ${CMAKE_CURRENT_SOURCE_DIR}/conf/robotInterface/*.xml) +file(GLOB templates ${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.template) +file(GLOB apps ${CMAKE_CURRENT_SOURCE_DIR}/scripts/*.xml) yarp_install(FILES ${conf} DESTINATION ${${PROJECT_NAME}_CONTEXTS_INSTALL_DIR}/${appname}) yarp_install(FILES ${apps} DESTINATION ${${PROJECT_NAME}_APPLICATIONS_INSTALL_DIR}) yarp_install(FILES ${scripts} DESTINATION ${${PROJECT_NAME}_APPLICATIONS_TEMPLATES_INSTALL_DIR}) - +yarp_install(FILES ${robotInterface} DESTINATION ${${PROJECT_NAME}_CONTEXTS_INSTALL_DIR}/${appname}/robotInterface) \ No newline at end of file diff --git a/app/r1Obr-orchestrator/conf/chatBot_nwc_test.ini b/app/r1Obr-orchestrator/conf/chatBot_nwc_test.ini new file mode 100644 index 0000000..7c2b095 --- /dev/null +++ b/app/r1Obr-orchestrator/conf/chatBot_nwc_test.ini @@ -0,0 +1 @@ +config robotInterface/chatBot_nwc_test.xml \ No newline at end of file diff --git a/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1.ini b/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1.ini index 076c049..1fc365c 100644 --- a/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1.ini +++ b/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1.ini @@ -1,13 +1,18 @@ input_rpc_port /r1Obr-orchestrator/rpc +input_port /r1Obr-orchestrator/input:i sensor_network_rpc_port /r1Obr-orchestrator/sensor_network:rpc next_loc_planner_rpc_port /r1Obr-orchestrator/nextLocPlanner/request:rpc goandfindit_rpc_port /r1Obr-orchestrator/goAndFindIt/request:rpc goandfindit_result_port /r1Obr-orchestrator/goAndFindIt/result:i faceexpression_rpc_port /r1Obr-orchestrator/faceExpression:rpc -[INPUT_PORT_GROUP] +[INPUT_MANAGER] voice_command_port /r1Obr-orchestrator/voice_command:i input_command_port /r1Obr-orchestrator/input_command:i +chatbot_active true +device chatBot_nwc_yarp +local /r1Obr-orchestrator/chatBot +remote /chatBot_nws/rpc [SPEECH_SYNTHESIZER] active true diff --git a/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1_demo.ini b/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1_demo.ini index bb43e2a..a9e37b2 100644 --- a/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1_demo.ini +++ b/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1_demo.ini @@ -1,13 +1,18 @@ input_rpc_port /r1Obr-orchestrator/rpc +input_port /r1Obr-orchestrator/input:i sensor_network_rpc_port /r1Obr-orchestrator/sensor_network:rpc next_loc_planner_rpc_port /r1Obr-orchestrator/nextLocPlanner/request:rpc goandfindit_rpc_port /r1Obr-orchestrator/goAndFindIt/request:rpc goandfindit_result_port /r1Obr-orchestrator/goAndFindIt/result:i faceexpression_rpc_port /r1Obr-orchestrator/faceExpression:rpc -[INPUT_PORT_GROUP] +[INPUT_MANAGER] voice_command_port /r1Obr-orchestrator/voice_command:i input_command_port /r1Obr-orchestrator/input_command:i +chatbot_active true +device chatBot_nwc_yarp +local /r1Obr-orchestrator/chatBot +remote /chatBot_nws/rpc [SPEECH_SYNTHESIZER] active true diff --git a/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1_noContinuousSearch.ini b/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1_noContinuousSearch.ini index 4104468..83fd901 100644 --- a/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1_noContinuousSearch.ini +++ b/app/r1Obr-orchestrator/conf/r1Obr-orchestrator_R1_noContinuousSearch.ini @@ -1,13 +1,18 @@ input_rpc_port /r1Obr-orchestrator/rpc +input_port /r1Obr-orchestrator/input:i sensor_network_rpc_port /r1Obr-orchestrator/sensor_network:rpc next_loc_planner_rpc_port /r1Obr-orchestrator/nextLocPlanner/request:rpc goandfindit_rpc_port /r1Obr-orchestrator/goAndFindIt/request:rpc goandfindit_result_port /r1Obr-orchestrator/goAndFindIt/result:i faceexpression_rpc_port /r1Obr-orchestrator/faceExpression:rpc -[INPUT_PORT_GROUP] +[INPUT_MANAGER] voice_command_port /r1Obr-orchestrator/voice_command:i input_command_port /r1Obr-orchestrator/input_command:i +chatbot_active true +device chatBot_nwc_yarp +local /r1Obr-orchestrator/chatBot +remote /chatBot_nws/rpc [SPEECH_SYNTHESIZER] active true diff --git a/app/r1Obr-orchestrator/conf/robotInterface/chatBot_nwc_test.xml b/app/r1Obr-orchestrator/conf/robotInterface/chatBot_nwc_test.xml new file mode 100644 index 0000000..3b342ae --- /dev/null +++ b/app/r1Obr-orchestrator/conf/robotInterface/chatBot_nwc_test.xml @@ -0,0 +1,18 @@ + + + + + + + + /test/chatBot + + + /chatBot_nws/rpc + + + + \ No newline at end of file diff --git a/app/r1Obr-orchestrator/conf/robotInterface/speechSynthesizer_nwc_test.xml b/app/r1Obr-orchestrator/conf/robotInterface/speechSynthesizer_nwc_test.xml new file mode 100644 index 0000000..ef52a5f --- /dev/null +++ b/app/r1Obr-orchestrator/conf/robotInterface/speechSynthesizer_nwc_test.xml @@ -0,0 +1,18 @@ + + + + + + + + /test/speechSynthesizer + + + /speechSynthesizer_nws_yarp + + + + \ No newline at end of file diff --git a/app/r1Obr-orchestrator/conf/speechSynthesizer_nwc_test.ini b/app/r1Obr-orchestrator/conf/speechSynthesizer_nwc_test.ini new file mode 100644 index 0000000..7e2fce0 --- /dev/null +++ b/app/r1Obr-orchestrator/conf/speechSynthesizer_nwc_test.ini @@ -0,0 +1 @@ +config robotInterface/chatBot_nwc.xml \ No newline at end of file diff --git a/modules/r1Obr-orchestrator/inputManager.cpp b/modules/r1Obr-orchestrator/inputManager.cpp new file mode 100644 index 0000000..e499c46 --- /dev/null +++ b/modules/r1Obr-orchestrator/inputManager.cpp @@ -0,0 +1,157 @@ +/* + * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "inputManager.h" + +YARP_LOG_COMPONENT(INPUT_MANAGER, "r1_obr.orchestrator.inputManager") + + +InputManager::InputManager(double _period, yarp::os::ResourceFinder &rf) + : PeriodicThread(_period), m_rf(rf) {} + + +// ****************************************************** // +bool InputManager::threadInit() +{ + // Defaults + string voiceCommandPortName = "/r1Obr-orchestrator/voice_command:i"; + string inputCommandPortName = "/r1Obr-orchestrator/input_command:i"; + string inputManagerRPCPortName = "/r1Obr-orchestrator/inputManager:rpc"; + string device_chatBot_nwc = "chatBot_nwc_yarp"; + string local_chatBot_nwc = "/r1Obr-orchestrator/chatBot"; + string remote_chatBot_nwc = "/chatBot_nws"; + string language_chatbot = "auto"; + + // ------------------ out ------------------ // + if(!m_inputManagerRPCPort.open(inputManagerRPCPortName)) + { + yCError(INPUT_MANAGER, "Unable to open input manager RPC port"); + return false; + } + + // ------------------ in ------------------ // + if(!m_rf.check("INPUT_MANAGER")) + { + yCWarning(INPUT_MANAGER,"INPUT_MANAGER section missing in ini file. Using the default values"); + } + + Searchable& inputs_config = m_rf.findGroup("INPUT_MANAGER"); + if(inputs_config.check("voice_command_port")) {voiceCommandPortName = inputs_config.find("voice_command_port").asString();} + if(inputs_config.check("input_command_port")) {inputCommandPortName = inputs_config.find("input_command_port").asString();} + + + // Voice Command Port + if (!m_voiceCommandPort.open(voiceCommandPortName)) + { + yCError(INPUT_MANAGER, "Unable to open voice command port"); + return false; + } + m_voiceCommandPort.useCallback(*this); + + // Other Input Port + if (!m_inputCommandPort.open(inputCommandPortName)) + { + yCError(INPUT_MANAGER, "Unable to open input command port"); + return false; + } + + // iChatBot + m_chatBot_active = inputs_config.check("chatbot_active") ? (inputs_config.find("chatbot_active").asString() == "true") : false; + + if(m_chatBot_active) + { + Property chatBotProp; + chatBotProp.put("device", inputs_config.check("device", Value(device_chatBot_nwc))); + chatBotProp.put("local", inputs_config.check("local", Value(local_chatBot_nwc))); + chatBotProp.put("remote", inputs_config.check("remote", Value(remote_chatBot_nwc))); + m_PolyCB.open(chatBotProp); + if(!m_PolyCB.isValid()) + { + yCWarning(INPUT_MANAGER,"Error opening PolyDriver check parameters. Using the default values"); + } + m_PolyCB.view(m_iChatBot); + if(!m_iChatBot){ + yCError(INPUT_MANAGER,"Error opening IChatBot interface. Device not available"); + return false; + } + + if(inputs_config.check("language")) language_chatbot = inputs_config.find("language").asString(); + m_iChatBot->setLanguage(language_chatbot); + } + + + + return true; +} + + +// ****************************************************** // +void InputManager::threadRelease() +{ + if(!m_voiceCommandPort.isClosed()) + m_voiceCommandPort.close(); + + if(!m_inputCommandPort.isClosed()) + m_inputCommandPort.close(); + + if (m_inputManagerRPCPort.asPort().isOpen()) + m_inputManagerRPCPort.close(); + + if(m_PolyCB.isValid()) + m_PolyCB.close(); + + yCInfo(INPUT_MANAGER, "Input Manager thread released"); +} + + +// ****************************************************** // +void InputManager::run() +{ + Bottle* inputCommand = m_inputCommandPort.read(false); + if(inputCommand != nullptr) + { + writeToRPC(*inputCommand); + } +} + + +// ****************************************************** // +void InputManager::onRead(Bottle& b) +{ + string b_str = b.toString(); + yCInfo(INPUT_MANAGER,"Received: %s",b_str.c_str()); + + string msg; + m_iChatBot->interact(b_str, msg); + yCInfo(INPUT_MANAGER,"ChatBot replied: %s",msg.c_str()); + + Bottle msg_btl; + msg_btl.fromString(msg); + writeToRPC(msg_btl); +} + + +// ****************************************************** // +void InputManager::writeToRPC(Bottle& req) +{ + Bottle _rep_; + m_inputManagerRPCPort.write(req,_rep_); + + yCInfo(INPUT_MANAGER, "Replied from orchestrator: %s", _rep_.toString().c_str() ); +} + diff --git a/modules/r1Obr-orchestrator/input_collector.h b/modules/r1Obr-orchestrator/inputManager.h similarity index 62% rename from modules/r1Obr-orchestrator/input_collector.h rename to modules/r1Obr-orchestrator/inputManager.h index 9561641..3f6d64a 100644 --- a/modules/r1Obr-orchestrator/input_collector.h +++ b/modules/r1Obr-orchestrator/inputManager.h @@ -15,34 +15,46 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef INPUT_COLLECTOR_H -#define INPUT_COLLECTOR_H +#ifndef INPUT_MANAGER_H +#define INPUT_MANAGER_H #include +#include +#include using namespace yarp::os; +using namespace yarp::dev; using namespace std; -class InputCollector : public PeriodicThread +class InputManager : public PeriodicThread, public TypedReaderCallback { private: BufferedPort m_voiceCommandPort; BufferedPort m_inputCommandPort; - - BufferedPort m_outputPort; + RpcClient m_inputManagerRPCPort; - ResourceFinder &m_rf; + bool m_chatBot_active; + PolyDriver m_PolyCB; + IChatBot* m_iChatBot = nullptr; + + ResourceFinder &m_rf; public: - InputCollector(double _period, yarp::os::ResourceFinder &rf); - ~InputCollector() = default; + InputManager(double _period, yarp::os::ResourceFinder &rf); + ~InputManager() = default; virtual bool threadInit() override; virtual void threadRelease() override; virtual void run() override; + //Port inherited from TypedReaderCallback + using TypedReaderCallback::onRead; + virtual void onRead(Bottle& b) override; + + void writeToRPC(Bottle& req); + }; #endif \ No newline at end of file diff --git a/modules/r1Obr-orchestrator/input_collector.cpp b/modules/r1Obr-orchestrator/input_collector.cpp deleted file mode 100644 index b5fda3f..0000000 --- a/modules/r1Obr-orchestrator/input_collector.cpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2006-2020 Istituto Italiano di Tecnologia (IIT) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "input_collector.h" - -YARP_LOG_COMPONENT(INPUT_COLLECTOR, "r1_obr.orchestrator.input-collector") - -InputCollector::InputCollector(double _period, yarp::os::ResourceFinder &rf) - : PeriodicThread(_period), m_rf(rf) {} - -// ------------------------------------------------------ // -bool InputCollector::threadInit() -{ - // Defaults - string voiceCommandPortName = "/r1Obr-orchestrator/voice_command:i"; - string inputCommandPortName = "/r1Obr-orchestrator/input_command:i"; - string inputsCollectorPortName = "/r1Obr-orchestrator/inputs:o"; - - // out - if(!m_outputPort.open(inputsCollectorPortName)) - { - yCError(INPUT_COLLECTOR, "Unable to open inputs collector port"); - return false; - } - - // in - if(!m_rf.check("INPUT_PORT_GROUP")) - { - yCWarning(INPUT_COLLECTOR,"INPUT_PORT_GROUP section missing in ini file. Using the default values"); - } - else - { - Searchable& inputs = m_rf.findGroup("INPUT_PORT_GROUP"); - if(inputs.check("voice_command_port")) {voiceCommandPortName = inputs.find("voice_command_port").asString();} - if(inputs.check("input_command_port")) {inputCommandPortName = inputs.find("input_command_port").asString();} - } - - if (!m_voiceCommandPort.open(voiceCommandPortName)) - { - yCError(INPUT_COLLECTOR, "Unable to open voice command port"); - return false; - } - - if (!m_inputCommandPort.open(inputCommandPortName)) - { - yCError(INPUT_COLLECTOR, "Unable to open input command port"); - return false; - } - - return true; -} - -// ------------------------------------------------------ // -void InputCollector::threadRelease() -{ - if(!m_voiceCommandPort.isClosed()) - m_voiceCommandPort.close(); - - if(!m_inputCommandPort.isClosed()) - m_inputCommandPort.close(); - - if(!m_outputPort.isClosed()) - m_outputPort.close(); - - yCInfo(INPUT_COLLECTOR, "Input collector thread released"); -} - -// ------------------------------------------------------ // -void InputCollector::run() -{ - Bottle* voiceCommand = m_voiceCommandPort.read(false); - if(voiceCommand != nullptr) - { - // NOT IMPLEMENTED YET - yCError(INPUT_COLLECTOR, "Voice command not implemented yet"); - return; - } - - Bottle* inputCommand = m_inputCommandPort.read(false); - if(inputCommand != nullptr) - { - Bottle& toMain = m_outputPort.prepare(); - toMain.clear(); - toMain = *inputCommand; - m_outputPort.write(); - } -} - - diff --git a/modules/r1Obr-orchestrator/r1Obr-orchestrator.cpp b/modules/r1Obr-orchestrator/r1Obr-orchestrator.cpp index 44b9af9..2ae6221 100644 --- a/modules/r1Obr-orchestrator/r1Obr-orchestrator.cpp +++ b/modules/r1Obr-orchestrator/r1Obr-orchestrator.cpp @@ -25,6 +25,7 @@ Orchestrator::Orchestrator() : m_period(1.0) { m_rpc_server_port_name = "/r1Obr-orchestrator/rpc"; + m_input_port_name = "/r1Obr-orchestrator/input:i"; m_status_port_name = "/r1Obr-orchestrator/status:o"; } @@ -33,11 +34,11 @@ bool Orchestrator::configure(ResourceFinder &rf) if(rf.check("period")){m_period = rf.find("period").asFloat32();} - string input_port_name = "/r1Obr-orchestrator/inputs:i"; - string input_collector_port_name = "/r1Obr-orchestrator/inputs:o"; - if (!m_input_port.open(input_port_name)) + if(rf.check("input_port")) + m_input_port_name = rf.find("input_port").asString(); + if (!m_input_port.open(m_input_port_name)) { - yCError(R1OBR_ORCHESTRATOR, "Unable to open input collector port"); + yCError(R1OBR_ORCHESTRATOR, "Unable to open input manager port"); return false; } @@ -55,15 +56,16 @@ bool Orchestrator::configure(ResourceFinder &rf) return false; } - // --------- Input Collector initialization --------- // - m_input_collector = new InputCollector(0.1, rf); - if (!m_input_collector->start()){ + // --------- Input Manager initialization --------- // + m_input_manager = new InputManager(0.1, rf); + if (!m_input_manager->start()){ return false; } - bool ok = Network::connect(input_collector_port_name.c_str(), input_port_name.c_str()); + string input_manager_port_name = "/r1Obr-orchestrator/inputManager:rpc"; + bool ok = Network::connect(input_manager_port_name.c_str(), m_rpc_server_port_name.c_str()); if (!ok) { - yCError(R1OBR_ORCHESTRATOR,"Could not connect to %s\n", input_collector_port_name.c_str()); + yCError(R1OBR_ORCHESTRATOR,"Could not connect to %s\n", input_manager_port_name.c_str()); return false; } @@ -98,8 +100,8 @@ bool Orchestrator::close() m_inner_thread->stop(); delete m_inner_thread; - m_input_collector->stop(); - delete m_input_collector; + m_input_manager->stop(); + delete m_input_manager; return true; } @@ -163,12 +165,11 @@ bool Orchestrator::respond(const Bottle &request, Bottle &reply) else if (cmd=="what" || cmd=="where" || cmd=="navpos") { reply = m_inner_thread->forwardRequest(request); - yCInfo(R1OBR_ORCHESTRATOR) << cmd.c_str() << ":" << reply.toString().c_str(); } else if (cmd=="info") { m_inner_thread->info(reply); - yCInfo(R1OBR_ORCHESTRATOR) << cmd.c_str() << ":" << reply.toString().c_str(); + } else if (m_inner_thread->getStatus() == "waiting_for_answer") { diff --git a/modules/r1Obr-orchestrator/r1Obr-orchestrator.h b/modules/r1Obr-orchestrator/r1Obr-orchestrator.h index 3ab5440..95c538a 100644 --- a/modules/r1Obr-orchestrator/r1Obr-orchestrator.h +++ b/modules/r1Obr-orchestrator/r1Obr-orchestrator.h @@ -22,7 +22,7 @@ #include #include "orchestratorThread.h" -#include "input_collector.h" +#include "inputManager.h" using namespace yarp::os; using namespace std; @@ -31,16 +31,19 @@ class Orchestrator : public RFModule { private: - //Input Collector - InputCollector* m_input_collector; - BufferedPort m_input_port; + //Input Manager + InputManager* m_input_manager; //Callback thread OrchestratorThread* m_inner_thread; - + //RPC Server RpcServer m_rpc_server_port; string m_rpc_server_port_name; + + //Other Input port + BufferedPort m_input_port; + string m_input_port_name; //Status port BufferedPort m_status_port;