One of the points of the competition is that the soccer player needs to be able to determine his position based entirely on vision analysis. It is not allowable for the player to query for his position while the match is running.
However, if you need to get the position for debugging purposes, you can use the following code to subscribe to the simulation engine and get a reference to the entity which represents your player. The position can then be obtained from _entity.Position.
-Kyle
> It is very easy to write code to find the position of
> your players or the soccer ball and also to move them.The state of
> each entity in the simulation environment is held in a class which derives from
> VisualEntity.You can query the simulation engine for the state of any
> VisualEntity in the environment.If you are running on the same node
> as the simulation engine, you will get back a pointer to the actual
> object.If you are running on a node on another machine, you will get
> back a pointer to a copy of the entity.
>
>
>
> The SimulatedWebCam service (source is in
> samples\simulation\sensors\simulatedwebcam) provides a good example of
> how to query the simulation engine for a particular entity and then
> receive the response:
>
>
>
> You must first add a reference to the followingtwo DLLs in your project:
>
> Bin\SimulationCommon.Proxy.Dll
>
> Bin\SimulationEngine.Proxy.Dll
>
>
>
> In the Start method of your service, add the following code to send a
> subscription request to the simulation engine:
>
>
>
> (this code assumes that you are running on the same node as the
> referee)
>
>
>
> using simengine = Microsoft.Robotics.Simulation.Engine;
>
> using simcommon = Microsoft.Robotics.Simulation.Physics;
>
> simengine.SimulationEnginePort _notificationTarget;
>
>
>
>_notificationTarget = new
> simengine.SimulationEnginePort();
>
>simengine.EntitySubscribeRequestType esrt = new
> simengine.EntitySubscribeRequestType();
>
>esrt.Name =
> "blueteam/field/2/simulatedsoccerplayer/robotmotioncontrol";
> // for example
>
>esrt.Subscriber = ServiceInfo.Service;
>
>_simEngine.Subscribe(esrt, _notificationTarget);
>
>MainPortInterleave.CombineWith(
>
>new Interleave(
>
>new TeardownReceiverGroup
>
>(
>
>),
>
>new ExclusiveReceiverGroup(
>
>
> Arbiter.Receive<simengine.InsertSimulationEntity>(true,
> _notificationTarget, InsertEntityNotificationHandler),
>
>
> Arbiter.Receive<simengine.DeleteSimulationEntity>(true,
> _notificationTarget,
> DeleteEntityNotificationHandler)
>
>),
>
>new ConcurrentReceiverGroup()
>
>)
>
>);
>
>
>
> This sends a request to the simulation engine for a pointer to the
> entity with the specified name.The MainPortInterleave.CombineWith
> statement adds two new message handlers which handle the
> InsertSimulationEntity and DeleteSimulationEntity messages.A
> possible implementation for these would
> be:
>
>
>
>VisualEntity _entity = null;
>
>void
> InsertEntityNotificationHandler(simengine.InsertSimulationEntity
> ins)
>
>{
>
>_entity = (VisualEntity)ins.Body;
>
>}
>
>
>
>void
> DeleteEntityNotificationHandler(simengine.DeleteSimulationEntity
> del)
>
>{
>
>_entity = null;
>
>}
>
>
>
> Now, at any time in your simulation, you can query this entity for its
> position and orientation:
>
>
>
> Vector3 myPosition = _entity.State.Pose.Position.
>
>
>
> The orientation of the robot is represented by a quaternion in
> _entity.State.Pose.Orientation.Or, there is also a property on
> VisualEntity that returns the orientation as a rotation angle (in
> degrees) around each axis:
>
>
>
> Xna.Vector3 rotation = _entity.Rotation;
>
>
>
>
>
Hi Kyle,
Thank you for this post, it is really usefull.
But what would you change in your code if the referee was not running on the same node?
Thanks
Adeline
If you are querying for an entity from a node other than the one where the simulation engine is running, you will get a reference to a copy of the entity. Since it is a copy of the entity, it is not updated automatically by the simulation engine, it is static.
In this case, the easiest thing to do is to post a Get message to the simulator. That will return all of the simulator's state. You can find a reference to all of the simulator entities within this state and once you find the appropriate entity, you can find its position in State.Pose.Position. The next time you need an updated position, you will have to once-again send a get request to the simulator.
Another option is to write a separate service that does run on the same node as the simulator. When it receives a get request, it sends the current position of the entity it is attached to. Then, your service would just have to send a get request to this new service to get the current position of the entity of interest.
Either approach should work.
-Kyle