[Bepu2] Belt conveyor

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
Darkon76
Posts: 23
Joined: Mon Mar 27, 2017 12:33 pm

[Bepu2] Belt conveyor

Post by Darkon76 »

Hello,

I’m trying to create a conveyor belt. I added another struct to the body ConveyorSettings,.
At the IntegrateBodiesAndUpdateBoundingBoxes, it sets the velocity.Linear before the PoseIntegration.Integrate most of the time 0 because the conveyor isn’t moving, then set the conveyor velocity to the velocity.Linear to simulate the belt velocity, propagating the movement to other objects. It works but it has a problem, if the conveyor is carrying an object and the belt stop moving the payload will stop and after short amount of time the payload will sleep. If the belt is restarted the payload wouldn’t be affected because it is sleeping.

Is there a better way to implement the conveyor?

For performance it is good that the payload sleeps. Because the payload is sleeping I can’t use collision detection to wake them. What other option do I have to wake up the payload?


Kind Regards

Image

Code: Select all

  unsafe void IntegrateBodiesAndUpdateBoundingBoxes(int startIndex, int endIndex, float dt, ref BoundingBoxBatcher boundingBoxBatcher, int workerIndex)
        {
		…
            ref var baseConveyorSettings = ref bodies.ActiveSet.ConveyorSettings[0];
            for (int i = startIndex; i < endIndex; ++i)
            {
                ref var pose = ref Unsafe.Add(ref basePoses, i);
                ref var velocity = ref Unsafe.Add(ref baseVelocities, i);
                ref var conveyorSettings = ref Unsafe.Add(ref baseConveyorSettings, i);


                if (conveyorSettings.IsLinearConveyor)
                {
                    velocity.Linear = conveyorSettings.LinearVelocity;
                }

                var previousOrientation = pose.Orientation; //This is unused if conservation of angular momentum is disabled... compiler *may* remove it...

                PoseIntegration.Integrate(pose, velocity, dt, out pose);
		…
                inertia.InverseMass = localInertia.InverseMass;

                if (conveyorSettings.IsLinearConveyor)
                {
                    velocity.Linear = conveyorSettings.LinearVelocity + conveyorSettings.ConveyorVelocity;
                }
                ...

Note the conveyor is easily implemented in bepu 1 adding an offset at EntityBase-> void IPositionUpdateable.PreUpdatePosition(float dt)

Code: Select all

            if (PositionUpdateMode == PositionUpdateMode.Discrete)
            {
                var velocity = IsLinearConveyor ? linearVelocity - LinearOffset : linearVelocity;
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: [Bepu2] Belt conveyor

Post by Norbo »

Any time the conveyor restarts, you could use Simulation.Awakener.AwakenBody to force it awake. Any bodies on the conveyor will be forced awake with it.

By the way, unless the majority of bodies are conveyor belts, it would probably be simpler and faster to directly modify velocity and pose of the conveyor outside of the pose integrator. You can do this external to the timestep or attach a callback to one of the timestepper stages, like PositionFirstTimeStepper.BeforeCollisionDetection. (An ITimestepper is provided in the Simulation.Create; by default it uses a PositionFirstTimeStepper. You could supply a PositionLastTimeStepper, SubsteppingTimestepper, or your own implementation too.)
Darkon76
Posts: 23
Joined: Mon Mar 27, 2017 12:33 pm

Re: [Bepu2] Belt conveyor

Post by Darkon76 »

Thanks for the replay.

After a lot of tries it ended being a mix of awake and shake the conveyor.

So you recommend at the before collision detection set the velocity and at PositionlasttimeStepper set the correct position of the conveyor to avoid the movement.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: [Bepu2] Belt conveyor

Post by Norbo »

You could do both pose and velocity in PositionFirstTimestepper.BeforeCollisionDetection. In the PositionFirstTimestepper, velocities and poses are integrated up front, so if you set the pose there it'll stick until the next frame.

If using the PositionLastTimestepper instead of the PositionFirstTimestepper, velocities are integrated early and poses late. Presumably the conveyors are kinematic and the pose integrator callback you provided doesn't apply velocity changes to kinematics, so you could just make the velocity and pose modification before or after the simulation timestep without using any stage callbacks.
Darkon76
Posts: 23
Joined: Mon Mar 27, 2017 12:33 pm

Re: [Bepu2] Belt conveyor

Post by Darkon76 »

A custom TimeStepper worked like a charm. It moves the payload and also it doesn't have the sleep problem.

Thanks for the help.

This is my custom unoptimized code (I know that I should have a collection with only the conveyors)

Code: Select all

        public void Timestep(Simulation simulation, float dt, IThreadDispatcher threadDispatcher = null)
        {
            simulation.Sleep(threadDispatcher);
            Slept?.Invoke(dt, threadDispatcher);

            simulation.IntegrateVelocitiesBoundsAndInertias(dt, threadDispatcher);
            BeforeCollisionDetection?.Invoke(dt, threadDispatcher);

            simulation.CollisionDetection(dt, threadDispatcher);
            CollisionsDetected?.Invoke(dt, threadDispatcher);


            int count = simulation.Bodies.ActiveSet.Count;
            ref var baseConveyorSettings = ref simulation.Bodies.ActiveSet.ConveyorSettings[0];
            ref var baseVelocities = ref simulation.Bodies.ActiveSet.Velocities[0];

            for (int i = 0; i < count; i++)
            {
                ref var conveyorSettings = ref Unsafe.Add(ref baseConveyorSettings, i);
                ref var velocity = ref Unsafe.Add(ref baseVelocities, i);
                if (conveyorSettings.IsLinearConveyor)
                {
                    velocity.Linear = conveyorSettings.LinearVelocity + conveyorSettings.ConveyorVelocity;
                }
            }
            


            simulation.Solve(dt, threadDispatcher);
            ConstraintsSolved?.Invoke(dt, threadDispatcher);


            for (int i = 0; i < count; i++)
            {
                ref var conveyorSettings = ref Unsafe.Add(ref baseConveyorSettings, i);
                ref var velocity = ref Unsafe.Add(ref baseVelocities, i);
                if (conveyorSettings.IsLinearConveyor)
                {
                    velocity.Linear = conveyorSettings.LinearVelocity;
                }
            }

            simulation.IntegratePoses(dt, threadDispatcher);
            PosesIntegrated?.Invoke(dt, threadDispatcher);

            simulation.IncrementallyOptimizeDataStructures(threadDispatcher);
        }
Post Reply