Sirikata
libspace/plugins/local/LocalPintoServerQuerier.hpp
Go to the documentation of this file.
00001 /*  Sirikata
00002  *  LocalPintoServerQuerier.hpp
00003  *
00004  *  Copyright (c) 2010, Ewen Cheslack-Postava
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions are
00009  *  met:
00010  *  * Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  *  * Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in
00014  *    the documentation and/or other materials provided with the
00015  *    distribution.
00016  *  * Neither the name of Sirikata nor the names of its contributors may
00017  *    be used to endorse or promote products derived from this software
00018  *    without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00021  * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00022  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00023  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
00024  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00025  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00026  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00027  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00028  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00029  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031  */
00032 
00033 #ifndef _SIRIKATA_LIBSPACE_LOCAL_PINTO_SERVER_QUERIER_HPP_
00034 #define _SIRIKATA_LIBSPACE_LOCAL_PINTO_SERVER_QUERIER_HPP_
00035 
00036 #include <sirikata/space/PintoServerQuerier.hpp>
00037 
00038 #include "Protocol_Prox.pbj.hpp"
00039 #include "Protocol_Loc.pbj.hpp"
00040 
00041 #include <sirikata/pintoloc/ProtocolLocUpdate.hpp>
00042 
00043 namespace Sirikata {
00044 
00057 class LocalPintoServerQuerier : public PintoServerQuerier {
00058 public:
00059     LocalPintoServerQuerier(SpaceContext* ctx)
00060      : mContext(ctx),
00061        mRegion(),
00062        mLargest(),
00063        mRootNodeID(UUID::random()),
00064        mSeqnoSource(1)
00065     {}
00066     virtual ~LocalPintoServerQuerier() {}
00067 
00068     // Service Interface
00069     virtual void start() {
00070         // This is a bit odd, but we actually just send results as soon as
00071         // things are ready to start.
00072 
00073         // To be compatible with all types of query processors, we have to at
00074         // least pretend there's a top-level pinto tree here. To make
00075         // compatibility simple, we'll just assume it's a single node tree and
00076         // that when this space server (the only space server) updates it's
00077         // query, we only need to notify it once of the update -- essentially we
00078         // set the cut at the root (and leaf) and we're done forever. Do it
00079         // async so it's like it's coming from the network and so we don't have
00080         // any issues with it running within the updateQuery request.
00081 
00082         // But because of the way other implementations behave, we just want to
00083         // send out the result (i.e. to this server) immediately.  Other
00084         // implementations connect to a server and have an implicit query
00085         // initialization. We don't have any connection to make, but we can just
00086         // pretend we've connected and gotten the info back, but post it async
00087         // so it's like it came from the network.
00088 
00089         mContext->mainStrand->post(
00090             std::tr1::bind(&LocalPintoServerQuerier::notifyResult, this)
00091         );
00092     }
00093     virtual void stop() {}
00094 
00095     // PintoServerQuerier Interface
00096     virtual void updateRegion(const BoundingBox3f& region) {
00097         mRegion = region;
00098         mContext->mainStrand->post(
00099             std::tr1::bind(&LocalPintoServerQuerier::notifyLocUpdate, this)
00100         );
00101     }
00102     virtual void updateLargestObject(float max_radius) {
00103         mLargest = max_radius;
00104         mContext->mainStrand->post(
00105             std::tr1::bind(&LocalPintoServerQuerier::notifyLocUpdate, this)
00106         );
00107     }
00108 
00109     virtual void updateQuery(const String& update) {
00110     }
00111 
00112 private:
00113     void notifyResult() {
00114         // Construct dummy update consisting of single node addition of leaf
00115         // node with our own ID so recursion to our own data will proceed where
00116         // an update like this is necessary for that to happen. It's actually a
00117         // bit more complicated because we don't actually support single node
00118         // trees -- we need at least one internal node and then the leaf node.
00119         Sirikata::Protocol::Prox::ProximityUpdate prox_update;
00120 
00121         Sirikata::Protocol::Prox::IIndexProperties index_props = prox_update.mutable_index_properties();
00122         index_props.set_id(1);
00123         index_props.set_index_id( boost::lexical_cast<String>(NullServerID) );
00124         index_props.set_dynamic_classification(Sirikata::Protocol::Prox::IndexProperties::Static);
00125 
00126 
00127         // Single addition of fake root
00128         {
00129             Sirikata::Protocol::Prox::IObjectAddition addition = prox_update.add_addition();
00130             // Shoe-horn server ID into UUID
00131             addition.set_object(mRootNodeID);
00132 
00133             addition.set_seqno (mSeqnoSource++);
00134 
00135             Sirikata::Protocol::ITimedMotionVector motion = addition.mutable_location();
00136             motion.set_t(mContext->simTime());
00137             motion.set_position(mRegion.center());
00138             motion.set_velocity(Vector3f(0,0,0));
00139 
00140             Sirikata::Protocol::ITimedMotionQuaternion msg_orient = addition.mutable_orientation();
00141             msg_orient.set_t(Time::null());
00142             msg_orient.set_position(Quaternion::identity());
00143             msg_orient.set_velocity(Quaternion::identity());
00144 
00145             Sirikata::Protocol::IAggregateBoundingInfo msg_bounds = addition.mutable_aggregate_bounds();
00146             msg_bounds.set_center_offset( Vector3f(0,0,0) );
00147             msg_bounds.set_center_bounds_radius( mRegion.toBoundingSphere().radius() );
00148             msg_bounds.set_max_object_size(mLargest);
00149 
00150             addition.set_type(Sirikata::Protocol::Prox::ObjectAddition::Aggregate);
00151         }
00152 
00153 
00154         // Single addition of our own node
00155         {
00156             Sirikata::Protocol::Prox::IObjectAddition addition = prox_update.add_addition();
00157             // Shoe-horn server ID into UUID
00158             addition.set_object(UUID((uint32)mContext->id()));
00159 
00160             addition.set_seqno (mSeqnoSource++);
00161 
00162             Sirikata::Protocol::ITimedMotionVector motion = addition.mutable_location();
00163             motion.set_t(mContext->simTime());
00164             motion.set_position(mRegion.center());
00165             motion.set_velocity(Vector3f(0,0,0));
00166 
00167             Sirikata::Protocol::ITimedMotionQuaternion msg_orient = addition.mutable_orientation();
00168             msg_orient.set_t(Time::null());
00169             msg_orient.set_position(Quaternion::identity());
00170             msg_orient.set_velocity(Quaternion::identity());
00171 
00172             Sirikata::Protocol::IAggregateBoundingInfo msg_bounds = addition.mutable_aggregate_bounds();
00173             msg_bounds.set_center_offset( Vector3f(0,0,0) );
00174             msg_bounds.set_center_bounds_radius( mRegion.toBoundingSphere().radius() );
00175             msg_bounds.set_max_object_size(mLargest);
00176 
00177             addition.set_type(Sirikata::Protocol::Prox::ObjectAddition::Object);
00178             addition.set_parent(mRootNodeID);
00179         }
00180 
00181         notify(&PintoServerQuerierListener::onPintoServerResult, prox_update);
00182     }
00183 
00184     void notifyLocUpdate() {
00185         // We don't really need the protocol version of the loc
00186         // update, but it's a convenient way to construct the update
00187         // we need.
00188         Sirikata::Protocol::Loc::LocationUpdate update;
00189         update.set_object(UUID((uint32)mContext->id()));
00190         update.set_seqno(mSeqnoSource++);
00191 
00192         // Bogus index ID (as used in prox update) so manual queries can route
00193         // updates to the right place
00194         update.add_index_id(1);
00195 
00196         Sirikata::Protocol::ITimedMotionVector motion = update.mutable_location();
00197         motion.set_t(mContext->simTime());
00198         motion.set_position(mRegion.center());
00199         motion.set_velocity(Vector3f(0,0,0));
00200 
00201         Sirikata::Protocol::ITimedMotionQuaternion msg_orient = update.mutable_orientation();
00202         msg_orient.set_t(Time::null());
00203         msg_orient.set_position(Quaternion::identity());
00204         msg_orient.set_velocity(Quaternion::identity());
00205 
00206         Sirikata::Protocol::IAggregateBoundingInfo msg_bounds = update.mutable_aggregate_bounds();
00207         msg_bounds.set_center_offset( Vector3f(0,0,0) );
00208         msg_bounds.set_center_bounds_radius( mRegion.toBoundingSphere().radius() );
00209         msg_bounds.set_max_object_size(mLargest);
00210 
00211         // notify wants to only pass through values and tries to copy the
00212         // LocProtocolLocUpdate by default -- we need to jump through hoops and
00213         // specify the exact template types explicitly to make this work
00214         notify<void(PintoServerQuerierListener::*)(const Sirikata::LocUpdate&), const LocProtocolLocUpdate&>(&PintoServerQuerierListener::onPintoServerLocUpdate, LocProtocolLocUpdate(update, NopTimeSynced()));
00215     }
00216 
00217 
00218     SpaceContext* mContext;
00219     BoundingBox3f3f mRegion;
00220     float32 mLargest;
00221     UUID mRootNodeID;
00222     uint64 mSeqnoSource;
00223 }; // PintoServerQuerier
00224 
00225 } // namespace Sirikata
00226 
00227 #endif //_SIRIKATA_LIBSPACE_LOCAL_PINTO_SERVER_QUERIER_HPP_