none
Resetting the configuration of the environment 2 RRS feed

  • Question

  • Hi again.

    Probably nobody watches answered threads. So, that'll be the new one.

    This is a continuation of Resetting the configuration of the environment thread. I re-post the tail of the thread.

    It is about recreation simulation environment from persisted in xml simulation engine state. There was a proposed solution, it worked, but eventually the AccessViolationException happened. This thread looks like encountering the same problem. And now I met it too. I traced this bug and distilled it to the code:

    using EngPxy = Microsoft.Robotics.Simulation.Engine.Proxy;
    using SimPxy = Microsoft.Robotics.Simulation.Proxy;
    using Microsoft.Dss.ServiceModel.DsspServiceBase;
    using Microsoft.Ccr.Core;
    using System;
    using System.Linq;
    using Microsoft.Dss.Core.Attributes;
    using System.ComponentModel;
    using Microsoft.Dss.ServiceModel.Dssp;
    using System.Collections.Generic;
    using System.Xml;
    using Microsoft.Robotics.Simulation.Engine;
    using Microsoft.Robotics.Simulation.Physics;
    using Microsoft.Robotics.PhysicalModel;
    using Microsoft.Dss.Services.Serializer;
    
    namespace Brumba.Simulation.AccessViolation
    {
    [Contract(Contract.Identifier)]
    [DisplayName("SimulationTester")]
    [Description("SimulationTester service (no description provided)")]
    class AccessViolationService : DsspServiceBase
    {
    	public static ITask Exec<T1, T2>(PortSet<T1, T2> portSet)
            {
    	    return Arbiter.Choice(portSet, (T1 p1) => { }, (T2 p2) => { Console.WriteLine("error"); });
            }
    
    	[ServiceState]
            AccessViolationState _state = new AccessViolationState();
    		
    	[ServicePort("/SimulationTester", AllowMultipleInstances = true)]
            AccessViolationOperations _mainPort = new AccessViolationOperations();
    
            [Partner("SimEngine", Contract = Microsoft.Robotics.Simulation.Engine.Proxy.Contract.Identifier, CreationPolicy = PartnerCreationPolicy.CreateAlways)]
            EngPxy.SimulationEnginePort _simEngine = new EngPxy.SimulationEnginePort();
    
            public AccessViolationService(DsspServiceCreationPort creationPort)
    			: base(creationPort)
    	{}
    		
    	protected override void Start()
    	{
    	    base.Start();
    	    SpawnIterator(Test1);
    	}
    
            private IEnumerator<ITask> Test1()
            {
                yield return Arbiter.FromIteratorHandler(SetUpSimulator);
    
                GenerateEnvironment();
    
                for (int i = 0; i < 100; ++i)
                {
                    yield return Arbiter.FromIteratorHandler(ResetBoxes);
                    yield return Arbiter.Receive<DateTime>(false, TimeoutPort(500), (DateTime val) => { });
                    Console.WriteLine("{0}", i);
                }
            }
    
            IEnumerator<ITask> SetUpSimulator()
            {
                yield return Exec(_simEngine.UpdatePhysicsTimeStep(0.01f));
    
                SimPxy.SimulationState simState = null;
                yield return Arbiter.Choice(_simEngine.Get(), s => simState = s, LogError);
    
                simState.RenderMode = SimPxy.RenderMode.None;
                yield return Exec(_simEngine.Replace(simState));
            }
    
            private IEnumerator<ITask> ResetBoxes()
            {
                SimPxy.SimulationState simState = null;
                yield return Arbiter.Choice(_simEngine.Get(), st => simState = st, LogError);
                simState.Pause = true;
                yield return Exec(_simEngine.Replace(simState));
    
                ///Remove old boxes {
                foreach (var entityNode in simState.SerializedEntities.XmlNodes.Cast<XmlElement>())
                {
                    var desRequest = new Deserialize(new XmlNodeReader(entityNode));
                    SerializerPort.Post(desRequest);
                    DeserializeResult desEntity = null;
                    yield return Arbiter.Choice(desRequest.ResultPort, v => desEntity = v, LogError);
    
                    EngPxy.VisualEntity entity = (EngPxy.VisualEntity)desEntity.Instance;
    
                    if (entity is EngPxy.SingleShapeEntity)
                    {
                        yield return Exec(_simEngine.DeleteSimulationEntity(entity));
                        break;
                    }
                }
                ///} Remove old boxes
    
                CreateJointBoxes();
    
                simState.Pause = false;
                yield return Exec(_simEngine.Replace(simState));
            }
    
            public void CreateJointBoxes()
            {
                var box1 = new SingleShapeEntity(new BoxShape(_boxProps), new Vector3())
                            {
                                State = { Name = "box1", Pose = { Position = new Vector3(0, 2f, 0), Orientation = new Quaternion(0, 0, 1f, 0.25f) } }
                            };
    
                box1.InsertEntity(new SingleShapeEntity(new BoxShape(_boxProps), new Vector3())
                            {
                                State = { Name = "box2", Pose = { Position = new Vector3(0.3f, 0, 0) } }
                            });
                SimulationEngine.GlobalInstancePort.Insert(box1);
            }
    
            private void GenerateEnvironment()
            {
                var ground = new HeightFieldEntity("Ground", "WoodFloor.dds", new MaterialProperties("ground", 0f, 0.5f, 0.5f));
                SimulationEngine.GlobalInstancePort.Insert(ground);
    
                SkyDomeEntity sky = new SkyDomeEntity("skydome.dds", "sky_diff.dds");
                SimulationEngine.GlobalInstancePort.Insert(sky);
    
                var sun = new LightSourceEntity(LightSourceEntityType.Directional)
                {
                    State = { Name = "Sun" },
                    Direction = new Vector3(0.5f, -.75f, 0.5f)
                };
                SimulationEngine.GlobalInstancePort.Insert(sun);
            }
    
            static readonly BoxShapeProperties _boxProps = new BoxShapeProperties("box1 props", 1, new Pose(), new Vector3(0.1f, 0.1f, 0.1f))
                                {
                                    Material = new MaterialProperties("ChassisMaterial", 0.0f, 0.5f, 0.5f),
                                    DiffuseColor = new Vector4(1, 0, 0, 0)
                                };
    	}
    }

    The AccessViolationService has Simulation Engine as a partner. It spawns Test1 method during Start. Test1 turns off rendering (that does not influence the bug, it occurs with or without rendering), decreases simulation step (that's kind of catalyst for the bug). Then generates fixed environment (the floor, the sky and the sun) and begin in the loop to execute test and reset it's movable parts. 

    The gist of the test - throwing two joint boxes on the floor from the height of 2 meters. The whole bug is about colliding items, when nothing collides all is ok. The child item is the necessary condition for the bug. In ResetBoxes I pause the simulator, delete old boxes (I assume that parent box goes first), recreate boxes, unpause the simulator - it is really Vincent's code.

    The loop consists of 100 iteration. It never goes beyond 20 (the bug likes twelfth iteration the most). Some details about the bug.

    1. Exception stack trace (every time it is the same):

       в Microsoft.Robotics.Simulation.Physics.Utilities.FindShapeFromNxShape(NxShape* nxShape)
       в Microsoft.Robotics.Simulation.Physics.ActorContactReport.onContactNotify(ActorContactReport* , NxContactPair* pair, UInt32 events)
       в Microsoft.Robotics.Simulation.Physics.PhysicsEngine.GetPreviousFrameResults(Boolean waitForResults)
       в Microsoft.Robotics.Simulation.Engine.SimulationEngine.Update(GraphicsDevice device, Double appTime, Double elapsedTime, Double elapsedRealTime)
       в Microsoft.Robotics.Simulation.Engine.SimulationEngine.Application_Idle(Object sender, EventArgs e)
       в System.Windows.Forms.Application.ThreadContext.System.Windows.Forms.UnsafeNativeMethods.IMsoComponent.FDoIdle(Int32 grfidlef)
       в System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
       в System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       в System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       в System.Windows.Forms.Application.Run(Form mainForm)
       в Microsoft.Robotics.Simulation.Engine.SimulationEngine.StartRenderLoop()
       в System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       в System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
       в System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       в System.Threading.ThreadHelper.ThreadStart()

    2. I can see in IntelliTrace panel that there is always a number of thrown and caught NullReferenceExceptions before AccessViolationException.

    It occurs on two machines (Windows 8 32, Windows 7 64), both of them have 8 cores.

    This bug is a real blocker for my work. At least, I need feedback :) Is it a bug, or am I buggy? Is there any workaround? If bug will it be fixed? When?

    Thank you once more. I apologize for being persistent.

    Thursday, December 6, 2012 9:01 AM

