iCub-main
Loading...
Searching...
No Matches
TransformModule.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2007-2010 RobotCub Consortium, European Commission FP6 Project IST-004370
3 * author: Arjan Gijsberts
4 * email: arjan.gijsberts@iit.it
5 * website: www.robotcub.org
6 * Permission is granted to copy, distribute, and/or modify this program
7 * under the terms of the GNU General Public License, version 2 or any
8 * later version published by the Free Software Foundation.
9 *
10 * A copy of the license can be found at
11 * http://www.robotcub.org/icub/license/gpl.txt
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16 * Public License for more details
17 */
18
19#include <iostream>
20#include <stdexcept>
21#include <cassert>
22
23#include <yarp/os/Network.h>
24#include <yarp/os/Vocab.h>
25
27
28namespace iCub {
29namespace learningmachine {
30
31bool TransformPredictProcessor::read(yarp::os::ConnectionReader& connection) {
32 if(!this->getTransformerPortable().hasWrapped()) {
33 return false;
34 }
35
36 yarp::sig::Vector input;
37 Prediction prediction;
38 bool ok = input.read(connection);
39 if(!ok) {
40 return false;
41 }
42
43 try {
44 yarp::sig::Vector trans_input = this->getTransformer().transform(input);
45 this->getOutputPort().write(trans_input, prediction);
46 } catch(const std::exception& e) {
47 std::cerr << "Error: " << e.what() << std::endl;
48 return false;
49 }
50
51 yarp::os::ConnectionWriter* replier = connection.getWriter();
52 if(replier != (yarp::os::ConnectionWriter*) 0) {
53 prediction.write(*replier);
54 }
55
56 return true;
57}
58
59
60void TransformTrainProcessor::onRead(yarp::os::PortablePair<yarp::sig::Vector,yarp::sig::Vector>& input) {
61 if(this->getTransformerPortable().hasWrapped()) {
62 try {
63 yarp::os::PortablePair<yarp::sig::Vector,yarp::sig::Vector>& output = this->getOutputPort().prepare();
64 output.head = this->getTransformer().transform(input.head);
65 output.body = input.body;
66 this->getOutputPort().writeStrict();
67 } catch(const std::exception& e) {
68 std::cerr << "Error: " << e.what() << std::endl;
69 }
70 }
71
72 return;
73}
74
75
76void TransformModule::printOptions(std::string error) {
77 if(error != "") {
78 std::cout << "Error: " << error << std::endl;
79 }
80 std::cout << "Available options" << std::endl;
81 std::cout << "--help Display this help message" << std::endl;
82 std::cout << "--list Print a list of available algorithms" << std::endl;
83 std::cout << "--load file Load serialized transformer from a file" << std::endl;
84 std::cout << "--transformer type Desired type of transformer" << std::endl;
85 std::cout << "--trainport port Data port for the training samples" << std::endl;
86 std::cout << "--predictport port Data port for the prediction samples" << std::endl;
87 std::cout << "--port pfx Prefix for registering the ports" << std::endl;
88 std::cout << "--commands file Load configuration commands from a file" << std::endl;
89}
90
91void TransformModule::printTransformerList() {
92 std::vector<std::string> keys = FactoryT<std::string, ITransformer>::instance().getKeys();
93 std::cout << "Available Transformers:" << std::endl;
94 for(unsigned int i = 0; i < keys.size(); i++) {
95 std::cout << " " << keys[i] << std::endl;
96 }
97}
98
99void TransformModule::registerAllPorts() {
100 //this->registerPort(this->model_out, "/" + this->portPrefix + "/model:o");
101
102 this->registerPort(this->train_in, this->portPrefix + "/train:i");
103 this->train_in.setStrict();
104
105 this->registerPort(this->train_out, this->portPrefix + "/train:o");
106 this->train_out.setStrict();
107
108 this->registerPort(this->predict_inout, this->portPrefix + "/predict:io");
109 this->predict_inout.setStrict();
110
111 this->registerPort(this->predictRelay_inout, this->portPrefix + "/predict_relay:io");
112 //this->predict_relay_inout.setStrict();
113
114 this->registerPort(this->cmd_in, this->portPrefix + "/cmd:i");
115}
116
117void TransformModule::unregisterAllPorts() {
118 this->cmd_in.close();
119 this->train_in.close();
120 this->train_out.close();
121 this->predict_inout.close();
122 this->predictRelay_inout.close();
123}
124
126 cmd_in.interrupt();
127 train_in.interrupt();
128 train_out.interrupt();
129 predict_inout.interrupt();
130 predictRelay_inout.interrupt();
131 return true;
132}
133
134bool TransformModule::configure(yarp::os::ResourceFinder& opt) {
135 // read for the general specifiers:
136 yarp::os::Value* val;
137 std::string transformerName;
138
139 // cache resource finder
140 this->setResourceFinder(&opt);
141
142 // check for help request
143 if(opt.check("help")) {
144 this->printOptions();
145 return false;
146 }
147
148 // check for algorithm listing request
149 if(opt.check("list")) {
150 this->printTransformerList();
151 return false;
152 }
153
154 // check for port specifier: portSuffix
155 if(opt.check("port", val)) {
156 this->portPrefix = val->asString().c_str();
157 }
158
159 if(opt.check("load", val)) {
160 this->getTransformerPortable().readFromFile(val->asString().c_str());
161 } else{
162 // check for transformer specifier: transformerName
163 if(opt.check("transformer", val)) {
164 transformerName = val->asString().c_str();
165 } else {
166 this->printOptions("no transformer type specified");
167 return false;
168 }
169
170 // construct transformer
171 this->getTransformerPortable().setWrapped(transformerName);
172
173 // send configuration options to the transformer
174 this->getTransformer().configure(opt);
175 }
176
177 // add processor for incoming data (training samples)
178 this->train_in.useCallback(trainProcessor);
179
180 // add replier for incoming data (prediction requests)
181 this->predict_inout.setReplier(this->predictProcessor);
182
183 // register ports
184 this->registerAllPorts();
185
186 // check for train data port
187 if(opt.check("trainport", val)) {
188 yarp::os::Network::connect(this->train_out.where().getName().c_str(),
189 val->asString().c_str());
190 } else {
191 // add message here if necessary
192 }
193
194 // check for predict data port
195 if(opt.check("predictport", val)) {
196 yarp::os::Network::connect(this->predictRelay_inout.where().getName().c_str(),
197 val->asString().c_str());
198 } else {
199 // add message here if necessary
200 }
201
202 // and finally load command file
203 if(opt.check("commands", val)) {
204 std::string full_fname = this->findFile(val->asString().c_str());
205 this->loadCommandFile(full_fname);
206 }
207
208 // attach to the incoming command port and terminal
209 this->attach(cmd_in);
210 this->attachTerminal();
211
212 return true;
213}
214
215
216bool TransformModule::respond(const yarp::os::Bottle& cmd, yarp::os::Bottle& reply) {
217 // NOTE: the module class spawns a new thread, which implies that exception
218 // handling needs to be done in this thread, so not the 'main' thread.
219 bool success = false;
220
221 try {
222 switch(cmd.get(0).asVocab32()) {
223 case yarp::os::createVocab32('h','e','l','p'): // print help information
224 reply.add(yarp::os::Value::makeVocab32("help"));
225
226 reply.addString("Transform module configuration options");
227 reply.addString(" help Displays this message");
228 reply.addString(" reset Resets the machine to its current state");
229 reply.addString(" info Outputs information about the transformer");
230 reply.addString(" load fname Loads a transformer from a file");
231 reply.addString(" save fname Saves the current transformer to a file");
232 reply.addString(" set key val Sets a configuration option for the transformer");
233 reply.addString(" cmd fname Loads commands from a file");
234 reply.addString(this->getTransformer().getConfigHelp().c_str());
235 success = true;
236 break;
237
238 case yarp::os::createVocab32('c','l','e','a'): // clear the machine
239 case yarp::os::createVocab32('c','l','r'):
240 case yarp::os::createVocab32('r','e','s','e'):
241 case yarp::os::createVocab32('r','s','t'):
242 this->getTransformer().reset();
243 reply.addString("Transformer reset.");
244 success = true;
245 break;
246
247 case yarp::os::createVocab32('i','n','f','o'): // information
248 case yarp::os::createVocab32('s','t','a','t'): // print statistics
249 { // prevent identifier initialization to cross borders of case
250 reply.add(yarp::os::Value::makeVocab32("help"));
251 reply.addString("Transformer Information: ");
252 reply.addString(this->getTransformer().getInfo().c_str());
253 success = true;
254 break;
255 }
256
257 case yarp::os::createVocab32('s','e','t'): // set a configuration option for the machine
258 { // prevent identifier initialization to cross borders of case
259 yarp::os::Bottle property;
260 /*
261 * This is a simple hack to enable multiple parameters The need
262 * for this hack lies in the fact that a group can only be found
263 * using findGroup if it is a nested list in a Bottle. If the
264 * Bottle itself is the list, then the group will _not_ be found.
265 */
266 property.addList() = cmd.tail();
267 std::string replymsg = "Setting configuration option ";
268 bool ok = this->getTransformer().configure(property);
269 replymsg += ok ? "succeeded" :
270 "failed; please check key and value type.";
271 reply.addString(replymsg.c_str());
272 success = true;
273 break;
274 }
275
276 case yarp::os::createVocab32('l','o','a','d'): // load
277 { // prevent identifier initialization to cross borders of case
278 reply.add(yarp::os::Value::makeVocab32("help"));
279 std::string replymsg = std::string("Loading transformer from '") +
280 cmd.get(1).asString().c_str() + "'... " ;
281 if(!cmd.get(1).isString()) {
282 replymsg += "failed";
283 } else {
284 this->getTransformerPortable().readFromFile(cmd.get(1).asString().c_str());
285 replymsg += "succeeded";
286 }
287 reply.addString(replymsg.c_str());
288 success = true;
289 break;
290 }
291
292 case yarp::os::createVocab32('s','a','v','e'): // save
293 { // prevent identifier initialization to cross borders of case
294 reply.add(yarp::os::Value::makeVocab32("help"));
295 std::string replymsg = std::string("Saving transformer to '") +
296 cmd.get(1).asString().c_str() + "'... " ;
297 if(!cmd.get(1).isString()) {
298 replymsg += "failed";
299 } else {
300 this->getTransformerPortable().writeToFile(cmd.get(1).asString().c_str());
301 replymsg += "succeeded";
302 }
303 reply.addString(replymsg.c_str());
304 success = true;
305 break;
306 }
307
308 case yarp::os::createVocab32('c','m','d'): // cmd
309 case yarp::os::createVocab32('c','o','m','m'): // command
310 { // prevent identifier initialization to cross borders of case
311 reply.add(yarp::os::Value::makeVocab32("help"));
312 std::string replymsg;
313 if(!cmd.get(1).isString()) {
314 replymsg = "Please supply a valid filename.";
315 } else {
316 std::string full_fname = this->findFile(cmd.get(1).asString().c_str());
317 replymsg = std::string("Loading commands from '") +
318 full_fname + "'... " ;
319 this->loadCommandFile(full_fname, &reply);
320 replymsg += "succeeded";
321 }
322 reply.addString(replymsg.c_str());
323 success = true;
324 break;
325 }
326
327 default:
328 break;
329
330 }
331 } catch(const std::exception& e) {
332 std::string msg = std::string("Error: ") + e.what();
333 reply.addString(msg.c_str());
334 success = true;
335 }
336
337 return success;
338}
339
340} // learningmachine
341} // iCub
static FactoryT< K, T > & instance()
An instance retrieval method that follows the Singleton pattern.
Definition FactoryT.h:86
std::string portPrefix
A prefix path for the ports that will be registered.
virtual void setResourceFinder(yarp::os::ResourceFinder *rf)
Mutator for the locally stored ResourceFinder.
std::string findFile(std::string fname)
Finds the full path to a specified filename using the ResourceFinder.
void registerPort(yarp::os::Contactable &port, std::string name)
Register a port with a given name.
yarp::os::Port cmd_in
An input port for commands.
virtual void loadCommandFile(std::string fname, yarp::os::Bottle *out=(yarp::os::Bottle *) 0)
Reads bottles from a file and sends these one by one to the respond method.
virtual TransformerPortable & getTransformerPortable()
Retrieve the transformer portable wrapper.
virtual ITransformer & getTransformer()
Retrieve the wrapped transformer.
virtual bool configure(yarp::os::Searchable &config)
virtual yarp::sig::Vector transform(const yarp::sig::Vector &input)
Transforms an input vector.
virtual void reset()
Forget everything and start over.
void setWrapped(T *w, bool wipe=true)
The mutator for the wrapped object.
Definition PortableT.h:228
bool writeToFile(std::string filename)
Writes a wrapped object to a file.
Definition PortableT.h:161
bool readFromFile(std::string filename)
Reads a wrapped object from a file.
Definition PortableT.h:182
A class that represents a prediction result.
Definition Prediction.h:44
bool write(yarp::os::ConnectionWriter &connection) const
Definition Prediction.h:166
bool read(yarp::os::ConnectionReader &connection)
Definition Prediction.h:186
virtual bool respond(const yarp::os::Bottle &cmd, yarp::os::Bottle &reply)
virtual bool configure(yarp::os::ResourceFinder &opt)
virtual ITransformer & getTransformer()
Retrieve the transformer that is used in this TransformModule.
virtual TransformerPortable & getTransformerPortable()
Retrieve the transformer portable.
virtual bool read(yarp::os::ConnectionReader &connection)
virtual yarp::os::Port & getOutputPort()
Accessor for the prediction output port.
virtual yarp::os::BufferedPort< yarp::os::PortablePair< yarp::sig::Vector, yarp::sig::Vector > > & getOutputPort()
Retrieve the training output port.
virtual void onRead(yarp::os::PortablePair< yarp::sig::Vector, yarp::sig::Vector > &input)
cmd
Definition dataTypes.h:30
bool error
This file contains the definition of unique IDs for the body parts and the skin parts of the robot.