Skip to content

Script Example: Creating objects

Scripting is an effective tool for data modification but it can be used to create new data as well. This example shows how to import data following an example that creates a new traffic state using data from an external file.

Object Creation

Any object that derives from GKObject must be created (unless specifically indicated) using the GKSystem::newObject() call. This call will create a new object, will initialize it, and will add it to the current model catalog.

Creating a new object that derives from GKObject in any other way can corrupt the current model or make the system crash later on. Therefore to create a new traffic state (GKTrafficState) the code will be:

state = GKSystem.getSystem().newObject( "GKTrafficState", model )

and not:

state = GKTrafficState() # NEVER do this!!!

This call instructs the system to create a new object of a particular type in the supplied model. The new object will be untitled, so it is advisable to give it a name using the GKObject::setName() method:

state.setName( "New traffic state" )

New Command

For some objects, there is an option to create new object by using a New Command. These commands create and initialize new object references and simplify the code. For example:

cmd = GKTurningNewCmd()
cmd.setTurning( origin, destination )
cmd.setUndoable( False )

This example calls the constructor, sets the minimum information required for the object, and sets undoable to false to prevent the new command being undone in the GUI.

If the new command is include in the model commander, this guarantees the command execution instantaneously and, for undo/redo action purposes, it also keeps the command references:

model.getCommander().addCommand( cmd )

Once the command has been executed and we want to access the new object, New Command returns it from createdObject() method:

newTurn = cmd.createdObject()

Object Organization

Aimsun Next organizes objects in two ways depending on their type. Graphical objects are organized in layers and shown in the 2D and 3D views. Non-graphical objects are organized in folders and shown in the Project Window.

After creation, a new object must be added to a layer or to a folder, depending on whether it is graphical or non-graphical.

As the traffic state that we will create in this exercise is a non-graphical object it must be added to a folder. However this folder must be created if it does not already exist. The following code creates the folder:

folderName = "GKModel::trafficStates"
folder = model.getCreateRootFolder().findFolder( folderName )
if folder == None:
    folder = GKSystem.getSystem().createFolder( model.getCreateRootFolder(), folderName )

First, this code looks for the folder using the GKFolder::findFolder() call. It searches in the root folder of the model which is the normal location. If the folder is not there then it will be created. Because the Traffic States folder is a system folder, we just need to pass the internal name of the folder for the system to create the correct structure. Refer to the table below for the internal name of the system folders.

Internal names of the system folders

External Name Internal Name (unique)
Centroid Configurations GKModel::centroidsConf
Control GKModel::top::control
Control Plans GKModel::controlPlans
Data Analysis GKModel::top::dataAnalysis
Demand Data GKModel::top::traffic
Detector Locations GKModel::detectorLocations
Functions GKModel::functions
Infrastructure GKModel::top::infrastructure
Lane Types GKModel::laneTypes
Master Control Plans GKModel::masterControlPlans
OD Matrices GKCentroidConfiguration::matrices
OD Routes GKCentroidConfiguration::routes
Transit GKModel::top::publicTransport
Transit Lines GKModel::publicLines
Transit Plans GKModel::publicPlans
Real Data Sets GKModel::realDataSets
Road Types GKModel::roadTypes
Scenarios GKModel::top::scenarios
Scripts GKModel::top::scripts
Subpaths GKModel::subPaths
Strategies GKModel::strategies
Traffic Conditions GKModel::trafficConditions
Traffic Demands GKModel::trafficDemand
Traffic Management GKModel::top::trafficmanagement
Traffic States GKModel::trafficStates
Triggers GKModel::triggers
Vehicles GKModel::vehicles
View Modes GKModel::viewModes
View Styles GKModel::viewStyles

Finally, the new object must be added to the folder:

folder.append( state )

Graphical objects must be added to the GeoModel. Within the GeoModel objects must be assigned to a layer. In most cases, the active layer will be used. This is found using the getActiveLayer() call:

(model.getGeoModel().getActiveLayer()).

For example, to write a script that creates a detector in the middle of a section: First create the detector, then define its parameters(name, lanes, and length). Add it on the top of a section (a detector cannot exist on its own), and finally add it to the GeoModel, placing it on the same layer of the section. If the script is added to the Section context menu, then the variable target is used to refer to the section:

detector = GKSystem.getSystem().newObject( "GKDetector", model )
detector.setName( "A new detector" )
detector.setLanes( 0, 1 )
detector.setLength( 4.5 )
detector.setPosition( target.length2D() / 2.0 )
target.addTopObject( detector )
model.getGeoModel().add( target.getLayer(), detector )


Add script to Context Menu

Object Destruction

Objects are removed from the model in two stages:

  1. Get the delete command for the object calling GKObject::getDelCmd()
  2. Execute the command

For example:

myObjectToDelete = model.getCatalog().find(104) #retrieve object
if myObjectToDelete!=None:
    cmd = myObjectToDelete.getDelCmd()
    model.getCommander().addCommand(cmd)

Because the GKObjectDelCmd class is derived from GKCommand, it provides undo functionality. Therefore, to make the deletion permanent (non-undoable), add a null command:

model.getCommander().addCommand(None)

Reading a File

After creating a Traffic State, the next stage is set the input flows by reading them from a file. This will be an ASCII file with the information organized in two columns in comma separated format. The first column holds the identifier of the section, the second one holds the input flow.

First, open the file, and read it line by line. Next, split each line, using comma as separator.

Use the catalog to look for the section using its ID. If, instead of identifiers, external identifiers or names were used. The method can be changed to refer to these.

With the section, and the flow, we set the flow in the traffic state:

def importState( model, state, fileName ):
for line in open( fileName, "r" ).readlines():
    # Separate the line in columns
    columns = line.split( "," )
    # First column contains the id of the section
    section = model.getCatalog().find(int(columns[0]))
    # Second column contains the flow
    flow = float(columns[1])
    # Set the value if the section is valid
    if section != None:
        state.setEntranceFlow( section, None, flow )

Error Handling

Suppose that the input file had an error in it and contained an identifier for a centroid instead of a section. The catalog will return the object with that identifier – a centroid – and when setEntranceFlow() is called using that centroid. Aimsun Next will report an error as shown here:

Python Error (exceptions.TypeError): argument 1 of GKTrafficState.setEntranceFlow() has an invalid type

An invalid type error is given as the function expects a section but has instead been passed a centroid. Note that the code already protects itself from None objects; None is returned when no object is found.

Therefore, when looking for an object in the catalog it is advisable to check first if it is found and second if it is of the correct type using the following code:

if section != None and section.isA( "GKSection" ):