upload_object_model.cpp
Go to the documentation of this file.
00001 
00044 #include <iostream>
00045 #include <string>
00046 #include <boost/program_options.hpp>
00047 
00048 #include <QString>
00049 #include <QStringList>
00050 #include <QDateTime>
00051 #include <QFile>
00052 #include <QDebug>
00053 #include <QDomDocument>
00054 
00055 #include <ros/ros.h>
00056 #include <re_srvs/SetObject.h>
00057 #include <re_srvs/GetObject.h>
00058 #include <re_srvs/UpdateObjectBinaryFile.h>
00059 #include <re_object_recorder/qminizip.h>
00060 #include "owldescriptioncreator.h"
00061 #include "uploadhelpers.h"
00062 
00063 namespace po = boost::program_options;
00064 
00065 using std::cout;
00066 using std::cerr;
00067 using std::endl;
00068 using std::string;
00069 
00070 // TODO: more operations?
00071 
00072 class UploadObjectModelNode {
00073 public:
00074     UploadObjectModelNode(int argc, char *argv[]) : desc("Usage"), update(false), no_owl(false) {
00075         desc.add_options()
00076                 ("help", "show this help message")
00077                 ("key", po:: value<string>(), "RoboEarth API key (get yours from http://api.roboearth.org)")
00078                 ("name", po::value<string>(),"name of the object")
00079                 ("class", po::value<string>(), "object class of the model")
00080                 ("description", po::value<string>(), "human-readable description of the model")
00081                 ("type", po::value<string>(), "model type (default value: 'ColoredPointCloudModel'")
00082                 ("update", "signals that the given file should be updated/added to the object in the database")
00083                 ("no-owl", "signals that no owl file should be generated (might cause upload to fail)")
00084                 ("force", "upload object model regardless of model name/class inconsistencies")
00085                 ("file", po::value<string>(), "zipped model file")
00086                 ;
00087 
00088         po::positional_options_description pos_opt_descs;
00089         pos_opt_descs.add("file", 1);
00090         po::parsed_options parsed = po::command_line_parser(argc, argv).options(desc).allow_unregistered().positional(pos_opt_descs).run();
00091         po::store(parsed, vm);
00092         po::notify(vm);
00093     }
00094 
00095     bool checkArguments() {
00096         if (vm.count("help")) {
00097             printUsage();
00098             return false;
00099         }
00100 
00101         if (!vm.count("file")) {
00102             cerr << "no model file given." << endl;
00103             printUsage();
00104             return false;
00105         }
00106         file = vm["file"].as<string>();
00107         if (!vm.count("key")) {
00108             cerr << "API key not given. Please specify an RoboEarth API key with --key=<KEY>'" << endl;
00109             printUsage();
00110             return false;
00111         }
00112 
00113         if ((file.length() > 4) && (file.substr(file.length() - 4) == ".zip")) {
00114             // TODO: write model name/class from command line in zip file
00115             QMiniZip mz(QString::fromStdString(file), QMiniZip::UNZIP);
00116 
00117             QByteArray ba = mz.getFile("meta.xml");
00118             if (ba.isEmpty()) {
00119                 cerr << "WARNING: could not read meta.xml file in model!" << endl;
00120             } else {
00121                 QDomDocument dom("meta");
00122                 dom.setContent(ba);
00123 
00124                 QDomElement modelEl = dom.firstChildElement("model");
00125                 QDomElement nameEl = modelEl.firstChildElement("name");
00126                 QString nameTxt = nameEl.text();
00127 
00128                 if (nameTxt.count(".") == 1) {
00129                     clss = nameTxt.split('.')[0].toStdString();
00130                     name = nameTxt.split('.')[1].toStdString();
00131                 } else {
00132                     cerr << "WARNING: could not parse name in model: '" << nameTxt.toStdString() << "'" << endl;
00133                 }
00134             }
00135         }
00136         if (name.empty()) {
00137             if (!vm.count("name")) {
00138                 cerr << "ERROR: model name neither in meta.xml nor on command line found" << endl;
00139                 return false;
00140             }
00141             name = vm["name"].as<string>();
00142         }
00143         if (clss.empty()) {
00144             if (!vm.count("class")) {
00145                 cerr << "ERROR: model class neither in meta.xml nor on command line found" << endl;
00146                 return false;
00147             }
00148             clss = vm["class"].as<string>();
00149         }
00150         if (vm.count("name") && (vm["name"].as<string>() != name)) {
00151             cerr << "WARNING: model name from command line does not match with model name from model's meta.xml: " << endl
00152                  << "\tname from command line: " << vm["name"].as<string>() << endl
00153                  << "\tname from meta.xml....: " << name << endl;
00154             if (!vm.count("force")) {
00155                 return false;
00156             } else {
00157                 cerr << "using model name from command line" << endl;
00158                 name = vm["name"].as<string>();
00159             }
00160         }
00161         if (vm.count("class") && (vm["class"].as<string>() != clss)){
00162             cerr << "WARNING: model class from command line does not match with model class from model's meta.xml: " << endl
00163                  << "\tclass from command line: " << vm["class"].as<string>() << endl
00164                  << "\tclass from meta.xml....: " << clss << endl;
00165             if (!vm.count("force")) {
00166                 return false;
00167             } else {
00168                 cerr << "using model class from command line" << endl;
00169                 clss = vm["class"].as<string>();
00170             }
00171         }
00172 
00173         key = vm["key"].as<string>();
00174         type = !vm.count("type") ? "ColoredPointCloudModel" : vm["type"].as<string>();
00175         description = !vm.count("description") ? "" : vm["description"].as<string>();
00176 
00177         update = vm.count("update");
00178         no_owl = vm.count("no-owl");
00179 
00180         return true;
00181     }
00182 
00183     bool upload() {
00184         // read file into FileMsg
00185         std::vector<re_msgs::File> fileMsgs;
00186         QString filename = QString::fromStdString(file);
00187         QString actualFilename = filename.split('/', QString::SkipEmptyParts).last();
00188         QFile f(filename);
00189 
00190         if (!f.open(QIODevice::ReadOnly)) {
00191             cerr << "Could not read file " << filename.toStdString() << endl;
00192             return false;
00193         }
00194 
00195         QByteArray data = f.readAll();
00196         re_msgs::File fileMsg;
00197         fileMsg.name = actualFilename.toStdString();
00198         fileMsg.data.resize(data.size());
00199         std::copy(data.data(), data.data()+data.size(), fileMsg.data.begin());
00200         fileMsgs.push_back(fileMsg);
00201 
00202         // upload
00203         UploadBase *uploadGeneric = NULL;
00204         if (update) {
00205             UpdateBinary *uploadSpecific = new UpdateBinary();
00206             uploadSpecific->fillRequest(key, clss + "." + name, fileMsg);
00207 
00208             uploadGeneric = uploadSpecific;
00209         } else {
00210             UploadSetNewObject *uploadSpecific = new UploadSetNewObject();
00211             OWLDescriptionCreator owldc(QString::fromStdString(type), QString::fromStdString(clss), QDateTime::currentDateTime());
00212             uploadSpecific->fillRequest(key, name, clss,
00213                                 no_owl ? "" : owldc.getOwlDescription().toStdString(),
00214                                 description, fileMsgs);
00215 
00216             uploadGeneric = uploadSpecific;
00217         }
00218         if (!uploadGeneric->waitForService())
00219             return false;
00220         if (!uploadGeneric->check())
00221             return false;
00222 
00223         return uploadGeneric->upload();
00224     }
00225 
00226 private:
00227     void printUsage() const {
00228         cout << desc << "\n";
00229         cout << "For example: " << endl
00230              << " upload a new model:\tupload_object_model --key <API-KEY> kinectmodel.zip" << endl
00231              << " update a binary file:\tupload_object_model --key <API-KEY> --update kinectmodel.zip " << endl << endl
00232              << "Please note that re_comm must be running for this program to work." << endl;
00233     }
00234 
00235     ros::NodeHandle nh;
00236     po::options_description desc;
00237     po::variables_map vm;
00238     string key, name, clss, type, description, file;
00239     bool update, no_owl;
00240 };
00241 
00242 
00243 int main(int argc, char *argv[])
00244 {
00245     ros::init(argc, argv, "upload_object_model");
00246 
00247     UploadObjectModelNode um(argc, argv);
00248     if (!um.checkArguments())
00249         return 1;
00250     if (um.upload()) {
00251         cout << "upload completed successfully" << endl;
00252     } else {
00253         cerr << "upload failed" << endl;
00254         return false;
00255     }
00256 
00257     return 0;
00258 }


re_object_recorder
Author(s): Andreas Koch
autogenerated on Sun Jan 5 2014 11:39:12