Answers

  •  This was crazy hard to track down.  Fortunately it happened pretty consistently for me on the very first iteration and I think I have an easy fix.

    The fix I have for you is to modify the reset so that it allows the sim to run for just a bit after removing the old boxes and before adding the new ones.  Basically just rearrange the end of the "RestBoxes()" method to look like this...


               
    ///} Remove old boxes

                simState.Pause = false;
               
    yield return Exec(_simEngine.Replace(simState));

                CreateJointBoxes();
            }

     It consistently runs to completion for me now.

    Tuesday, December 11, 2012 4:09 AM
    Moderator

All replies

  • I cant compile and run this without definitions for "AccessViolationState" and "AccessViolationOperatons".  Can you provide these?  Also please provide the manifest you are using. 
    You can put the files on this dropbox if that is helpful...

    https://www.dropbox.com/sh/wtc61jwqout7s32/5-FP5J2C_r

    -Gershon

    Monday, December 10, 2012 6:03 PM
    Moderator
  • They are all default and empty as after dssnewservice.

    using Microsoft.Dss.Core.Attributes;
    using Microsoft.Ccr.Core;
    using Microsoft.Dss.ServiceModel.Dssp;
    using W3C.Soap;
    
    namespace Brumba.Simulation.AccessViolation
    {
    	public sealed class Contract
    	{
    		[DataMember]
    		public const string Identifier = "http://schemas.tempuri.org/2012/11/accessviolation.html";
    	}
    	
    	[DataContract]
        public class AccessViolationState
    	{
    	}
    	
    	[ServicePort]
        public class AccessViolationOperations : PortSet<DsspDefaultLookup, DsspDefaultDrop, Get>
    	{
    	}
    
        public class Get : Get<GetRequestType, PortSet<AccessViolationState, Fault>>
    	{
    		public Get()
    		{
    		}
    		
    		public Get(GetRequestType body)
    			: base(body)
    		{
    		}
    
            public Get(GetRequestType body, PortSet<AccessViolationState, Fault> responsePort)
    			: base(body, responsePort)
    		{
    		}
    	}
    }
    <?xml version="1.0" ?>
    <Manifest 
        xmlns="http://schemas.microsoft.com/xw/2004/10/manifest.html"
        xmlns:dssp="http://schemas.microsoft.com/xw/2004/10/dssp.html"
        >
        <CreateServiceList>
            <ServiceRecordType>
                <dssp:Contract>http://schemas.tempuri.org/2012/11/accessviolation.html</dssp:Contract>
            </ServiceRecordType>
        </CreateServiceList>
    </Manifest>
    Monday, December 10, 2012 8:07 PM
  •  This was crazy hard to track down.  Fortunately it happened pretty consistently for me on the very first iteration and I think I have an easy fix.

    The fix I have for you is to modify the reset so that it allows the sim to run for just a bit after removing the old boxes and before adding the new ones.  Basically just rearrange the end of the "RestBoxes()" method to look like this...


               
    ///} Remove old boxes

                simState.Pause = false;
               
    yield return Exec(_simEngine.Replace(simState));

                CreateJointBoxes();
            }

     It consistently runs to completion for me now.

    Tuesday, December 11, 2012 4:09 AM
    Moderator
  • Awesome! Well done, Gershon. I can imagine how it was not easy!
    It works with test. It works with my real code.
    And my personal gratitude to you. Because I began to think of moving to some other simulator with wasting all the effort and now I don't need to.
    Tuesday, December 11, 2012 8:12 AM