Exemplo de Script: Criando objetos¶
Scripting é uma ferramenta eficaz para modificação de dados, mas também pode ser usado para criar novos dados. Este exemplo mostra como importar dados seguindo um exemplo que cria um novo estado de tráfego usando dados de um arquivo externo.
Criação de objetos¶
Qualquer objeto derivado de GKObject deve ser criado (salvo indicação específica) usando um Novo Command. Esses comandos criam e inicializam novas referências de objeto, adicionam o objeto à sua camada ou pasta e reduzem o código a ser escrito. Por exemplo:
cmd = GKTurningNewCmd()
cmd.setTurning( origin, destination )
cmd.setUndoable( False )
Este exemplo chama o construtor, define as informações mínimas necessárias para o objeto e define desfazível como false para impedir o new comando sendo desfeito na GUI.
O novo comando precisa ser incluído no model commander para garantir a execução instantânea do comando e manter as referências do comando para fins de ações de desfazer/refazer:
model.getCommander().addCommand( cmd )
Depois que o comando tiver sido executado e quisermos acessar o novo objeto, qualquer comando New o retorna a partir de createdObject() método:
newTurn = cmd.createdObject()
Se o novo comando para o GKType que você está procurando não existir, há uma forma alternativa de criar objetos, que é usando o GKSystem::newObject() chamada. Esta chamada criará um novo objeto, o inicializará e o adicionará ao catálogo do modelo atual.
Criar um novo objeto derivado de GKObject de qualquer outra forma pode corromper o modelo atual ou fazer o sistema falhar mais tarde. Portanto, para criar um novo objeto de um tipo cujo NewCmd não está disponível (GKMyType, por exemplo), o código será:
state = GKSystem.getSystem().newObject( "GKMyType", model )
e não:
state = GKMyType() # NEVER do this!!!
Esta chamada instrui o sistema a criar um novo objeto de um tipo específico (um objeto GKMyType neste exemplo) no modelo fornecido. O novo objeto ficará sem título, portanto é aconselhável atribuir-lhe um nome usando o GKObject::setName() método:
state.setName( "New my type object" )
Organização de objetos¶
O Aimsun Next organiza objetos de duas maneiras, dependendo do seu tipo. Objetos gráficos são organizados em camadas e exibidos nas vistas 2D e 3D. Objetos não gráficos são organizados em pastas e exibidos na Janela do Projeto.
Após criar um objeto sem usar seu comando New, um novo objeto deve ser adicionado a uma camada ou a uma pasta, dependendo de ele ser gráfico ou não gráfico.
Imagine que o objeto GKMyType criado na seção anterior seja um objeto não gráfico. Como objeto não gráfico, ele deve ser adicionado a uma pasta. Vamos imaginar que queremos adicioná-lo à pasta de estados de tráfego. No entanto, essa pasta deve ser criada se ainda não existir. O código a seguir cria a pasta:
folderName = "GKModel::trafficStates"
folder = model.getCreateRootFolder().findFolder( folderName )
if folder == None:
folder = GKSystem.getSystem().createFolder( model.getCreateRootFolder(), folderName )
Primeiro, este código procura a pasta usando o GKFolder::findFolder() call. Ele procura na pasta raiz do modelo, que é o local normal. Se a pasta não estiver lá, ela será criada. Porque o Estados de Tráfego pasta é uma pasta do sistema, precisamos apenas passar o nome interno da pasta para que o sistema crie a estrutura correta. Consulte a tabela abaixo para o nome interno das pastas do sistema.
Nomes internos das pastas do sistema
| Nome externo | Nome Interno (único) |
|---|---|
| Configurações de Centroides | GKModel::centroidsConf |
| Controle | GKModel::top::control |
| Planos de Controle | GKModel::controlPlans |
| Análise de Dados | GKModel::top::dataAnalysis |
| Dados de Demanda | GKModel::top::traffic |
| Localizações dos Detectores | GKModel::detectorLocations |
| Funções | GKModel::functions |
| Infraestrutura | GKModel::top::infrastructure |
| Tipos de Faixa | GKModel::laneTypes |
| Planos de Controle Mestres | GKModel::masterControlPlans |
| Matrizes OD | GKCentroidConfiguration::matrices |
| Rotas OD | GKCentroidConfiguration::routes |
| Transporte Público | GKModel::top::publicTransport |
| Linhas de Transporte Público | GKModel::publicLines |
| Planos de transporte público | GKModel::publicPlans |
| Conjuntos de dados reais | GKModel::realDataSets |
| Tipos de vias | GKModel::roadTypes |
| Cenários | GKModel::top::scenarios |
| Scripts | GKModel::top::scripts |
| Subcaminhos | GKModel::subPaths |
| Estratégias | GKModel::strategies |
| Condições de Tráfego | GKModel::trafficConditions |
| Demandas de Tráfego | GKModel::trafficDemand |
| Gestão de Tráfego | GKModel::top::trafficmanagement |
| Estados de Tráfego | GKModel::trafficStates |
| Gatilhos | GKModel::triggers |
| Veículos | GKModel::vehicles |
| Modos de Visualização | GKModel::viewModes |
| Estilos de Visualização | GKModel::viewStyles |
Por fim, o novo objeto deve ser adicionado à pasta:
folder.append( state )
Objetos gráficos devem ser adicionados ao GeoModel. Dentro do GeoModel, os objetos devem ser atribuídos a uma camada. Na maioria dos casos, a camada ativa será usada. Isso é encontrado usando o getActiveLayer() chamada:
(model.getGeoModel().getActiveLayer()).
Por exemplo, se o comando New para criar um detector não existisse (o GKSectionObjectNewCmd é o que deve ser usado para isso), as etapas que precisaríamos seguir para escrever um script que criasse um detector no meio de uma seção seriam: primeiro criar o detector e, em seguida, definir seus parâmetros (nome, faixas e comprimento). Adicioná-lo sobre uma seção (um detector não pode existir por conta própria) e, por fim, adicioná-lo ao GeoModel, colocando-o na mesma camada da seção. Se o script for adicionado ao menu de contexto Section, então a variável target é usado para se referir à seção:
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 )

