Creating a custom route programmatically

Transporters with path-guided navigation move from one point to another by following the chosen route. The routing information is stored in the RouteData object. It contains a series of movement tasks. Each task describes transporter's movement along a single segment of the route. The segment ends when the type of movement changes. There are three types of movement:

This type of object is returned by the findShortestPath() function used to specify the transporter's route, and by the getRouteData() function used to obtain the details of the previously specified route.

Example of custom routing

Demo model: Custom Routing for Transporters

In this example, we will demonstrate how to specify a custom route for a transporter (AGV).

We have simulated the transfer of material items between two nodes, which are connected by three paths of noticably different lengths. In the process diagram this transfer is defined by the MoveByTransporter block from the Material Handling Library.

The items are transferred from node1 to node2 by a single AGV which is defined by the TransporterFleet block. We use the TransporterControl block to specify the rules of movement for the AGV. The Navigation parameter in its properties is set to Custom: this way we can specify our own routing algorithm for the AGV. This algorithm is described in the custom setRoute(source, target, unit) function. We switch the Find path parameter of the TransporterControl block to the dynamic value editor and place the call of the custom function there.

The function must return the RouteData object, therefore in the function's properties we have selected the Returns value option and specified the RouteData in the Type field. In the Arguments section we have set the following arguments:

ILocation source - Argument that passes the point where the AGV begins its movement.

ILocation target - Argument that passes the point where the AGV ends its movement.

AGV agv - Argument that defines the AGV.

The function is used for routing and is called each time the AGV starts its movement.

Here is the routing algorithm we have created for this example:

//check the AGV's current state
if
(agv.getState() == TransporterState.DELIVERING)
{
    switch (radio.value)
    {
        case 0:
            //use the default routing
            return transporterControl.findShortestPath(source, target, null, null);
        case 1:
        {
            //use the default routing with the specified path(s) excluded
            Path[] avPaths = {path1};
            //avPaths list passes the excluded paths to the routing algorithm
            return transporterControl.findShortestPath(source, target, null, avPaths);
        }
        case 2:
        {
            //create data structure to store the custom route
            RouteData route = new RouteData();
            
            //define the 1st movement task, from node1 center to node1 border
            Point source1 = new Point(100.0, 100.0, 0.0);
            Point target1 = new Point(100.0, 110.0, 0.0);
            route.addPlainMovement(node1, source1, target1);
            
            //the 2nd movement task along path2
            route.addPathMovement(path2, 0.0, 78.0, METER);
            
            //the 3rd task, inside node2    
            Point source2 = new Point(700.0, 110.0, 0.0);
            Point target2 = new Point(700.0, 100.0, 0.0);
            route.addPlainMovement(node2, source2, target2);
            
            return route;
        }
        default:
            return null;
    }
}
//use the shortest path to return to the home location
else return transporterControl.findShortestPath(source, target, null, null);

In this example, you can choose one of three routing policies using the radio buttons control. We utilize the switch statement in the algorithm to specify one delivery route per button. The integer value used for each case is the index of the corresponding radio button. Note, that the index is zero-based, so the index of the first button is 0.

The statement contains three cases.

Using the default route

By default, the transporters in AnyLogic select the shortest route to target. In this example, the AGV uses the shortest path as the delivery route if the Default routing (shortest route) radio button is selected.

We set this route by calling the findShortestPath() function of the TransporterControl block and passing the following arguments:

ILocation source - The place where the AGV starts its movement.

ILocation target - The place where the AGV moves to.

null - We don't want to exclude any nodes, therefore we provide null here.

null - We don't want to exclude any paths, therefore we provide null here.

Excluding paths / nodes from the default route

You may need to create a custom route for the transporter where it will avoid certain paths or nodes, but still select the shortest way to the destination. In this example, when the Exclude path1 radio button is selected, we tell the AGV to find the shortest delivery route which must exclude path1.

First, we create a local variable avPaths (array of Path elements). In our example it stores just one path, path1. To specify several paths, list them comma-separated inside the curly brackets.

    Path[] avPaths = {path1};

Then we call the findShortestPath() function again, but this time we pass our local variable avPaths as the last argument to exclude from the route.

    return transporterControl.findShortestPath(source, target, null, avPaths);

AnyLogic also provides an option to include certain paths in the custom route with the help of the findShortestPath(ILocation source, ILocation target, Node[] nodesToAvoid, Path[] pathsToAvoid, Path[] pathsToInclude) function.

Creating the custom route with RouteData

You can create the transporter's route from scratch by manually defining all the necessary movement tasks that will be stored in the RouteData object. This approach gives you the most control over the transporter's movement.

In this example we use this approach to define the AGV's delivery route along path2. This delivery route is used when we select the Custom route radio button.

First, we declare the new RouteData object:

RouteData route = new RouteData();

Next, we define the first movement task: PLAIN type of movement from the center of node1 to the point of connection between node1 and path2.

We define two local variables to store the movement start point (source1) and end point (target1). The arguments pass X-, Y-, Z- coordinates of the point. We set source1 to store the node1 center point, and target1 - the connection point of the node1 and path2.

     Point source1 = new Point(100.0, 100.0, 0.0);
     Point target1 = new Point(100.0, 110.0, 0.0);

We use the addPlainMovement() function of the RouteData to define the movement task and add it to the route.

          route.addPlainMovement(node1, source1, target1);

The function has the following arguments:

The second movement task describes the PATH type of movement along path2:

    route.addPathMovement(path2, 0.0, 78.0, METER);

To add the PATH movement task to the route, we use the addPathMovement() function of the RouteData.

The function has the following arguments:

The third movement task describes the PLAIN type of movement from the point of connection between path2 and node2 to the center of node2.

Setting up the return route

The algorithm tells the AGV to select the shortest route every time it returns to its home location. This is executed by using the ifstatement and checking the current state of the AGV: if the AGV is delivering the material item, it follows the chosen routing policy described above. In any other state it uses the shortest route set up with the help of findShortestPath() function.

//check the AGV's current state
if (agv.getState() == TransporterState.DELIVERING)

    { //the section of code that describes the delivery routing policy }

else return transporterControl.findShortestPath(source, target, null, null);

Related topics  

        Transporters

        Transporter API

        Path-guided navigation