WIP AGV Demo
Now that we have the basics down, we can move on to a more advanced example
In this tutorial we’ll be making a AGV(Automated Guided Vehicle) demo. We’ll be picking and dropping off boxes, moving it through a metal detector and then letting it be carried away.
The first step is to create a DESController by adding a new gameobject and adding the DESController script. All DES Participants will need to be children of the DESController.
Drawing the AGV Splines
The AGV route consists of two splines, the starting spline from outside where the AGV’s are spawned and the main loop. To draw these splines we’ve created shots of the AGV and generated the splines with the Actor Route Creator
.
To create the loop spline there is a setting in the Actor Route Creator
that closes the spline. Check the “Close the resulting main spline“ checkbox to generate a closed/loop spline.
After generating the spline you might see the following anomaly in corners. This can be fixed by selecting the spline point and shortening the yellow handle.
Spawning the AGV
First, add the AGV to the scene and attach the AGVActor script to it.
AGVActor
using u040.prespective.prescripted.des;
namespace u040.agv
{
/// <summary>
/// Basic motion actor for the agv
/// </summary>
public class AGVActor : DESActor
{
public CardBoxActor box;
}
}
CardBoxActor (Will be used later)
using u040.prespective.prescripted.des;
namespace u040.agv
{
public class CardBoxActor : DESActor
{
public MotionTensorView motionTensorView;
private MotionTensor motionTensor;
public void StartMotion(double passedFrameTime)
{
motionTensorView.GenerateMotionTensor(this, out motionTensor);
SimulationController.AddActivityMidFrame(passedFrameTime, SimulationController.FrameTime, this, motionTensor);
}
}
}
Then create a gameobject for the spawner and attach the BlockableSpawner
script. Then set the “Spawn Interval Range” X and Y to 10. This is how many seconds it takes between spawns. Select which object to spawn by setting the Spawn Recipies to 1 and then setting the Spawn prototype to the AGVActor. Then set the Starting Tensor to the following.
Spline: The spline on which to spawn, here we use the spawn spline.
Thickness: How much space it will take on the spline. Because the AGV’s don’t collide in our test we’ve set it to a random value of 0.05 so as that it has a thickness.
Velocity curve: Click the velocity curve and set it to 1.
Component motion mode: We’ve selected absolute as that is how we want to move.
Component Motion Type: Because the AGV changes it’s rotation and position over the spline we’ve selected “TRANSLATION_AND_ROTATION“.
Weight Curve: Set this to 1, we don’t use it so it can just use a default value
Start Perc override: We don’t use this feature so keep it at it’s default 0.
Look Offset: We don’t use this feature so keep it at it’s default 0.
And setting the “Max Active Spawns“ to 10. This will stop the spawning when 10 AGV’s are active in the scene.
When set correctly this spawns the AGV and will automatically give it the motion tensor to start moving.
Changing spline
Next up is the changing of the spline. After the AGV has spawned, it moves over the spawn spline. At the end of the spawn spline, it needs to move onto the loop spline. At the end of the spawn spline there is a cue that uses the ChangeSplineInstructor
.
Create an object for the instructor, Attach the ChangeSplineInstructor
script and select the ChangeSplineInstructor
object in the cue’s Cue Instructor
field. Then set the “Next Spline“ field on the ChangeSplineInstructor
to the loop spline and the velocity to 1.
ChangeSplineInstructor
using System.Collections.Generic;
using u040.prespective.core;
using u040.prespective.prescripted.des;
/// <summary>
/// Changes splines when
/// </summary>
public class ChangeSplineInstructor : DESInstructor
{
/// <summary>
/// The new spline on which to transfer
/// </summary>
public DSpline nextSpline;
/// <summary>
/// The velocity of the new movement
/// </summary>
public double velocity;
/// <summary>
/// The thickness of the object
/// </summary>
public double thickness = 0.02;
public override bool ApplyInstruction(ADESActor actor, ADESCue _cue, ActorCueIntersectionEvent _intersectionEvent)
{
if (_intersectionEvent.IntersectionType != ActorCueIntersectionEvent.CueIntersectionType.CENTER)
{
return false;
}
//Destroy the old movement
List<MotionTensor> motionTensors = actor.getActivitiesByType<MotionTensor>();
foreach (MotionTensor tensor in motionTensors)
{
tensor.Destroy(_intersectionEvent.EventTime, SimulationController);
}
//Create a new movement on the new spline
MotionTensorComponent mtc = new MotionTensorComponent(nextSpline, MotionMode.ABSOLUTE,
MotionType.TRANSLATION_AND_ROTATION, thickness, 1d, velocity, 0d);
mtc.LookOffsetPercentage = 0d;
List<MotionTensorComponent> components = new List<MotionTensorComponent>() {mtc};
MotionTensor motionTensor = new MotionTensor(components);
motionTensor.IsRunning = true;
SimulationController.AddActivityMidFrame(_intersectionEvent.EventTime, SimulationController.FrameTime,
actor, motionTensor);
return true;
}
}
The ChangeSplineInstructor
has two actions, destroying the old movement:
And creating the new one
It’s important to always destroy the old movement so they don’t counteract one another. Also note that this uses AddActivityMidFrame
instead of AddActivity
that was used in the BasicMotionActor
in the introduction. This is because the instructor is called mid frame while the BasicMotionActor
uses OnSimulationStart
. The AddActivityMidFrame
uses the frametime passed and the total frametime. The passed frame time is the time passed in the current frame and the total frame time is the total length of the current frame. The passed frametime can be retrieved from the ActorCueIntersectionEvent.EventTime
in the Instructor.ApplyInstruction
or it is explicitly passed. The total frametime can be retrieved from the SimulationController.FrameTime
. Actions that change something mid frame in the DES system need these two variables to work, if it is an option they should be passed.
Waiting
Next up is the AGV waiting for a box to come down the conveyor belt. First of we’ll generate the Cardboard Box Spline by creating shots of the box and then creating a spline with the Actor Route Creator
. Make sure to set the Spline Up Direction Mode
in the Actor Route Creator
to “Free” so the up direction of the box is defined by the spline.
When the AGV arrives we want it to spawn and wait for the box, so we add a waiting instructor to the Box_Pickup_From_Spawn
cue. The instructor is the WaitForBoxSpawnInstructor
we add a new gameobject, add the instructor and select it in the cue’s “Cue Instructor“ field.
WaitForBoxSpawnInstructor
This sets the motion tensor to zero, stopping the motion. Then setting the waiting AGV so that the box knows what to move on, and then spawns a box. To spawn a box we use a custom spawner named the CardBoxSpawner
.
CardBoxSpawner
Create a new gameobject and attach the CardBoxSpawner
, then add the cardboard box to the scene and attach the CardBoxActor
to the box gameobject (can be found earlier in the article). Then add a motion tensor in the CardBoxActor.MotionTensorView
. Using the recently created cardbox spline, velocity of 1 and Component Motion Type to TRANSLATION_AND_ROTATION.
Then go to the CardBoxSpawner
and select the CardBoxActor
in the ”spawnObject”. Then go to the WaitForBoxSpawnInstructor
and set the “Custom Spawner“ field to the just created CardBoxSpawner
.
When the box is at the end of the spline it hits the cue (Box_Spawn_End
) to parent the box to the AGV and restart the AGV motion. This uses the SetBoxOnAGVSpawnerInstructor
instructor. Create a new gameobject, add the SetBoxOnAGVSpawnerInstructor
and connect it from the Box_Spawn_End
“Cue Instructor“ field. Then set the SetBoxOnAGVSpawnerInstructor
“Wait For Box Spawn Instructor“ field to the previously created WaitForBoxSpawnInstructor
.
SetBoxOnAGVSpawnerInstructor
Drop off the package for the metal detector
Next up is dropping the package off to go through the metal detector. First we create the shots necessary for the box to be dropped off and picked up again. Then generate the spline with the Actor Route Creator
.
The easiest way to create the metal detector spline is to first create a instructor that stops the AGVActor on the cue. And then getting the position of the box as a starting point.
Next up is creating the Instructor to stop the AGV temporarily and moving the box on the metal detector spline. The DropOffMetalDetectorInstructor
can then be connected to the Box_Dropoff_Metal_Detector
cue to pause the AGV and move the box onto the metal detector.
DropOffMetalDetectorInstructor
Waiting for the box after the metal detector
After the metal detector the box returns on top of the AGV. This is almost the same action as when the AGV waits for the spawned box.
Firstly stop the AGV at the Box_Pickup_Metal_Detector
cue with the PickupMetalDetectorInstructor
instructor. The PickupMetalDetectorInstructor
sets the velocity to zero and keeps track of which AGV is waiting. This way we can get which AGV is waiting when the box hits the MetalDetector_End
cue.
PickupMetalDetectorInstructor
Next we’ll add the instructor for when the box hits it’s end cue MetalDetector_End
. This references PickupMetalDetectorInstructor
to get the AGV waiting, destroys it’s old movement, parents it to the AGV and then restarts the movement of the AGV.
SetBoxOnAGVMetalDetectorInstructor
Moving the box onto the exit conveyor belt and destroying
This movement is the exact same as the drop off at the metal detector so we can re-use the same instructor (DropOffMetalDetectorInstructor
) on a different gameobject.
At the end of the box spline we add one more cue with a destroy instructor to destroy the boxes.
DestroyInstructor
Conclusion
With the DES system we can move objects over time. By using cues and instructors we can create precise and discrete simulations.
Prespective Documentation