Todas as etapas acima para objetos não gráficos e gráficos são tratadas automaticamente ao usar os comandos New.
Destruição de objeto¶
Os objetos são removidos do modelo em duas etapas:
- Obtém o comando de exclusão para o objeto chamando GKObject::getDelCmd()
- Executar o comando
Por exemplo:
myObjectToDelete = model.getCatalog().find(104) #retrieve object
if myObjectToDelete!=None:
cmd = myObjectToDelete.getDelCmd()
model.getCommander().addCommand(cmd)
Como a classe GKObjectDelCmd é derivada de GKCommand, ela fornece funcionalidade de desfazer. Portanto, para tornar a exclusão permanente (não desfazível), adicione um comando nulo:
model.getCommander().addCommand(None)
Lendo um Arquivo¶
Após criar um Traffic State, a próxima etapa é definir os fluxos de entrada lendo-os a partir de um arquivo. Este será um arquivo ASCII com as informações organizadas em duas colunas em formato separado por vírgulas. A primeira coluna contém o identificador da seção; a segunda contém o fluxo de entrada.
Primeiro, abra o arquivo e leia-o linha por linha. Em seguida, divida cada linha usando vírgula como separador.
Use o catálogo para procurar a seção usando seu ID. Se, em vez de identificadores, foram usados identificadores externos ou nomes. O método pode ser alterado para fazer referência a estes.
Com a seção e o fluxo, definimos o fluxo no estado de tráfego:
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 )
Tratamento de erros¶
Suponha que o arquivo de entrada tivesse um erro e contivesse um identificador para um centroide em vez de uma seção. O catálogo retornará o objeto com esse identificador – um centroide – e quando setEntranceFlow() é chamado usando esse centroide. O Aimsun Next reportará um erro como mostrado aqui:
Python Error (exceptions.TypeError): argument 1 of GKTrafficState.setEntranceFlow() has an invalid type
Um erro de tipo inválido é gerado, pois a função espera uma seção, mas recebeu um centroide. Observe que o código já se protege de objetos None; None é retornado quando nenhum objeto é encontrado.
Portanto, ao procurar um objeto no catálogo, é aconselhável verificar primeiro se ele foi encontrado e, em segundo lugar, se é do tipo correto usando o seguinte código:
if section != None and section.isA( "GKSection" ):