1 ////////////////////////////////////////////////////////////////////////////////////
2 ///
3 /// \file tutorial_07.cpp
4 /// \brief This file is part of a set of tutorials for learning how to use
5 /// JAUS++. This program demonstrates how to create your own
6 /// custom service that is used to subscribe to data from another
7 /// component.
8 ///
9 /// <br>Author(s): Daniel Barber
10 /// <br>Created: 3 July 2010
11 /// <br>Copyright (c) 2010
12 /// <br>Applied Cognition and Training in Immersive Virtual Environments
13 /// <br>(ACTIVE) Laboratory
14 /// <br>Institute for Simulation and Training (IST)
15 /// <br>University of Central Florida (UCF)
16 /// <br>All rights reserved.
17 /// <br>Email: dbarber@ist.ucf.edu
18 /// <br>Web: http://active.ist.ucf.edu
19 ///
20 /// Redistribution and use in source and binary forms, with or without
21 /// modification, are permitted provided that the following conditions are met:
22 /// * Redistributions of source code must retain the above copyright
23 /// notice, this list of conditions and the following disclaimer.
24 /// * Redistributions in binary form must reproduce the above copyright
25 /// notice, this list of conditions and the following disclaimer in the
26 /// documentation and/or other materials provided with the distribution.
27 /// * Neither the name of the ACTIVE LAB, IST, UCF, nor the
28 /// names of its contributors may be used to endorse or promote products
29 /// derived from this software without specific prior written permission.
30 ///
31 /// THIS SOFTWARE IS PROVIDED BY THE ACTIVE LAB''AS IS'' AND ANY
32 /// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 /// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 /// DISCLAIMED. IN NO EVENT SHALL UCF BE LIABLE FOR ANY
35 /// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 /// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 /// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 /// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 /// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 /// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 ///
42 ////////////////////////////////////////////////////////////////////////////////////
43 #include <jaus/core/component.h>
44 #include <jaus/mobility/sensors/queryglobalpose.h>
45 #include <jaus/mobility/sensors/reportglobalpose.h>
46 #include <cxutils/keyboard.h>
47 #include <iostream>
48
49 // NOTE - Run another JAUS program like tutorial_06
50 // so that this program can talk to it.
51
52 ////////////////////////////////////////////////////////////////////////////////////
53 ///
54 /// \class SubscriberService
55 /// \brief This is an example service showing how to make subscriptions
56 /// to data you want.
57 ///
58 /// Since we are using events to create subscriptions, we inherit from
59 /// the Events service using the class JAUS::Events::Child,
60 /// overloading any methods it requires.
61 ///
62 ////////////////////////////////////////////////////////////////////////////////////
63 class SubscriberService : public JAUS::Events::Child
64 {
65 public:
66 SubscriberService() : JAUS::Events::Child(JAUS::Service::ID("SubscriberService"), // ID of my service.
67 JAUS::Service::ID(JAUS::Events::Name)) // ID of the service
68 // I inherit from
69 // (i.e. Events).
70 {
71 // Sets the ID of the component with the
72 // Global Pose Sensor we want to subscribe to. For
73 // simplicity, this is set to the ID of the component
74 // in tutorial 6.
75 mSensorComponent(1000, 1, 6);
76 }
77 ~SubscriberService()
78 {
79 }
80 ////////////////////////////////////////////////////////////////////////////////////
81 ///
82 /// \brief This method indicates if other services/components can discover
83 /// this service. Since it doesn't do anything but get data, it is returning
84 /// false in this tutorial.
85 ///
86 ////////////////////////////////////////////////////////////////////////////////////
87 virtual bool IsDiscoverable() const { return false; }
88 ////////////////////////////////////////////////////////////////////////////////////
89 ///
90 /// \brief This method is used to create Message structures to read data
91 /// received by the Transport service (e.g. UDP, TCP, Serial).
92 ///
93 /// This method must be overloaded by every Service, otherwise no Callbacks
94 /// or Receive method will be called to consume messages received. This
95 /// method acts like a Message Factory for the Transport Service.
96 ///
97 /// \param[in] messageCode The ID/Message Code of the message to create.
98 ///
99 ////////////////////////////////////////////////////////////////////////////////////
100 virtual JAUS::Message* CreateMessage(const JAUS::UShort messageCode) const
101 {
102 JAUS::Message* message = NULL;
103 switch(messageCode)
104 {
105 case JAUS::REPORT_GLOBAL_POSE:
106 message = new JAUS::ReportGlobalPose();
107 break;
108 case JAUS::QUERY_GLOBAL_POSE:
109 message = new JAUS::QueryGlobalPose();
110 break;
111 default:
112 message = NULL;
113 break;
114 }
115 return message;
116 }
117 ////////////////////////////////////////////////////////////////////////////////////
118 ///
119 /// \brief This method is called whenever a message is received by the
120 /// Transport service. It is up to you to add functionality to
121 /// process/consume/respond to the messages.
122 ///
123 /// The main reason(s) this method would fail is 1) CreateMessage method
124 /// has not been overloaded, 2) Your service is not added to a component
125 /// that has been initialized, 3) It is a command message and the sender
126 /// is not in control of the component.
127 ///
128 /// \param[in] message Pointer to a message to consume/respond to.
129 ///
130 ////////////////////////////////////////////////////////////////////////////////////
131 virtual void Receive(const JAUS::Message* message)
132 {
133 switch(message->GetMessageCode())
134 {
135 case JAUS::REPORT_GLOBAL_POSE:
136 // Type cast the message and use the data
137 {
138 const JAUS::ReportGlobalPose* report =
139 dynamic_cast<const JAUS::ReportGlobalPose*>(message);
140 if(report)
141 {
142 std::cout << "\nRecieved Report Global Pose Message:\n";
143 report->PrintMessageBody();
144 }
145 }
146 break;
147 case JAUS::QUERY_GLOBAL_POSE:
148 {
149 // Do nothing, this service doesn't generate
150 // global pose, only subscribes to it.
151 }
152 break;
153 default:
154 // Do nothing, service is not meant to process
155 break;
156 }
157 }
158 ////////////////////////////////////////////////////////////////////////////////////
159 ///
160 /// \brief This method tries to create subscriptions to a global pose data
161 /// on a component. This is just an example of helper methods you
162 /// may want to add to your service.
163 ///
164 ////////////////////////////////////////////////////////////////////////////////////
165 bool CreateSubscriptions()
166 {
167 // See if we have a subscription, and if not, create one.
168 if(EventsService()->HaveSubscription(JAUS::REPORT_GLOBAL_POSE,
169 mSensorComponent) == false)
170 {
171 // Setup the query for the type of report message we want to
172 // get for our subscription. In this case, we want to
173 // get ReportGlobalPose, so we use a QueryGlobalPose
174 JAUS::QueryGlobalPose query;
175 // Set the PresenceVector mask to request any available
176 // pose data. Not all Query messages have a PresenceVector.
177 // By using the GetPresenceVectorMask method of the query
178 // message, we are requesting all/any available bits of data
179 // for Pose that the component we are requesting from supports.
180 query.SetPresenceVector(query.GetPresenceVectorMask());
181 if(EventsService()->RequestEveryChangeEvent(mSensorComponent,
182 &query))
183 {
184 // Success! We should not be getting
185 // data through the Receive method or any other callbacks we
186 // have setup.
187 return true;
188 }
189 }
190
191 return false;
192 }
193 // Method called when an Event has been signaled, generates an Event message.
194 virtual bool GenerateEvent(const JAUS::Events::Subscription& info) const
195 {
196 // We are not supporting generation of events, so we can simply
197 // return false. For examples of how to create a sensor
198 // service that supports generation of events, see the Liveness
199 // service.
200 return false;
201 }
202 // Method called to determine if an Event is supported by the service.
203 virtual bool IsEventSupported(const JAUS::Events::Type type,
204 const double requestedPeriodicRate,
205 const JAUS::Message* queryMessage,
206 double& confirmedPeriodicRate,
207 std::string& errorMessage) const
208 {
209 // We are not supporting generation of events, so we can simply
210 // return false. For examples of how to create a sensor
211 // service that supports generation of events, see the Liveness
212 // service.
213 return false;
214 }
215 JAUS::Address mSensorComponent; ///< ID of the component to subscribe to.
216 };
217
218
219 int main(int argc, char* argv[])
220 {
221 JAUS::Component component;
222
223 // Add our own services to the component.
224 // By default the Component will already have
225 // the Core Service Set (e.g. Events, Discovery, AccessControl).
226
227 // Services must be added before initialization of the component.
228 SubscriberService* service = new SubscriberService();
229 component.AddService(service);
230
231 // Setup identification (types are Subsystem::Vehicle or Subsystem::OCU).
232 // string name is whatever your platform/ocu identification is (e.g. XUV, AUV, OCU).
233 component.DiscoveryService()->SetSubsystemIdentification(JAUS::Subsystem::OCU,
234 "OCU");
235
236 // Initialize component.
237 if(component.Initialize(JAUS::Address(1000, 1, 7)) == false)
238 {
239 return 0;
240 }
241
242 std::cout << "Component Initialized!\n";
243 std::cout << "Creating subscription(s)...\n";
244 while(service->CreateSubscriptions() == false)
245 {
246 if(CxUtils::GetChar() == 27)
247 {
248 return 0;
249 }
250 CxUtils::SleepMs(1);
251 }
252
253 while(CxUtils::GetChar() != 27)
254 {
255 // Do stuff...
256 CxUtils::SleepMs(1);
257 }
258
259 // Shutdown component. Services will be deleted automatically.
260 component.Shutdown();
261
262 return 0;
263 }
264
265
266 /* End of File */
267