Sirikata
|
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_