generator.cpp
Go to the documentation of this file.
00001 /*****************************************************************************
00002  * PROJECT: iwaki
00003  *
00004  * FILE: generator.cpp
00005  *
00006  * ABSTRACT: This is an example executor of Iwaki actions: a sound file player.
00007  * It relies on gstreamer library and executes a console command,
00008  * so, most probably only runs on Unix.
00009  *
00010  * Iwakishi: a ROS wrapper around Iwaki interaction manager library.
00011  * Copyright (C) 2012-2013 Maxim Makatchev.
00012  * 
00013  * This program is free software: you can redistribute it and/or modify
00014  * it under the terms of the GNU General Public License as published by
00015  * the Free Software Foundation, either version 3 of the License, or
00016  * (at your option) any later version.
00017  *
00018  * This program is distributed in the hope that it will be useful,
00019  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  * GNU General Public License for more details.
00022  *
00023  * You should have received a copy of the GNU General Public License
00024  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00025  * 
00026  * 
00027  ****************************************************************/
00028 
00029 
00030 #include <iostream>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <getopt.h>
00034 #include <string>
00035 #include <fstream>
00036 
00037 #include "ros/ros.h"
00038 #include "iwaki/ActionMsg.h"
00039 #include "iwaki/ActionStatusMsg.h"
00040 
00041 using namespace std;
00042 
00043 using std::string;
00044 using std::iostream;
00045 
00050 string sounds_path;
00051 ros::Publisher actionStatus_pub;
00052 
00053 bool executeAction(const iwaki::ActionMsg &anActionMsg) {
00054     string full_filename;
00055     
00056         /* in the future generate may handle other actions, perhaps */
00057     if (anActionMsg.name == "generate_utterance") {
00058         string utterance_file;
00059         string utterance_token;
00060         string utterance_string;
00061         
00062             /* get the args*/
00063         for (std::vector<iwaki::ArgSlot>::const_iterator arg_it = anActionMsg.args.begin();
00064              arg_it != anActionMsg.args.end(); arg_it++) {
00065              cout  << "  arg name: " << arg_it->name << endl;
00066              cout  << "  arg value: " << arg_it->value << endl;
00067              cout  << "  arg type: " << arg_it->type << endl;
00068             if (arg_it->name == "utterance_file") {
00069                 utterance_file = arg_it->value;
00070             } else if (arg_it->name == "utterance_token") {
00071                 utterance_token = arg_it->value;
00072             } else if (arg_it->name == "utterance_string") {
00073                 utterance_string = arg_it->value;
00074             }
00075         }
00076 
00077         if (utterance_file != "_NO_VALUE_") {
00078                 /* action included utterance file, ignore the rest */
00079 
00080 
00081             full_filename = sounds_path + "/" + utterance_file;
00082 
00083             ifstream sound_file(full_filename.c_str());
00084             
00085             if ( !sound_file)
00086             {
00087                 cout << "Can't find sound file:" << full_filename << endl;
00088                 return false;
00089             }
00090                 /* using & to run gstreamer as a new processes to allow for
00091                  * asychnronous execution. -q quiets it although this
00092                  * doesn't prevent it with messing text_ui without &. */
00093             string exec_str = "gst-launch-0.10 -q playbin uri=file://" +
00094                 full_filename + " &";
00095             const char *exec_cstr = (const char*)exec_str.c_str();
00096             int res = system(exec_cstr);
00097 
00098            
00099                 
00100             cout  << "System() returned value: " << res
00101                   << " when asked to execute command: " << exec_str << endl;
00102         }
00103     } else {
00104         cout << "Don't know what to do with the action named: " << anActionMsg.name
00105              << endl;
00106     }
00107     return true;
00108 }
00109 
00110 
00111 /*
00112  * actionCallback implements the callback on the subscribed topic,
00113  * the actions Iwakishi interaction manager.
00114  * */
00115 
00116 void actionCallback(const iwaki::ActionMsg::ConstPtr& anActionMsg_p) {
00117     cout << "Generator received action: " << endl;
00118     cout << "       action name: " << anActionMsg_p->name << endl;
00119     cout << "         action id: " << anActionMsg_p->id << endl;
00120     cout << "      action actor: " << anActionMsg_p->actor << endl;
00121 
00122     if (anActionMsg_p->actor != "generator") {
00123         return;
00124     }
00125 
00126 
00127     if (!executeAction(*anActionMsg_p)) {
00128         cout << "There was an error executing action named: "
00129              << anActionMsg_p->name << ", action id: "
00130              << anActionMsg_p->id << endl;
00131     }
00132     
00133     iwaki::ActionStatusMsg aStatusMsg;
00134             /* send an action completed status when done */
00135     aStatusMsg.status = "completed";
00136     aStatusMsg.executor = "generator";
00137     aStatusMsg.action_id = anActionMsg_p->id;
00138 
00139     actionStatus_pub.publish(aStatusMsg);
00140     cout << "Generator sent status completed for action id: "
00141          << anActionMsg_p->id << endl;
00142     return;
00143 
00144 }
00145 
00146 
00147 
00148 
00149 int main (int argc, char **argv)
00150 {
00151 
00152         /* before reading the app's arglist */
00153     ros::init(argc, argv, "generator");
00154     
00155     opterr = 0;
00156     char* cvalue;
00157     int c;
00158 
00159     while (1)
00160     {
00161         static struct option long_options[] =
00162             {
00163                     /* These options set a flag. */
00164                     //{"verbose", no_argument,       &verbose_flag, 1},
00165                     //{"brief",   no_argument,       &verbose_flag, 0},
00166                     /* These options don't set a flag.
00167                        We distinguish them by their indices. */
00168                 {"help",    no_argument,       0, 'h'},
00169                 {"sounds",   required_argument, 0, 's'},
00170                 {0, 0, 0, 0}
00171             };
00172             /* getopt_long stores the option index here. */
00173         int option_index = 0;
00174         
00175         c = getopt_long (argc, argv, "hs:",
00176                          long_options, &option_index);
00177         
00178             /* Detect the end of the options. */
00179         if (c == -1)
00180             break;
00181      
00182         switch (c) {
00183              case 0:
00184                /* If this option set a flag, do nothing else now. */
00185                if (long_options[option_index].flag != 0)
00186                  break;
00187                printf ("option %s", long_options[option_index].name);
00188                if (optarg)
00189                  printf (" with arg %s", optarg);
00190                printf ("\n");
00191                break;
00192 
00193             case 'h':
00194                 cout << "\
00195 Usage: imcore [OPTION]... \n\
00196 ";
00197                 cout << "Mandatory arguments to long options are mandatory for short options too.\n\
00198 ";
00199                 cout << "\
00200   -s --sounds SOUND_DIR          sound file directory \n\
00201 ";            
00202                 cout << "\
00203   -h --help                  This info." << endl;
00204                 return -1; 
00205             case 's':
00206             {
00207                 cvalue = optarg;
00208                 sounds_path = (string) ((const char*) cvalue);
00209                 break;
00210             }   
00211             default:
00212                  cout << "Unknown option. Try 'generator --help' for more information.\n";
00213                  return -1;
00214         }
00215     }
00216 
00217             /* Print any remaining command line arguments (not options). */
00218     if (optind < argc)
00219     {
00220         printf ("non-option ARGV-elements: ");
00221         while (optind < argc)
00222             printf ("%s ", argv[optind++]);
00223         putchar ('\n');
00224     }
00225 
00226     if (sounds_path.empty()) {
00227         cout << "Missing path to sounds directory. Pass it with a command line option -s."
00228              << endl;
00229     }
00230 
00231 
00232         /* ROS stuff */
00233     ros::NodeHandle n;
00234     ros::Subscriber action_sub = n.subscribe("IwakiAction", 1000, actionCallback);
00235         /* publisher object is global so that callback can see it */
00236     actionStatus_pub = n.advertise<iwaki::ActionStatusMsg>("IwakiActionStatus", 1000);
00237         /******************************
00238          *
00239          * Main loop
00240          * 
00241          ******************************/
00242     ros::Rate loop_rate(10);
00243     while (ros::ok()) {
00244 
00245         ros::spinOnce();
00246         loop_rate.sleep();
00247     }
00248     
00249 }


iwaki
Author(s): Maxim Makatchev, Reid Simmons
autogenerated on Thu Aug 27 2015 13:34:44