Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.


 

Table of Contents
maxLevel2

Introduction 

GMAT uses a publish-and-subscribe model to make propagation and optimization state data available for plotting, reporting, and output ephemeris files.

...

In order for the Publisher to know the plots and/or reports for which data is are requested, each subscriber must register with the Publisher.  This happens prior to initialization of the Data Providers.  In GMAT, this step is performed when each Subscriber is cloned into the Sandbox, prior to object initialization.  When a Subscriber registers, the Publisher adds it to a list of Subscriber pointers for later use.  In other words, the Subscriber list is built for the Publisher before object initialization occurs in the Sandbox, so that the Publisher can pass data to all Subscribers during initialization.

...

                                                  const StringArray &elementList);

The arguments here are:

provider

A pointer to the data provider, supplied using its ‘this’ pointer.

id

The ID for the data set that is pushed.  Set to -1 if the Publisher needs to assign the id.  

If not -1, it needs to be an ID that the publisher assigned previously.

ownerList

The names of the object(s) associated with the data.

elementList

A text description of each element of the provided data.

 


The is the Propagate code that sets up and makes this call:

// Prep the publisher
StringArray owners, elements;
owners.push_back("All");
elements.push_back("All.epoch");
for (UnsignedInt i = 0; i < propagators.size(); ++i)
{
   for (StringArray::iterator scName = satName[i]->begin();
        scName != satName[i]->end(); ++scName)
   {
      SpaceObject *so = NULL;
      for (UnsignedInt i = 0; i < sats.size(); ++i)
         if (sats[i]->GetName() == (*scName))
            so = (SpaceObject*)sats[i];
      if (so == NULL)
         continue;
      if (so->GetType() == Gmat::FORMATION)
         FillFormation(so, owners, elements);
      else
      {
         // Add to the owners (spacecraft names) and elements arrays
         SetNames(so->GetName(), owners, elements); 
      }
   }
}
streamID = publisher->RegisterPublishedData(this, streamID, owners, elements);

 


The string “All” used for the first element indicates that the corresponding element (the epoch data) belongs to all identified owners.  

The SetNames() method for this example (see PropagationEnabledCommand::SetNames()) pushes data onto the ‘owners’ and ‘elements’ string arrays, so that, for each spacecraft, the owner is set to the spacecraft name six times, and the element array receives the strings X, Y, Z, Vx, Vy, Vz (each with the spacecraft name prefix): 

 voidPropagationEnabledCommand::SetNames(conststd::string& name,
                                                                         StringArray& owners,
                                                                         StringArray& elements)
{
   // Add satellite labels
   for (Integer i = 0; i < 6; ++i)
      owners.push_back(name);       
   // X, Y, Z, VxVyVz
   elements.push_back(name+".X");
   elements.push_back(name+".Y");
   elements.push_back(name+".Z");
   elements.push_back(name+".Vx");
   elements.push_back(name+".Vy");
   elements.push_back(name+".Vz");
}

 


As an example, if the Propagate command has 2 spacecraft named Sat1 and Sat2, the owners array and elements array StringArrays look like this for the RegisterPublishedData() call:

owners

All

Sat1

Sat1

Sat1

Sat1

Sat1

Sat1

Sat2

Sat2

Sat2

Sat2

Sat2

Sat2

elements

All.epoch

Sat1.X

Sat1.Y

Sat1.Z

Sat1.Vx

Sat1.Vy

Sat1.Vz

Sat2.X

Sat2.Y

Sat2.Z

Sat2.Vx

Sat2.Vy

Sat2.Vz

...


This example is, of course, specific to the Propagate command.  Each data provider will need to set up the data it will be providing to the subscribers. 

...

Note: The Publish() method is overloaded in the Publisher, but this is currently the only one used in the code.  

The arguments here are:

provider

A pointer to the data provider, supplied using its ‘this’ pointer.

id

The ID assigned to this data provider during initialization

data

The data to be published; this data maps directly to the data provided during initialization (the “elements” StringArray in the earlier code).  

count

The size of the provided data array.

propDir

Indicates the direction time is moving at the call (1.0 = forward, -1.0 = backward,

2.0 = forward, ephems only, -2.0 = backwards, ephems only)

...


That call passes in the data as a double precision array.  Here’s how the data are set up and passed to the Publisher in our example Propagate command:

pubdata = newReal[dim+1];
// Publish the data
if (hasPrecisionTime)
   pubdata[0] = currEpochGT[0].GetMjd();
else
   pubdata[0] = currEpoch[0];   
// Walk the PropSetups to load the pubdata array
Integer index = 1, size;
Real *js;
for (UnsignedInt i = 0; i < propagators.size(); ++i)
{
   if (p[i]->UsesODEModel())
   {
      js = fm[i]->GetJ2KState();
      size = fm[i]->GetDimension();
   }
   else
   {
      js   = p[i]->GetJ2KState();
      size = p[i]->GetDimension();
   }
   memcpy(&pubdata[index], js, size*sizeof(Real));
   index += size;
}
publisher->Publish(this, streamID, pubdata, dim+1, direction);

...


As mentioned above, streamID here is the data provider ID assigned during initialization.  The code here fills in the dim+1 sized Real array, pubdata, with the epoch followed by the spacecraft state data retrieved from the propagation system.  That data maps map directly to the data provided during initialization (the “elements” StringArray in the earlier code).  The direction flag indicates the direction time is moving at the call.

...

            void   Publisher::UnregisterPublishedData(GmatBase *provider);

 


For the example here, the Propagate command, the data is are registered in its Initialize method, published by several of its methods – PrepareToPropagate, Execute, and TimeFinalStep, and unregistered in the destructor.  

 

 

 

 

 

 

 








* the Collocate command is currently only available to persons with access to the internal plugins.

...

A new data provider may need to be added occasionally in order to display data computed in a new class or subsystem.  As mentioned above, a data provider does not have to derive from the GmatCommand class.  However, the GmatCommand base class does provide data, e.g. object maps, and methods (e.g. FindObject) that are helpful in either registering or publishing the data.   


For example, a new Collocate* command was recently added to GMAT.  It was determined that the optimization data computed by this command should be displayed to the user, so a data provider needed to be created.  The new command itself was selected as the data provider, due to the helpful inherited GmatCommand data and methods noted above.  This command is a bit different than the Propagate command in several ways, primarily in that the to-be-published data is are computed in a separate stand-alone utility with which GMAT interacts. To get the data to the command for publishing, we needed to provide a new interface class that would call a new Collocate::Publish method at appropriate points in the optimization process.  This Publish method would then be able to retrieve the data from the utility and send it to the Publisher.

 


Other Considerations

...


Some Subscribers may need other information to handle the published data correctly and provide the data to the user in the requested format or appearance.  For example: 

...