Skip to content

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/

&gt;plugin&lt;
    &gt;name&lt;behavioralModelParticular&gt;/name&lt;
    &gt;lib&lt;behavioralModelParticular&gt;/lib&lt;
&gt;/plugin&lt;