Example of Microscopic Model SDK use¶
In this section we provide examples for the four files that can be modified to code a new behavior model:
File simVehicleParticular.h
\\*-Mode: C++;-*-
#ifndef _simVehicleParticular_h_
#define _simVehicleParticular_h_
#include "A2BehavioralModelUtil.h"
#include "A2SimVehicle.h"
class A2BEHAVIORALEXPORT simVehicleParticular: public A2SimVehicle
{
private:
float newAttribute;
public:
simVehicleParticular ( void *handlerVehicle, unsigned short idhandler, bool isFictitiousVeh );
~ simVehicleParticular ();
const float getnewAttribute() const;
void setnewAttribute ( float avalue);
};
#endif
File simVehicleParticular.cpp
#include "simVehicleParticular.h"
simVehicleParticular::simVehicleParticular ( void *handlerVehicle, unsigned short idhandler, bool isFictitiousVeh, unsigned int vehTypeId ) : A2SimVehicle( handlerVehicle, idhandler, isFictitiousVeh, vehTypeId )
{
//get a column from GKVehicle, retrieve its value and do any computation required
const unsigned short * param1 = AKIConvertFromAsciiString("GKVehicle::ExampleAttribute");
newAttribute = ANGConnGetAttributeValueFloat( ANGConnGetAttribute(param1), vehTypeId );
}
simVehicleParticular::~simVehicleParticular (){}
const float simVehicleParticular::getnewAttribute() const
{
return newAttribute;
}
void simVehicleParticular::setnewAttribute ( float avalue)
{
newAttribute=avalue;
}
File behavioralModelParticular.h
//-*-Mode: C++;-*-
#ifndef _behavioralModelParticular_h_
#define _behavioralModelParticular_h_
#include "A2BehavioralModelUtil.h"
#include "A2BehavioralModel.h"
#include "simVehicleParticular.h"
enum Type {eNone, eReservedLane, eTurning, eNotAllowedInfluence, eNotAllowed, ePTStopInfluence, eOnRamp, eLaneClosureInfluence, eIncidentInfluence, eLaneClosure, eIncident, ePTStop};
class A2BEHAVIORALEXPORT behavioralModelParticular: public A2BehavioralModel
{
private:
int seed;
double p_distance;
public:
behavioralModelParticular();
~behavioralModelParticular();
bool evaluateCarFollowing( A2SimVehicle *vehicle, double &newpos, double &newspeed);
bool evaluateLaneChanging( A2SimVehicle *vehicle ,int threadId);
double computeCarFollowingAccelerationComponentSpeed(A2SimVehicle *vehicle,double VelActual,double VelDeseada, double RestoCiclo);
double computeCarFollowingDecelerationComponentSpeed (A2SimVehicle *vehicle,double Shift,A2SimVehicle *vehicleLeader,double ShiftLeader,bool controlDecelMax=false, bool aside=false,int time=1);
double computeMinimumGap(A2SimVehicle *vehicleUp,A2SimVehicle *vehicleDown,double Xup,double Vup,double Xdw,double Vdw,double Gap,bool ImprudentCase=false, bool VehicleIspVehDw=false);
bool isVehicleGivingWay( A2SimVehicle *vehicleGiveWay, A2SimVehicle *vehiclePrio, yieldInfo *givewayInfo, int &Yield);
A2SimVehicle * arrivalNewVehicle( void *handlerVehicle, unsigned short idHandler, bool isFictitiousVeh, unsigned int vehTypeId);
virtual void removedVehicle( void *handlerVehicle, unsigned short idHandler, A2SimVehicle * a2simVeh );
bool avoidCollision(A2SimVehicle *vehicle,A2SimVehicle *vehiclePre,double ShiftPre);
double getGippsAccelerationSpeed (simVehicleParticular *vehicle,double VelActual,double VelDeseada, double RestoCiclo);
double getGippsDecelerationSpeed (simVehicleParticular *vehicle,double Shift,simVehicleParticular *vehicleLeader,double ShiftLeader,bool controlDecelMax=false, bool aside=false,int time=1);
double getGippsMinimumGap(simVehicleParticular * pVehUp,simVehicleParticular * pVehDw,double Xup,double Vup,double Xdw,double Vdw,double Gap,bool ImprudentCase=false,bool VehicleIspVehDw=false);
double getIDMAccelerationSpeed (simVehicleParticular *vehicle,double VelActual,double VelDeseada, double RestoCiclo);
double getIDMDecelerationSpeed (simVehicleParticular *vehicle,double Shift,simVehicleParticular *vehicleLeader,double ShiftLeader);
double getIDMMinimumGap(simVehicleParticular *vehicle,simVehicleParticular *leader,double Vup,double Vdw,double Gap);
};
#endif
File behavioralModelParticular.cpp
#include "behavioralModelParticular.h"
#include "simVehicleParticular.h"
#include "AKIProxie.h"
#include "ANGConProxie.h"
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
using namespace std;
#define Tolerancia 0.01
#define DBL_MAX 1.7976931348623158e+308
bool UseIDM=false;
behavioralModelParticular::behavioralModelParticular(): A2BehavioralModel()
{
const unsigned short *randomSeedString = AKIConvertFromAsciiString("GKReplication::randomSeedAtt" );
seed = ANGConnGetAttributeValueInt( ANGConnGetAttribute( randomSeedString ), ANGConnGetReplicationId() );
const unsigned short *param0= AKIConvertFromAsciiString( "GKExperiment::p_distance" );
p_distance = ANGConnGetAttributeValueDouble( ANGConnGetAttribute( param0 ),ANGConnGetExperimentId());
}
behavioralModelParticular::~behavioralModelParticular(){}
bool behavioralModelParticular::evaluateLaneChanging(A2SimVehicle *vehicle,int threadId)
{
//Define Lane Changing Direction
int LaneChangingDirection=vehicle->getNbLaneChanges2ReachNextValidLane();
if (LaneChangingDirection==0){
return false;
}
if (abs(LaneChangingDirection)>1){
LaneChangingDirection=LaneChangingDirection/abs(LaneChangingDirection);
}
bool RightLanePossible=vehicle->isLaneChangingPossible(1);
bool LeftLanePossible=vehicle->isLaneChangingPossible(-1);
if (LaneChangingDirection==-1 && !LeftLanePossible){
LaneChangingDirection=0;
} else if (LaneChangingDirection==1 && !RightLanePossible){
LaneChangingDirection=0;
}
if (LaneChangingDirection!=0){
double XPosTargetlane=vehicle->getPositionInTargetlane(vehicle->getPosition(0),LaneChangingDirection);
//Define whether a lane changing attempt is made or not
bool Intentacambio=true;
if (Intentacambio){
//Lane Changing attempt
A2SimVehicle * pVehDw=NULL;
A2SimVehicle *pVehUp=NULL;
double ShiftUp=0,ShiftDw=0;
vehicle->getUpDown(LaneChangingDirection, XPosTargetlane, pVehUp, ShiftUp, pVehDw, ShiftDw);
bool GapAcceptable=vehicle->isGapAcceptable(LaneChangingDirection, XPosTargetlane, pVehUp, ShiftUp, pVehDw, ShiftDw);
if(GapAcceptable){
vehicle->assignAcceptedGap(LaneChangingDirection, XPosTargetlane,(const simVehicleParticular*)pVehUp,ShiftUp,(const simVehicleParticular*)pVehDw,ShiftDw,threadId);
return true;
}
}
//Target New Gap
if (abs(vehicle->getNbLaneChanges2ReachNextValidLane())>0){
A2SimVehicle * pVehDwReal=NULL;
A2SimVehicle * pVehUpReal=NULL;
double ShiftUpReal=0,ShiftDwReal=0;
vehicle->getRealUpDown( LaneChangingDirection, XPosTargetlane, pVehUpReal, ShiftUpReal, pVehDwReal, ShiftDwReal);
vehicle->targetNewGap( LaneChangingDirection, XPosTargetlane, pVehUpReal, ShiftUpReal, pVehDwReal,ShiftDwReal,threadId);
if (pVehUpReal||pVehDwReal){
vehicle->assignNewTargetGap(XPosTargetlane,(const simVehicleParticular*) pVehUpReal, ShiftUpReal, (const simVehicleParticular*) pVehDwReal, ShiftDwReal, threadId);
}
}
}
return true;
}
bool behavioralModelParticular::evaluateCarFollowing(A2SimVehicle *vehicle, double &newpos, double &newspeed)
{
newspeed=vehicle->getAimsunCarFollowingSpeed();
double increment=0;
if (newspeed>=vehicle->getSpeed(vehicle->isUpdated())){
increment=newspeed*getSimStep();
}else{
increment=0.5*(newspeed+vehicle->getSpeed(vehicle->isUpdated()))*getSimStep();
}
newpos=vehicle->getPosition(vehicle->isUpdated()) + increment;
return true;
}
double behavioralModelParticular::computeCarFollowingAccelerationComponentSpeed( A2SimVehicle *vehicle, double VelActual, double VelDeseada, double RestoCiclo)
{
double VelPropia = 0;
if (UseIDM){
VelPropia = getIDMAccelerationSpeed( (simVehicleParticular*)vehicle, VelActual, VelDeseada, RestoCiclo);
}else{
VelPropia = getGippsAccelerationSpeed( (simVehicleParticular*)vehicle, VelActual, VelDeseada, RestoCiclo);
}
return VelPropia;
}
double behavioralModelParticular::computeCarFollowingDecelerationComponentSpeed (A2SimVehicle *vehicle,double Shift,A2SimVehicle *vehicleLeader,double ShiftLeader,bool controlDecelMax, bool aside,int time)
{
double VelImpuesta=0;
if (UseIDM){
VelImpuesta=getIDMDecelerationSpeed((simVehicleParticular*)vehicle,Shift,(simVehicleParticular*)vehicleLeader,ShiftLeader);
}else{
VelImpuesta=getGippsDecelerationSpeed((simVehicleParticular*)vehicle,Shift,(simVehicleParticular*)vehicleLeader,ShiftLeader,controlDecelMax,aside,time);
}
return VelImpuesta;
}
double behavioralModelParticular::computeMinimumGap(A2SimVehicle *vehicleUp,A2SimVehicle *vehicleDown,double Xup,double Vup,double Xdw,double Vdw,double Gap,bool ImprudentCase,bool VehicleIspVehDw)
{
double GapMin=0;
if (UseIDM){
GapMin=getIDMMinimumGap((simVehicleParticular*)vehicleUp,(simVehicleParticular*)vehicleDown,Vup, Vdw, Gap);
}else{
GapMin=getGippsMinimumGap((simVehicleParticular*)vehicleUp,(simVehicleParticular*)vehicleDown, Xup, Vup, Xdw, Vdw, Gap, ImprudentCase, VehicleIspVehDw);
}
return GapMin;
}
bool behavioralModelParticular::isVehicleGivingWay(A2SimVehicle *vehicleGiveWay, A2SimVehicle *vehiclePrio, yieldInfo *givewayInfo, int &Yield)
{
if (givewayInfo->isVehiclePrioWithinVisibility && (givewayInfo->isVehicleGiveWayComingNext || (!givewayInfo->isVehiclePrioRealAndReachingConflict && vehiclePrio->getSpeed(0)>0) || givewayInfo->isVehiclePrioLeaderOfVehicleGiveWay)){
//Vehicle is passing before Ceda arrives
//or
//Vehicle is fictitious or not coming to this conflict (and not stopped)
Yield=-1;
}else{
bool prioritaryComesNext = (givewayInfo->isVehiclePrioComingNext || givewayInfo->isVehiclePrioAffectedByStop || givewayInfo->isVehiclePrioAffectedByYellowBox || (givewayInfo->isVehiclePrioAffectedByGiveWay && !givewayInfo->isVehiclePrioPrioritaryBasedOnWaitingTime) ||((vehiclePrio->getSpeed(0)==0) && (givewayInfo->passingTimeVehicleGiveWay <= 0.0)));
if (givewayInfo->isVehiclePrioWithinVisibility && givewayInfo->isVehiclePrioRealAndReachingConflict && !prioritaryComesNext){
Yield=1;
}else{
//Vehicle not visible will not be considered!
//Vehicle not prioritary but stopped
//Ceda is Passing before Prioritary arrives
Yield=0;
}
}
return true;
}
A2SimVehicle * behavioralModelParticular::arrivalNewVehicle( void *handlerVehicle, unsigned short idHandler, bool isFictitiousVeh, unsigned int vehTypeId)
{
simVehicleParticular * res = new simVehicleParticular( handlerVehicle, idHandler, isFictitiousVeh, vehTypeId );
if (!isFictitiousVeh) {
res->setnewAttribute(2);
}
return res;
}
void behavioralModelParticular::removedVehicle( void *handlerVehicle, unsigned short idHandler, A2SimVehicle * a2simVeh )
{
}
//Gipps
double behavioralModelParticular::getGippsAccelerationSpeed(simVehicleParticular *vehicle,double VelActual,double VelDeseada, double RestoCiclo)
{
double X=VelActual / VelDeseada;
double VelPropia = min(VelDeseada, VelActual + 2.5 * vehicle->getAcceleration() * RestoCiclo * (1.0 - X)*sqrt( 0.025 + X));
if (VelPropia<VelActual){
VelPropia=max(VelPropia,max(0.,VelActual + (0.5 * vehicle->getDeceleration() * RestoCiclo)));
}
return VelPropia;
}
double behavioralModelParticular::getGippsDecelerationSpeed(simVehicleParticular *vehicle,double Shift,simVehicleParticular *leader,double ShiftLeader,bool controlDecelMax,bool aside,int time)
{
double PosAnterior,VelAnterior,PosAnteriorLeader,VelAnteriorLeader;
double GapAnterior=vehicle->getGap( Shift, leader, ShiftLeader, PosAnterior, VelAnterior, PosAnteriorLeader, VelAnteriorLeader,time);
double RT=vehicle->getReactionTime();
double DecelEstimada=0;
if (VelAnteriorLeader>Tolerancia){
DecelEstimada=vehicle->getEstimationOfLeadersDeceleration(leader,VelAnteriorLeader);
}
double bn=vehicle->getDeceleration();
double bnTau=bn*RT;
double VelImpuesta=bnTau;
double factorSqrt=0;
if(VelAnteriorLeader<Tolerancia){
factorSqrt = (bnTau* bnTau) - vehicle->getDeceleration() * (2.0 * GapAnterior - (VelAnterior * RT));
}else if (VelAnteriorLeader<DBL_MAX){
factorSqrt = (bnTau * bnTau) - vehicle->getDeceleration() * (2.0 * GapAnterior - (VelAnterior * RT) - ((VelAnteriorLeader * VelAnteriorLeader)/ DecelEstimada));
}else{
VelImpuesta = DBL_MAX;
}
if (factorSqrt>0){
VelImpuesta = bnTau + (double) sqrt(factorSqrt);
}
if (aside){
//SpeedAnterior imposed by Car-Following on side lane > Tolerancia to avoid RT at stop
double GapMin=getGippsMinimumGap(vehicle, leader, PosAnterior, VelAnterior, PosAnteriorLeader, VelAnteriorLeader, GapAnterior, false, false);
GapMin=GapAnterior-GapMin;
if (GapMin<0){
double Distance2Obstacle=DBL_MAX;
if (vehicle->getObstacleType()!=eNone){
Distance2Obstacle=vehicle->getDistance2Obstacle()/abs(vehicle->getNbLaneChanges2ReachNextValidLane());
Distance2Obstacle=max(0.,Distance2Obstacle-max(VelAnteriorLeader*RT, leader->getLength()));
}
double minimo = Distance2Obstacle;
double AdaptationDistance=max(vehicle->getFreeFlowSpeed()*RT,vehicle->getLength());
if (vehicle->getObstacleType()==eOnRamp){
minimo = min(minimo,3*AdaptationDistance);
}else{
minimo = min(minimo,AdaptationDistance);
}
double maximo = max(VelAnteriorLeader,Tolerancia);
double expParam = 0.5*(1.-VelAnterior/maximo*(1-(GapMin)/minimo));
double expValue = (float)exp( expParam );
VelImpuesta = VelAnterior*expValue;
}
}
if (controlDecelMax){
double VelMin=0;
if (aside){
VelMin=max(0.,VelAnterior+vehicle->getDeceleration()*RT);
}else{
VelMin=max(0.,VelAnterior+vehicle->getDecelerationMax()*RT);
}
if (VelImpuesta<VelMin){
VelImpuesta=VelMin;
}
}
return VelImpuesta;
}
double behavioralModelParticular::getGippsMinimumGap(simVehicleParticular* pVehUp,simVehicleParticular* pVehDw,double Xup,double Vup,double Xdw,double Vdw,double Gap,bool ImprudentCase,bool VehicleIspVehDw)
{
double DecelFactorUp=1;
if (VehicleIspVehDw){
DecelFactorUp=pVehDw->getDecelerationVariationFactor(ImprudentCase);
}else{
DecelFactorUp=pVehUp->getDecelerationVariationFactor(ImprudentCase);
}
double tau=pVehUp->getReactionTime();
double GapMin=0;
if (Vdw<0.01){
GapMin=max(0.,0.5*Vup*tau+max(0.,-Vup*Vup/(2*pVehUp->getDeceleration())+DecelFactorUp*(1.-0.5*DecelFactorUp)*pVehUp->getDeceleration()*tau*tau+(1-DecelFactorUp)*Vup*tau));
if (DecelFactorUp>-Vup/(pVehUp->getDeceleration())*tau){
GapMin=max(0.,0.5*Vup*tau);
}
}else{
double DecelEstimada=pVehUp->getEstimationOfLeadersDeceleration(pVehDw,Vdw);
GapMin=max(0.,(Vdw*Vdw)/(2*DecelEstimada)+0.5*Vup*tau+max(0.,-Vup*Vup/(2*pVehUp->getDeceleration())+DecelFactorUp*(1.-0.5*DecelFactorUp)*pVehUp->getDeceleration()*tau*tau+(1-DecelFactorUp)*Vup*tau));
if (DecelFactorUp>-Vup/(pVehUp->getDeceleration())*tau){
GapMin=max(0.,(Vdw*Vdw)/(2*DecelEstimada)+0.5*Vup*tau);
}
}
return GapMin;
}
double behavioralModelParticular::getIDMAccelerationSpeed(simVehicleParticular *vehicle,double VelActual,double VelDeseada, double RestoCiclo)
{
double X=VelActual/VelDeseada;
double acceleration=max(vehicle->getDeceleration(),vehicle->getAcceleration()*(1.-pow(X,4)));
double speed=max(0.,VelActual+acceleration*RestoCiclo);
return speed;
}
double behavioralModelParticular::getIDMDecelerationSpeed(simVehicleParticular *vehicle,double Shift,simVehicleParticular *leader,double ShiftLeader)
{
double a=vehicle->getAcceleration();
double VelAnterior,PosAnterior,VelAnteriorLeader,PosAnteriorLeader;
double GapAnterior=vehicle->getGap(Shift,leader,ShiftLeader,PosAnterior,VelAnterior,PosAnteriorLeader,VelAnteriorLeader);
double DesiredGap=getIDMMinimumGap(vehicle,leader,VelAnterior,VelAnteriorLeader, GapAnterior);
double X=VelAnterior/vehicle->getFreeFlowSpeed();
double acceleration=a*(1-pow(X,4)-(DesiredGap/GapAnterior)*(DesiredGap/GapAnterior));
double speed=max(0.,VelAnterior+acceleration*getSimStep());
return speed;
}
double behavioralModelParticular::getIDMMinimumGap(simVehicleParticular* pVehUp,simVehicleParticular* pVehDw,double VelAnterior,double VelAnteriorLeader,double GapAnterior)
{
double a=pVehUp->getAcceleration();
double b=-pVehUp->getDeceleration();
double DesiredGap=pVehUp->getMinimumDistanceInterVeh()+max(0.,VelAnterior*pVehUp->getMinimumHeadway()+VelAnterior*(VelAnteriorLeader-VelAnterior)/(2*sqrt(a*b));
return DesiredGap;
}
bool behavioralModelParticular::avoidCollision(A2SimVehicle *vehicle,A2SimVehicle *vehiclePre,double ShiftPre)
{
return false;
}
Contents of the XML, located in /ProgramFiles/Aimsun/Aimsun Next X.X/plugins/
>plugin<
>name<behavioralModelParticular>/name<
>lib<behavioralModelParticular>/lib<
>/plugin<