/*! \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 << getQueueName(); 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 << 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 ) { queue_last = queue; queue = ql; queue_avg_last = queue_avg; // KALMAN //cout << endl << "pridani fronty\t" << queue_avg << "\t" << ql << endl; queue_avg += queue_w*( ql - queue_avg ); /*cout << getQueueName() << " inputs"; int k = 0; for ( int i = 0; i < rv_inputs.length(); i ++ ) { cout <<"\t"<< rv_inputs.name(i) << ": "; for ( int j = 0; j < rv_inputs.size(i); j ++ ) { cout << inputs(k) << " "; k ++; } cout << endl;*/ } if ( inputs(0) >= 0 ) { cars_in_avg += cars_in_w*( inputs(0) - cars_in_avg ); } if ( cars_in_avg > 0 && queue_avg_last > saturated_stream*last_Tc*green_time_ratio ) { //double delta_d = queue_avg - queue_avg_last + last_Tc * saturated_stream - cars_in_avg*(double)last_Tc/90; double delta_d = ( last_Tc/(90*saturated_stream)) * (cars_in_avg - queue_avg + queue_avg_last) - green_time_ratio; delta += delta_w * ( delta_d - delta ); if ( delta < 0 ) delta = 0; } cout << getQueueName() << " cars in: " << inputs(0) << " " << cars_in_avg << " q_avd: " << queue_avg << " delta: " << delta << endl; } double getAverageQueueLength () { // kalmam return queue_avg; } double getLastAverageQueueLength () { return queue_avg_last; } /*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 ); } // hodnotici funkce - suma cekaciho casu aut za 10h //double getWT_old ( 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; //} // stredni doba prujezdu n-teho auta ve fronte double getEcarWT ( const double tc, const int n ) { double cpg = (tc * green_time_ratio - delta) * saturated_stream; // cars per green time double wc = floor( n / cpg ); // number of waiting cycles double ET_last_cycle = ( 1/ (2*tc) ) * ( tc*(1-green_time_ratio) + (n-wc*cpg)/saturated_stream )*( tc*(1-green_time_ratio) + (n-wc*cpg)/saturated_stream ); double ET = wc*tc + ET_last_cycle; return ET; } // suma strednich hodnot cekacich casu pres auta ve fronte double getWT ( const double tc ) { double sumEWT = 0; //int n = round(getAverageQueueLength()); int n = round(cars_in_avg + getAverageQueueLength()); for ( int i = 0; i <= n; i ++ ) { sumEWT += getEcarWT( tc, i ); } return sumEWT; } //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