1. 程式人生 > >ros+科大迅飛語音包+圖靈機器人(三)通過圖靈進行語義理解

ros+科大迅飛語音包+圖靈機器人(三)通過圖靈進行語義理解

  • 在vioce_system 包中的src資料夾下建立一個tuling_nlu.cpp檔案
  • 以下是tuling_nlu.cpp的內容(注意,需要把程式碼中的key改為自己建立機器人的key,把 curl_easy_setopt(pCurl, CURLOPT_URL, "http://openapi.tuling123.com/openapi/api"); 
    中的網址改為自己機器人的介面地址,這個地址可以在機器人的api文件中找到)
  • #include<ros/ros.h>
    #include<std_msgs/String.h>
    #include<iostream>
    #include<sstream>
    #include<jsoncpp/json/json.h>
    #include<curl/curl.h>
    #include<string>
    #include<exception>
     
    using namespace std;
     
    int flag = 0;
    string result;
     
     int writer(char *data, size_t size, size_t nmemb, string *writerData)
    {
        unsigned long sizes = size * nmemb;
        if (writerData == NULL)
            return -1;
     
        writerData->append(data, sizes);
     
        return sizes;
    }
    
    int parseJsonResonse(string input)
    {
       Json::Value root;
       Json::Reader reader;
       bool parsingSuccessful = reader.parse(input, root);
       if(!parsingSuccessful)
       {
           std::cout<<"!!! Failed to parse the response data"<< std::endl;
            return -1;
       }
       const Json::Value code = root["code"];
       const Json::Value text = root["text"];
       result = text.asString();
       flag = 1;
     
       std::cout<< "response code:" << code << std::endl;
       std::cout<< "response text:" << result << std::endl;
     
       return 0;
    }
    
    int HttpPostRequest(string input)
    {
        string buffer;
     
        std::string strJson = "{";
        strJson += "\"key\" : \"093f05b003c643bbae919b353c3a12ff\","; //雙引號前加/防轉儀
        strJson += "\"info\" : ";
        strJson += "\"";
        strJson += input;
        strJson += "\"";
        strJson += "}";
     
        std::cout<<"post json string: " << strJson << std::endl;
     
         try
        {
            CURL *pCurl = NULL;
            CURLcode res;
            // In windows, this will init the winsock stuff
            curl_global_init(CURL_GLOBAL_ALL);
     
            // get a curl handle
            pCurl = curl_easy_init();
            if (NULL != pCurl)
            {
                // 設定超時時間為10秒
                curl_easy_setopt(pCurl, CURLOPT_TIMEOUT, 10);
     
                // First set the URL that is about to receive our POST.
                // This URL can just as well be a
                // https:// URL if that is what should receive the data.
                curl_easy_setopt(pCurl, CURLOPT_URL, "http://openapi.tuling123.com/openapi/api");
                //curl_easy_setopt(pCurl, CURLOPT_URL, "http://192.168.0.2/posttest.cgi");
     
                // 設定http傳送的內容型別為JSON
                curl_slist *plist = curl_slist_append(NULL,"Content-Type:application/json;charset=UTF-8");
                curl_easy_setopt(pCurl, CURLOPT_HTTPHEADER, plist);
     
                // 設定要POST的JSON資料
                curl_easy_setopt(pCurl, CURLOPT_POSTFIELDS, strJson.c_str());
     
                curl_easy_setopt(pCurl, CURLOPT_WRITEFUNCTION, writer);
     
                curl_easy_setopt(pCurl, CURLOPT_WRITEDATA, &buffer);
     
                // Perform the request, res will get the return code
                res = curl_easy_perform(pCurl);
                // Check for errors
                if (res != CURLE_OK)
                {
                    printf("curl_easy_perform() failed:%s\n", curl_easy_strerror(res));
                }
                // always cleanup
                curl_easy_cleanup(pCurl);
            }
            curl_global_cleanup();
        }
        catch (std::exception &ex)
        {
            printf("curl exception %s.\n", ex.what());
        }
        if(buffer.empty())
        {
          std::cout<< "!!! ERROR The Tuling sever response NULL" << std::endl;
        }
        else
        {
            parseJsonResonse(buffer);
        }
     
        return 0;
     
    }
    void arvCallBack(const std_msgs::String::ConstPtr &msg)
    {
        std::cout<<"your quesion is: " << msg->data << std::endl;
        HttpPostRequest(msg->data);
    }
     
    int main(int argc, char **argv)
    {
        ros::init(argc, argv,"tuling_nlu_node");
        ros::NodeHandle nd;
     
        ros::Subscriber sub = nd.subscribe("voice/tuling_nlu_topic", 10, arvCallBack);
        ros::Publisher pub = nd.advertise<std_msgs::String>("/voice/xf_tts_topic", 10);
        ros::Rate loop_rate(10);
     
        while(ros::ok())
        {
            if(flag)
            {
                std_msgs::String msg;
                msg.data = result;
                pub.publish(msg);
                flag = 0;
            }
            ros::spinOnce();
            loop_rate.sleep();
        }
     
     
    }
  • 在CMakeList檔案中加入
  • add_executable(tuling_nlu_node src/tuling_nlu.cpp)
    target_link_libraries(tuling_nlu_node   ${catkin_LIBRARIES} -lcurl -ljsoncpp)
  • 修改好的CMakeList如下
  • cmake_minimum_required(VERSION 2.8.3)  
    project(voice_system)  
      
      
    find_package(catkin REQUIRED COMPONENTS  
      roscpp  
      rospy  
      std_msgs  
    )  
      
      
    include_directories(  
       include  
      ${catkin_INCLUDE_DIRS}  
        
    )  
      
      
    add_executable(xf_tts_node src/xf_tts.cpp)  
    target_link_libraries(xf_tts_node ${catkin_LIBRARIES}   -lmsc -lrt -ldl -lpthread)
    add_executable(tuling_nlu_node src/tuling_nlu.cpp)
    target_link_libraries(tuling_nlu_node   ${catkin_LIBRARIES} -lcurl -ljsoncpp)
  • 在catkin_ws編譯一下
  • $ cd catkin_ws
  • $ catkin_make
  • 現在就可以和機器人對話了
  • 首先roscore一下,在catkin_ws下執行xf_tts_node節點和tuling_nlu_node節點
  • $ rosrun voice_system xf_tts_node
  • $ rosrun voice_system tuling_nlu_node
  • $ rostopic pub -1 /voice/tuling_nlu_topic std_msgs/String "明天東莞天氣"
  • 在此,你便能聽到圖靈機器人的回覆了

該文章主要是對自己學習的一些總結,方便以後學習,也對學習該方面的人提供一些幫助,如有問題請指出。

同時該文章也借鑑了ros小課堂的一些內容。