/*!
\file
\brief Traffic Light Agents
\author Vaclav Smidl.
*/
#ifndef TRAGE_H
#define TRAGE_H
#include
using namespace bdm;
class BaseTrafficAgent;
//! detector of traffic variables
class Lane{
public:
Array inputs;
Array outputs;
vec input_distances;
vec output_distances;
vec alpha; //size of outputs
//! percent of queue lenght (for "multiline queues")
double beta;
string queue;
string sg;
//! function loading info from Setting
void from_setting(const Setting &set){
UI::get(inputs,set,"inputs",UI::compulsory);
UI::get(outputs,set,"outputs",UI::compulsory);
UI::get(input_distances,set,"input_distances",UI::compulsory);
UI::get(output_distances,set,"output_distances",UI::compulsory);
UI::get(alpha,set,"alpha",UI::compulsory);
UI::get(queue,set,"queue",UI::compulsory);
UI::get(sg,set,"sg",UI::compulsory);
UI::get(beta, set, "beta");
}
};
//! class that operates on a signal group
class LaneHandler {
protected:
//! pointer to physical lane
const Lane &lane;
//! agent pointer
BaseTrafficAgent *agent;
public:
//! actual data from the relevant signal group
vec inputs;
//! queue length
double queue;
//! description of det_data
RV rv_inputs;
//! description of det_data
RV rv_outputs;
//! description of det_data
RV rv_queue;
//! link from global measured data
datalink agentin2input;
//!
datalink output2agentout;
//!
int queue_index;
public:
LaneHandler(const Lane &lane0): lane(lane0){
for (int i=0;i 0 ) return x;
else return -x;
}*/
void echo () {
//cout << "n:" << n_of_queues_in_length << " " << getQueueName() << " q:" << getQueue() << " aq:" << getAverageQueueLength() << " diff:" << getAverageQueueGrow() << " D:" << getQueueVariance() << endl;
/*cout << "n:" << n_of_queues_in_length
<< " " << getQueueName()
<< "LAST aq:" << last_sum_queue_length/last_n_of_queues_in_length
<< " aq:" << getAverageQueueLength()
<< " diff" << getAverageQueueLength() - last_sum_queue_length/last_n_of_queues_in_length
<< endl;*/
cout << getQueueName();
/*if ( last_n_of_queues_in_length> 0 && n_of_queues_in_length > 0 )
cout << " DIFF: " << getAverageQueueLength() - last_sum_queue_length/last_n_of_queues_in_length;
else
cout << " no diff available";*/
//cout << "\tn " << n_of_queues_in_length;
//cout << " prijizdejicich aut za 90: " << getRo()*90;
cout << "\tgtr: " << green_time_ratio;
cout << "\tRo: " << getRo();
cout << "\tC: " << green_time_ratio*Tc*saturated_stream - getRo()*Tc << endl;
//cout << "\tWT:";
for ( int i = -2; i <= 2; i++ ) {
double tc = Tc + i*8;
cout << tc << "\t";
}
cout << endl;
for ( int i = -2; i <= 2; i++ ) {
double tc = Tc + i*8;
cout << (int)(100*getWT(tc)) << "\t";
}
//cout << " diff: " << getRo()*Tc - saturated_stream*getGreenTime();
/*if ( saturated_stream*getGreenTime() >= getAverageQueueLength() )
cout << " projede vsechno ";
else
cout << " zustanou auta ";*/
cout << endl << endl;
}
Lane getLane () {
return lane;
}
string getSG () {
return lane.sg;
}
string getQueueName () {
return lane.queue;
}
double getQueue() {
return queue_avg;
}
void addQueueLength ( int ql ) {
// pricita pouze namerene udaje
if ( ql >= 0 ) {
last_queue = queue;
queue = ql;
queue_diff_sum += queue - last_queue;
//queue_variance_sum += abs(queue - last_queue);
sum_queue_length += ql;
n_of_queues_in_length ++;
// KALMAN
cout << endl << "pridani fronty\t" << queue_avg << "\t" << ql << endl;
queue_avg += queue_w*( ql - queue_avg );
queue_d += queue_dd;
queue_w = queue_d/(queue_d+1);
queue_d = (1-queue_w)*queue_d;
double Ro = getActualRo();
Ro_avg += Ro_w*( Ro - Ro_avg );
Ro_d += Ro_dd;
Ro_w = Ro_d/(Ro_d+1);
Ro_d = (1-Ro_w)*Ro_d;
}
}
void resetQueue () {
last_Tc = Tc;
//last_variance = getQueueVariance();
last_n_of_queues_in_length = n_of_queues_in_length;
last_sum_queue_length = sum_queue_length;
n_of_queues_in_length = 0;
sum_queue_length = 0;
queue_variance_sum = 0;
queue_diff_sum = 0;
// kalman
last_queue_avg = getAverageQueueLength();
}
double getAverageQueueLength () {
// kalmam
return queue_avg;
if( n_of_queues_in_length > 0 )
return sum_queue_length / n_of_queues_in_length;
else
return 0.0;
}
double getLastAverageQueueLength () {
if( last_n_of_queues_in_length > 0 )
return last_sum_queue_length / last_n_of_queues_in_length;
else
return 0.0;
}
/*double getAverageQueueGrow () {
return queue_diff_sum / n_of_queues_in_length;
}*/
/*double getQueueVariance () {
return queue_variance_sum / n_of_queues_in_length;
}*/
double getGreenTime ( double tc ) { return green_time_ratio * tc - delta; }
double getGreenTime () { return getGreenTime( Tc ); }
double getRedTime ( double tc ) { return (1-green_time_ratio) * tc; }
double getRedTime () { return getRedTime( Tc ); }
double getRelativeQueueDiff () {
if ( last_n_of_queues_in_length > 0 && n_of_queues_in_length > 0 ) {
return getAverageQueueLength()/(Tc*(1-green_time_ratio)) - (last_sum_queue_length/last_n_of_queues_in_length)/(last_Tc*(1-green_time_ratio));
}
else
return 0;
}
// hodnotici funkce - suma cekaciho casu aut za 10h
double getWT ( double Tc ) {
double T = 36000; // celkovy cas 10h
double Ro = getRo();
double Gr = green_time_ratio;
double ss = saturated_stream;
double WT = 0;
double q = 0; // zacina s nulovou frontou ?
double ti = 0;
double sumq = q;
while ( ti < T ) {
// ve fronte stoji vic aut nez je schopno odjet za zelenou
if ( q > 0.5*ss*Tc ) {
WT += 0.5*ss*(Tc*Gr - delta)*(Tc*Gr - delta);
}
else {
WT += 0.5*q*(Tc*Gr - delta);
}
if ( (Tc*Gr - delta)*ss < q )
q -= (Tc*Gr - delta)*ss;
else
q = 0;
WT += q * Tc; // zbytek fronty ceka cely cyklus
// cekani vozidel, ktera prijela za pocitany cyklus
if ( q > 0 ) {
//pokud je fronta > 0, auta cekaji prumerne polovinu delky cyklu
WT += Ro*Tc*0.5*Tc;
}
else {
// pokud je fronta = 0 cekaji pouze auta, ktera prijela na cervenou (p=(1-Gr)) 0.5Tc(1-Gr)
WT += Ro*(1-Gr)*Tc*0.5*(1-Gr)*Tc;
}
// fronta se zvetsi o Ro*Tc
q += Ro*Tc;
sumq += Ro*Tc;
ti += Tc;
}
//return WT;
if ( sumq > 0 )
return 100*(WT/(0.5*T*sumq));
else
return 0;
}
//double getWT ( double tc ) {
// double T = ;
// double WT = 0;
// double cWT = 0;
// double q = 0;
// double cq = 0;
// double sum_t;
// double car_part = 0.1;
// double Ro = getRo();
// double dt = car_part/Ro;
// while ( sum_t < T ) {
// if ( q < 0 )
// q = 0;
// WT += q * dt;
// // prirustek fronty za dt
// q += car_part;
// // zelena - auta projedou
// if ( (sum_t - tc*(int)(sum_t/tc)) > delta && )
// q -= saturated_stream*dt;
// sum_t += dt;
// }
//}
// Odhad hustoty ( auto/sec )
double getActualRo () {
// pokud delka fronty mensi nez pocet aut ktere odjedou za zelenou
if ( saturated_stream*getGreenTime() >= getAverageQueueLength() ) {
// pocet aut, ktera prijela pri cervene
return getAverageQueueLength()/getRedTime();
}
else {
//fronta se nevynuluje
// pocet aut = to co stihlo projet na zelenou + o co narostla fronta
// doba pocet_cyklu*90
//double T = n_of_queues_in_length*90;
//double cars_per_green = T*(getGreenTime()/Tc)*saturated_stream;
//return (cars_per_green + queue_diff_sum)/T;
double T = 90;
double cars_per_green = T*(getGreenTime()/Tc)*saturated_stream;
return (cars_per_green + (getLastAverageQueueLength()-getAverageQueueLength()))/T;
}
}
double getRo() {
return Ro_avg;
}
/***************************************
* KONEC KODU PRO TrafficAgentCycleTime *
****************************************/
};
/*!
\brief Basic Traffic Agent
*/
class BaseTrafficAgent : public Participant {
LOG_LEVEL(BaseTrafficAgent,logdata);
public:
//! Signal Groups
Array lanes;
Array lanehs;
//!data from messages
vec inputs;
//! decription of msg_data
RV rv_inputs;
//! data to broadcast
vec outputs;
//! description of broadcast dataind
RV rv_outputs;
vec queues;
//! description of queues
RV rv_queues;
//!
vec green_starts;
//!
vec green_times;
//!
Array green_names;
//!
Array stage_names;
//!
vec stage_times;
//! datalink from DS to input variables
datalink ds2inputs;
//! datalink from DS to output variables
datalink ds2queues;
//! action description
RV rv_action;
datalink_part action2ds;
Array neighbours;
Array rv_neighbours_out;
Array output2neighbour;
//! simulator's step length in seconds
static const int step_length=90;
//! lenght of cycle in seconds
static const int cycle_length=80;
public:
void validate(){
lanehs.set_length(lanes.length());
for (int l=0; lrv_inputs);
rv_outputs.add(lanehs(l)->rv_outputs);
rv_queues.add(lanehs(l)->rv_queue);
}
inputs.set_size(rv_inputs._dsize());
outputs.set_size(rv_outputs._dsize());
queues.set_size(rv_queues._dsize());
for (int l=0; lconnect_data(*this);
}
//for -- rv_outputs --
// TODO vybrat rv pro sousedy
rv_neighbours_out.set_length(neighbours.length());
output2neighbour.set_length(neighbours.length());
for (int i=0; i(int)neighbours(i).length()){
rv_neighbours_out(i).add(rv_outputs.subselect(vec_1(r)));
}
}
// connect datasource
output2neighbour(i).set_connection(rv_neighbours_out(i), rv_outputs);
}
// lanehs knows RVS
// write internal checks if all was loaded OK
}
void receive(const Setting &msg){
string what;
UI::get(what, msg, "what", UI::compulsory);
if (what=="new_stable_state"){ //
// field data
// extract decription of teh received datavector
shared_ptr rv=UI::build(msg,"rv",UI::compulsory);
// find if it is needed
ivec ind=rv->dataind(rv_inputs); // position of rv in in_rv;
if (ind.length()>0){ //data are interesting
vec dt;
UI::get(dt, msg, "value",UI::compulsory); // get data
set_subvector(inputs, ind, dt); //check size?
}
} else {
Participant::receive(msg);
}
}
void log_register(logger &L, const string &prefix){
root::log_register ( L, prefix );
if ( log_level[logdata]){
L.add_vector ( log_level, logdata, RV ( 1 ), prefix );
}
}
void log_write() const {
if (log_level[logdata]){
log_level.store(logdata, inputs);
}
}
void broadcast(Setting& set){
// broadcast data to all neighbours
for (int i=0; i