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