Perception Messaging

From Multiverse

Jump to: navigation, search

Contents

Overview

The Multiverse perception system controls what objects can perceive ("see") in the world. The perception system is exercised hundreds of times a second in a busy world, so efficiency is important. The world manager quad tree plays an important role in making the system fast. Also important is the communication of perception information from the world manager to the client and other plugins. The server uses custom perception messaging to make this as efficient as possible.

Perception messaging is implemented by three classes:

  • multiverse.server.messages.PerceptionMessage
    The PerceptionMessage communicates perception changes for a single object. The message contains a list of gained objects (newly perceived) and lost objects (no longer perceivable).
  • multiverse.server.messages.PerceptionFilter
    The PerceptionFilter is used by the subscriber to get perception messages for some set of objects (the target set). The filter is also used to get other messages for the target objects, and for objects perceived by those targets (the subject set).
  • multiverse.server.messages.PerceptionTrigger
    The PerceptionTrigger automatically updates a PerceptionFilter subject set to keep it in-sync with the set of object perceivable by the filter's target set.

As of Multiverse 1.1, perception messaging is used by the proxy plugin and the ObjectTracker.

PerceptionMessage

The PerceptionMessage Javadoc contains a good description of the information contained in a PerceptionMessage. However, it does not describe the "object info" returned by ObjectNote.getObjectInfo(). If you subscribe to WorldManagerClient.MSG_TYPE_PERCEPTION then the object info is null. If you subscribe to WorldManagerClient.MSG_TYPE_PERCEPTION_INFO, then the object info is a WorldManagerClient.PerceptionInfo The PerceptionInfo contains a WorldManagerClient.ObjectInfo and optionally, a DisplayContext. The ObjectInfo contains basic world information such as name, object type, location, direction, and orientation.

PerceptionFilter

Creating a PerceptionFilter subscription is the first step in using perception messaging. The PerceptionFilter message types should include one of WorldManagerClient.MSG_TYPE_PERCEPTION or WorldManagerClient.MSG_TYPE_PERCEPTION_INFO. Set the filter's target set to the object you want to track. If the target set changes, add or remove the targets from the filter using addTarget() or removeTarget(). If these methods return true, then you should apply a FilterUpdate to the subscription to notify publishers of the target set change.

The subscription should be created with a PerceptionTrigger instance if you want more than just the perception messages. For example, if you want location updates for the perceived objects, then add WorldManagerClient.MSG_TYPE_UPDATEWNODE to the filter's message types. The PerceptionTrigger will cause the world manager to keep the PerceptionFilter's subject set in-sync with the union of objects perceived by the filter's target set. Note that this is only done on the world manager's copy of the PerceptionFilter. The PerceptionFilter in the subscriber's process will have an empty subject set. You could keep the subject set updated manually, but it's easier to just call PerceptionFilter.setMatchAllSubjects(true) on the subscriber. This setting is transient; it's not replicated when the subscription if forwarded.

The preceding description applies if the additional message types only originate from the world manager. The example uses MSG_TYPE_UPDATEWNODE which should only be published by the world manager. If you add message types originating from other plugins, then extra work is needed to keep their filter's subject set in-sync with the world manager's subject set. The subscriber should apply a filter update to the subscription when the subject set changes. The subscriber will need to track the subject set via PerceptionMessage gains and losses and only apply a FilterUpdate when a subject is first perceived by any target or when a subject is no longer perceived by any target.

PerceptionTrigger

The PerceptionTrigger doesn't have any configuration or require any manipulation. Simply instantiate one when creating a PerceptionFilter subscription.

PerceptionUpdateTrigger

The PerceptionUpdateTrigger gives you a means to run code just before and after a remote PerceptionFilter receives a FilterUpdate. The trigger is called once for each FilterUpdate instruction.

The set of PerceptionUpdateTriggers is global for a process.

PerceptionUpdateTriggers implement the following interface:

public interface PerceptionUpdateTrigger
{
   public void preUpdate(PerceptionFilter filter,
       FilterUpdate.Instruction instruction,
       AgentHandle sender,
       SubscriptionHandle sub);

   public void postUpdate(PerceptionFilter filter,
       FilterUpdate.Instruction instruction,
       AgentHandle sender,
       SubscriptionHandle sub);
}

preUpdate() is called once for each FilterUpdate instruction before any of the instructions have been applied. postUpdate() is called once for each FilterUpdate instruction after all of the instructions have been applied.

The sender is the agent who sent the FilterUpdate. The sub is the filter's subscription. These values can be used with the method MessageAgent.sendDirect(message,sender,sub)

Simple example

Simple perception messaging example. Monitor the location of objects perceived by some set of objects. Contains methods to dynamically change the set of perceiving objects.

   import java.util.ArrayList;
   import multiverse.msgsys.*;
   import multiverse.server.messages.*;
   import multiverse.server.plugins.WorldManagerClient;
   import multiverse.server.engine.Engine;
   
   /** Simple perception messaging example.  Monitor the location of
   objects perceived by some set of objects.  Contains methods to
   dynamically change the set of perceiving objects.
   */
   public class PerceptionExample implements MessageCallback
   {
       public PerceptionExample()
       {
           perceptionFilter = new PerceptionFilter();
           perceptionFilter.addType(WorldManagerClient.MSG_TYPE_PERCEPTION);
           perceptionFilter.addType(WorldManagerClient.MSG_TYPE_UPDATEWNODE);
           perceptionFilter.setMatchAllSubjects(true);
           PerceptionTrigger perceptionTrigger = new PerceptionTrigger();
           perceptionSubId = Engine.getAgent().createSubscription(
               perceptionFilter, this, MessageAgent.NO_FLAGS, perceptionTrigger);
       }
   
       public synchronized void addObjectMonitoring(long oid) {
           if (perceptionFilter.addTarget(oid)) {
               FilterUpdate filterUpdate = new FilterUpdate(1);
               filterUpdate.addFieldValue(PerceptionFilter.FIELD_TARGETS,
                       new Long(oid));
               Engine.getAgent().applyFilterUpdate(perceptionSubId,
                       filterUpdate);
           }
       }
   
       public synchronized void removeObjectMonitoring(long oid) {
           if (perceptionFilter.removeTarget(oid)) {
               FilterUpdate filterUpdate = new FilterUpdate(1);
               filterUpdate.removeFieldValue(PerceptionFilter.FIELD_TARGETS,
                       new Long(oid));
               Engine.getAgent().applyFilterUpdate(perceptionSubId,
                       filterUpdate);
           }
       }
   
       public void handleMessage(Message msg, int flags) {
           if (msg.getMsgType() == WorldManagerClient.MSG_TYPE_PERCEPTION) {
               handlePerception((PerceptionMessage)msg);
           }
           else if (msg.getMsgType() == WorldManagerClient.MSG_TYPE_UPDATEWNODE) {
               handleUpdateWorldNode((WorldManagerClient.UpdateWorldNodeMessage)msg);
           }
       }
     
       void handlePerception(PerceptionMessage message)
       {
       }
       
       void handleUpdateWorldNode(
           WorldManagerClient.UpdateWorldNodeMessage message)
       {
       }
       
       PerceptionFilter perceptionFilter;
       PerceptionTrigger perceptionTrigger;
       long perceptionSubId;
   }
Personal tools