iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
test-split-messages.C
Go to the documentation of this file.
1 /*! @file
2  @author Laurent Itti
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
37 #include <nrt/Core/Model/Manager.H>
38 #include <nrt/Core/Typing/Macros.H> // for NRT_MACRO_WHERE
39 #include <nrt/Core/Geometry/Dims.H>
40 #include <nrt/External/cereal/types/string.hpp>
41 #include <nrt/External/cereal/types/map.hpp>
42 #include <nrt/External/cereal/types/memory.hpp>
43 #include <iostream>
44 #include <fstream>
45 #include <tuple>
46 
47 // BEGIN_NRT_CODE_SNIPPET splitmsg1.C
48 namespace mydata
49 {
50  NRT_DECLARE_MESSAGEFIELD(x, int, "x coordinate (pixels)");
51  NRT_DECLARE_MESSAGEFIELD(y, float, "y coordinate (feet)");
52  NRT_DECLARE_MESSAGEFIELD(s, std::string, "string info");
53  typedef typename std::map<int, std::string> mymap; // pre-processor parsing sucks, use typedefs for types that contain commas, etc
54  NRT_DECLARE_MESSAGEFIELD(m, mymap, "map stuff");
55 };
56 // END_NRT_CODE_SNIPPET
57 
58 // BEGIN_NRT_CODE_SNIPPET splitmsg2.C
59 class MyMessage : public nrt::CompositeMessage<NRT_MESSAGEFIELD(mydata::x),
60  NRT_MESSAGEFIELD(mydata::y),
61  NRT_MESSAGEFIELD(mydata::s),
62  NRT_MESSAGEFIELD(mydata::m)>
63 { };
64 // END_NRT_CODE_SNIPPET
65 
66 
67 // BEGIN_NRT_CODE_SNIPPET splitmsg4.C
68 namespace mydata2
69 {
70  NRT_DECLARE_MESSAGEFIELD(z, int, "z coordinate (pixels)");
71  NRT_DECLARE_MESSAGEFIELD(md, MyMessage, "my data");
72 }
73 
74 class MyMessage2 : public nrt::CompositeMessage<NRT_MESSAGEFIELD(mydata2::z),
75  NRT_MESSAGEFIELD(mydata2::md)>
76 { };
77 // END_NRT_CODE_SNIPPET
78 
79 
80 // ######################################################################
81 
82 // BEGIN_NRT_CODE_SNIPPET splitmsg5.C
83 namespace mymod
84 {
85  NRT_DECLARE_MESSAGEPOSTER_PORT(Output, MyMessage, void, "MyMessage Output");
86  NRT_DECLARE_MESSAGEPOSTER_PORT(Output2, MyMessage2, void, "MyMessage2 Output");
87 
88  NRT_DECLARE_MESSAGESUBSCRIBER_PORT(Input, MyMessage, void, "MyMessage Input");
89  NRT_DECLARE_MESSAGESUBSCRIBER_PORT(Input2, MyMessage2, void, "MyMessage2 Input");
90 }
91 
92 class MyModule : public nrt::Module,
93  public nrt::MessagePoster<mymod::Output, mymod::Output2>,
94  public nrt::MessageSubscriber<mymod::Input, mymod::Input2>
95 {
96  public:
97  MyModule(std::string const & instanceid = "") : nrt::Module(instanceid)
98  {
99  // split our posters:
100  mymod::Output::createSubPosters();
101  mymod::Output2::createSubPosters();
102 
103  // can also split port via string access. Necessary for our sub-ports and their subs:
104  nrt::Blackboard::instance().splitMessagePoster(uid().str(), "Output2.md");
105 
106  // some split subscribers:
107  mymod::Input2::createSubSubscribers();
108  nrt::Blackboard::instance().splitMessageSubscriber(uid().str(), "Input2.md");
109  }
110 
111  void onMessage(mymod::Input::InPtr msg)
112  {
113  std::stringstream ss;
114  for (auto const & m : msg->m()) { ss << "m[" << m.first << "]=[" << m.second << "] "; }
115  NRT_INFO("Got a MyMessage! x=[" << msg->x() << "], y=[" << msg->y() << "], s=[" << msg->s() << "], " << ss.str());
116  }
117 
118  void onMessage(mymod::Input2::InPtr msg)
119  {
120  std::stringstream ss;
121  for (auto const & m : msg->md().m()) { ss << "m[" << m.first << "]=[" << m.second << "] "; }
122  NRT_INFO("Got a MyMessage2! x=[" << msg->md().x() << "], y=[" << msg->md().y() << "], s=[" << msg->md().s() <<
123  "], " << ss.str() << " z=[" << msg->z() << ']');
124  }
125 
126  void tryPost()
127  {
128  NRT_INFO("Posting MyMessage");
129  std::unique_ptr<MyMessage> md(new MyMessage());
130  mymod::Output::post(md);
131 
132  NRT_INFO("Posting MyMessage2");
133  std::unique_ptr<MyMessage2> md2(new MyMessage2());
134  mymod::Output2::post(md2);
135  }
136 
137 };
138 
139 // ######################################################################
140 namespace mymod2
141 {
142  NRT_DECLARE_MESSAGEPOSTER_PORT(OutputX, nrt::Message<int>, void, "int Output");
143  NRT_DECLARE_MESSAGEPOSTER_PORT(OutputY, nrt::Message<float>, void, "float Output");
144  NRT_DECLARE_MESSAGEPOSTER_PORT(OutputS, nrt::Message<std::string>, void, "string Output");
145  NRT_DECLARE_MESSAGEPOSTER_PORT(OutputZ, nrt::Message<int>, void, "int Output 2");
146  typedef typename std::map<int, std::string> mymap;
147  NRT_DECLARE_MESSAGEPOSTER_PORT(OutputM, nrt::Message<mymap>, void, "map Output 2");
148 }
149 
150 class MyModule2 : public nrt::Module,
151  public nrt::MessagePoster<mymod2::OutputX, mymod2::OutputY, mymod2::OutputS, mymod2::OutputZ,
152  mymod2::OutputM>
153 {
154  public:
155  MyModule2(std::string const & instanceid = "") : nrt::Module(instanceid)
156  { }
157 
158  void tryPost()
159  {
160  // note: posting each part will block the poster until the whole message is assembled. Hence here to post each
161  // member one after the other from the same thread, we hold on to the poster results so we won't block on them:
162  NRT_INFO("all right, posting int to OutputX");
163  std::unique_ptr<nrt::Message<int> > mx(new nrt::Message<int>(42));
164  auto rx = mymod2::OutputX::post(mx);
165 
166  NRT_INFO("all right, posting float to OutputY");
167  std::unique_ptr<nrt::Message<float> > my(new nrt::Message<float>(43.0F));
168  auto ry = mymod2::OutputY::post(my);
169 
170  NRT_INFO("all right, posting string to OutputS");
171  std::unique_ptr<nrt::Message<std::string> > ms(new nrt::Message<std::string>("NRT Rocks!"));
172  auto rs = mymod2::OutputS::post(ms);
173 
174  NRT_INFO("all right, posting int to OutputZ");
175  std::unique_ptr<nrt::Message<int> > mz(new nrt::Message<int>(44));
176  auto rz = mymod2::OutputZ::post(mz);
177 
178  NRT_INFO("all right, posting std::map to OutputM");
179  std::unique_ptr<nrt::Message<mymod2::mymap> > mm(new nrt::Message<mymod2::mymap>());
180  mm->value()[1] = "NRT";
181  mm->value()[5] = "Rocks!";
182  auto rm = mymod2::OutputM::post(mm);
183  }
184 };
185 
186 // END_NRT_CODE_SNIPPET
187 
188 
189 
190 // ######################################################################
191 // ######################################################################
192 // ######################################################################
193 
194 //! Test main function demonstrating use of Blackboard
195 int main(int argc, char const* argv[])
196 {
197  // BEGIN_NRT_CODE_SNIPPET splitmsg3.C
198  std::unique_ptr<MyMessage> msg(new MyMessage);
199  msg->x() = 23;
200  msg->y() = 42.0F;
201  msg->s() = "Hello";
202  msg->m()[12] = "twelve";
203  // END_NRT_CODE_SNIPPET
204 
205  try
206  {
207  // BEGIN_NRT_CODE_SNIPPET splitmsg6.C
208  // Get a handle onto our Blackboard:
210 
211  // Set some default args, in particular, we are master by default:
212  bb.setParamVal("master", true);
213 
214  // Pass command-line args to Blackboard:
215  bb.setCommandLineArgs(argc, argv);
216 
217  // Create some modules:
218  auto m = bb.addModule<MyModule>("mymodule");
219  auto m2 = bb.addModule<MyModule2>("mymodule2");
220 
221  // get started:
222  bb.launch();
223 
224  // set some topics: Module m2 is going to post its individual fields:
225  bb.setMessagePosterTopic(m2->uid().str(), "OutputX", "splita");
226  bb.setMessagePosterTopic(m2->uid().str(), "OutputY", "splita");
227  bb.setMessagePosterTopic(m2->uid().str(), "OutputS", "splita");
228  bb.setMessagePosterTopic(m2->uid().str(), "OutputZ", "splitb");
229  bb.setMessagePosterTopic(m2->uid().str(), "OutputM", "splita");
230 
231  // and we set the topic filters on Input2 of Module m accordingly:
232  bb.setMessageSubscriberTopicFilter(m->uid().str(), "Input2.md.x", "splita");
233  bb.setMessageSubscriberTopicFilter(m->uid().str(), "Input2.md.y", "splita");
234  bb.setMessageSubscriberTopicFilter(m->uid().str(), "Input2.md.s", "splita");
235  bb.setMessageSubscriberTopicFilter(m->uid().str(), "Input2.md.m", "splita");
236  bb.setMessageSubscriberTopicFilter(m->uid().str(), "Input2.z", "splitb");
237 
238  bb.printInfo(std::cout);
239 
240  m->tryPost();
241 
242  // make sure all callbacks are completed to avoid clashing in printing messages
243  usleep(300000);
244 
245  // Blackboard should have this Message:
246  bb.printMessages(std::cout);
247 
248  // post a bunch of splits
249  m2->tryPost();
250 
251  // make sure all callbacks are completed to avoid clashing in printing messages
252  usleep(300000);
253 
254  // Blackboard should have this Message:
255  bb.printMessages(std::cout);
256 
257  // done
258  bb.stop();
259 
260  NRT_DEBUG("Execution successful.");
261 
262  // END_NRT_CODE_SNIPPET
263  }
264  catch (...) { nrt::warnAndRethrowException(); }
265 
266  return 0;
267 }