It is All about Traffic, and Programming
0 visitors online now
0 guests, 0 members


A cute example of Aimsun scripting

Aimsun is traffic simulation software developed by Transport Simulation System (TSS). It has a very powerful python-based scripting engine.  Though other traffic simulation software, e.g., PTV Vissim or Caliper TransModeler provides scripting functionality as well – yet Aimsun’s scripting engine has some unique features that make the scripting work not only productive, but also quite fun 😆 .

One such feature is the so-called live-binding of  a script to any selected object type.  

In Aimsun framework,  all elements of the simulation task – from network geometry,  control devices, script,  to menus, dialogs, projects, scenarios, algorithms …. everything … anything – is an “object”,  derived from a base class GKBaseObject which is rooted from Qt’s QObject.  The entire Aimsun software is built upon a Model-View-Controller (MVC) framework taking advantage of Qt framework.  This framework is well exposed to end users via its SDKs, APIs, and the Scripting Engine.  Apart from being a  comprehensive traffic simulation tool,  Aimsun presents itself as an excellent example of  modern design patterns and software engineering. It has very small memory footprint as well.

The following example comes with default Aimsun installation, i.e.,  the sample script No. 30 “Copy Control Plan”.

Please note, the latest Aimsun 8.0.x versions have some internal changes breaking the scripts that once had worked with Aimsun version 7.x. TSS releases  these scripts with the official Version 8.0.x without upgrading those scripts,  and you’ll have to fix them yourself.   (UPDATE: Aimsun 8.0.8 released on March 19, 2015 has fixed this.)

The following is the original script Copy Control Plan that comes with Aimsun official 8.0.x installation:


In the above,  Line 3 – Line 7 should be replaced as follows:


So, the script after the fix should look like the following:


Some notes:

  • The object that the script binds to is represented by the name “target”. Therefore,  if the script is bound to node-type objects (e.g., the script is added to the context menu of node objects),  “target” would refer to the subject node object.  To bind a script to another  object,  you simply right click the script, select “Properties”. Then from “Settings” tab –> “Add Script to a Menu”, select an object type in the drop-down list “To Context Menu for Object Type” .  See the figure below.


  • getControlPlan is called twice, at Line 11, and at Line 14. At Line 11,  it is called to get the source control plan object. At Line 14, it is called to get the destination control plan object.
  • GAnyObjectChooserEditor and GAnyObjectChooser are two interesting classes.  GAnyObjectChooserEditor is a later-addition.  Originally there was only GAnyObjectChooser class.  The helper class GAnyObjectChooserEditor is added to separate the chooser class and the editor class – a better design/refactoring but breaking some of the existing scripts .  Basically,  as its name indicates, it provides a user interface to choose an object of the specified type in Aimsun framework.  You can see it in action in the following figure:


  •   chooser.setType is the one responsible for specifying what type of objects that the Editor dialog should present.

In summary – Aimsun python scripting engine are able to:

  1. Dynamically bind a script  to any objects during run-time;
  2. Inside the script engine, Aimsun provides ready-made UI elements to facilitate the interactions between the end user and the Aimsun host.  This allows productive and efficient workflow of simulation projects with the creative minds of a traffic modeler.
  3. Agree?  Any thoughts, or Aimsun scripting experience to share?

Aimsun scripting: A different perspective

Aimsun is an Object-Oriented Framework and Unified Platform for Traffic Modeling.  It  provides quite a few programming interfaces for advanced applications and customization. To name a few,  those  include Aimsun Simulator API,  Aimsun SDK,  Aimsun Python-based Scripting,  MicroSDK,  Logistics SDK, Parking APIs.  These SDKs and APIs  together with Aimsun main software  provide powerful tools for its users.

Interestingly, by design all these APIs, albeit having different focuses, have ONE in common, i.e., they MUST either be invoked within Aimsun host ( e.g., Aimsun SDK and Aimsun Pyhton-based Scripting), or called-back during run time (i.e., simulator API and MicroSDK). This means Aimsun cannot be used as a COM automation sever, and therefore it may not be invoked by external applications.

Actually, it is only partially true.  First of all, this is not something to complain about.  Aimsun is a cross-platform software package;  it runs on Linux, MacOS, and Windows. COM is a very much Windows specific technology, so in spite of that it is doable it simply doesn’t seem to make much sense to dedicate Aimsun to a platform specific feature.  Second some the COM-like functionality can be achieved by using ANGApp class, which is fully accessible by Python scripting.

In this post,  I would like to discuss a way of porting ANGApp class by Python C API,  so that some of  its advanced functionality becomes available to a common compiler-based language.  To start with,  the following shows a Python wrapper class that encapsulate some COM-like interfaces, on top of the ANGApp class:

from PyANGBasic   import *
from PyANGApp     import *
from PyANGAimsun  import *
from PyANGKernel  import *
from PyANGConsole import *

__author__    = "Wuping Xin"
__company__   = "No Inc."
__copyright__ = "Copyright (c) No Rights Reserved"
__license__   = "python"
__version__   = "$1.0.0 $"
__date__      = "$Date: 2009/07/15 11:57 $"

class AimsunApp:
"Wrapper class of Aimsun ANGApp class for C++ application with Python C API"
def __init__(self, isCon = False):
  self.angInstance = None
  self.simulator   = None
  self.model       = None
  self.angGui      = None
  self.isConsole   = isCon
  def initInstance(self):

def freeInstance(self):

def openNetwork(self,filename):

def runInteractive(self):

def __setModel(self):
  self.model = self.angInstance.getModel()

def initSimulator(self,repID,simMode = 0):

def runSingleStep(self):
  self. angInstance.processEvents()

With this wrapper class ready, we can use the following C code to invoke:


pName    = PyString_FromString("aimsunpy_interface");
pModule  = PyImport_Import(pName);
pDict    = PyModule_GetDict(pModule);

// Build the name of a callable class
pClass = PyDict_GetItemString(pDict, "AimsunApp");

// Create an instance of the wrapper cls.
if (PyCallable_Check(pClass))
    pInstance = PyObject_CallObject(pClass, NULL);

PyObject_CallMethod(pInstance, "initInstance", NULL);
PyObject_CallMethod(pInstance, "openNetwork","s","C:\\Test\\test.ang");
PyObject_CallMethod(pInstance, "initSimulator","i",346);

This is a nuance to note – when trying to load a C-Extension module ( i.e., *.pyd file),  if the host program that embeds Python interpreter links with pythonxx_d.dll, then PyImport_Import will import the xxxx_d.pyd, even if the module’s name is specified without “_d”!  Also this approach is dependent on Aimsun’s embedded Python  interpreter hence there is some run-time performance hit. But if that is not an issue, this approach would make it possible to integrate Aimsun with external applications, for example, MATLAB platform.