root/applications/doprava/aimsun_bdm/aimsun_ds.cpp @ 1029

Revision 1029, 22.3 kB (checked in by prikryl, 14 years ago)

Removed fake queues 495_Q1, 495_Q2, 601_Q1, and 601_Q2.

Line 
1/*
2 */
3
4/* Class definition */
5#include "aimsun_ds.h"
6#include "tools.h"
7
8// TODO: reference additional headers your program requires here
9#include <process.h>
10#include <strsafe.h>
11#include <shlwapi.h>
12#include <io.h>
13
14//#include <atlbase.h>
15
16#define MAX_PATH_BYTES  (MAX_PATH*sizeof(TCHAR))
17#define MAX_EXE_BYTES   (MAX_EXE_PATH*sizeof(TCHAR))
18
19/* Contoller list is hardwired for Aimsun scenario `zlicin_495_601.sce` */
20#define NUM_CONTROLLERS 2
21const TCHAR * ControllerList[NUM_CONTROLLERS] = { TEXT("K_5_495"), TEXT("K_5_601") };
22const TCHAR * WindowStr[NUM_CONTROLLERS]      = { TEXT("els3@5.495"), TEXT("els3@5.601") };
23const int IntersectionIDs[] = { 495, 601 };
24const int NumLanes[] = { 6, 6 };
25const int NumIntersections = sizeof ( IntersectionIDs )/sizeof(int);
26
27/* Entrance sections are hardwired for Aimsun scenario `zlicin_495_601.sce` */
28const int EntranceSections[] = { 1, 42, 45, 287, 26 };
29const int NumEntranceSections = sizeof(EntranceSections)/sizeof(int);
30
31/* Identifiers of sections that Aimsun shall collect statistics for are also
32   hardwired for the scenario `zlicin_495_601.sce`. */
33const int StatIds[] = {
34        1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
35        26, 27, 35, 28, 29, 30, 31, 32, 33, 34, 39, 36, 37, 38, 21, 22, 23, 24, 25, 40,
36        42, 43, 44, 45, 49, 46, 47, 50, 51, 287, 288, 54, 55, 56, 57, 58, 59, 60, 61,
37        62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77 };
38const int NumStatIds = sizeof(StatIds)/sizeof(int);
39
40const int LaneQueuesSectIds[] = {
41        1,      2,      3,      6,      7,
42        3,      4,      5,
43        35,     28,     32,     33,     34,
44        26,     27,     35,     28,     29,     30,     31,
45        16,     17,     18,     19,     20,     14,     15,
46        16,     17,     18,     19,     20,     12,     13,
47        21,     22,     23,     24,     25,     40,
48        21,     22,     23,     24,     25,     40,
49        61,     62,     63,     64,     65,
50        287,288,54,     55,     56,     57,     58,     59,     60,     61,     62,     63,     64,     65,
51        45,     49,     51,
52        45,     49,     50,
53        43,     44,
54        43,     44,     42 };
55const int NumLaneQueuesSectIds = sizeof(LaneQueuesSectIds)/sizeof(int);
56
57/* This array contains offsets of particular lanes stored in LaneQueuesSectIds,
58   plus the would-be offset of the next non-existent lane (this is used to
59   set the limits of the index when extracting statistical data from the
60   section_stats structure). */
61int LaneQueueOffsets[] = {
62        0, 5, 8, 13, 20, 27,
63        34, 40, 46, 51, 65, 68, 70, 72, NumLaneQueuesSectIds+1 };
64
65/* The position of the statistics is given by the indices in the StatIds
66   array. In order to parse the statistics correctly we have to create
67   a copy of LaneQueuesSectIds holding indices to the StatIds array instead
68   of the original section ids. */
69int * LaneQueuesStatPos;
70
71const int LaneQueuesLaneIds[] = {
72        1,      1,      2,      1,      1,
73        1,      1,      1,
74        2,      2,      1,      1,      1,
75        1,      1,      1,      1,      1,      1,      1,
76        2,      2,      2,      2,      2,      1,      1,
77        1,      1,      1,      1,      1,      1,      1,
78        2,      2,      2,      2,      2,      2,
79        1,      1,      1,      1,      1,      1,
80        2,      2,      2,      2,      2,
81        1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,      1,
82        2,      2,      1,
83        1,      1,      1,
84        2,      2,
85        1,      1,      1 };
86
87
88const TCHAR * PatternsELS3[] = { TEXT("GetramELS3.dll"), TEXT("GetramELS3d.dll") };
89const TCHAR * PatternsVGS[] = { TEXT("GetramVGS.dll"), TEXT("GetramVGSd.dll") };
90
91/* Offsets of `dt` components (dt is the vector returned by AimsunDS, it contains composite
92   values of all measurements for all intersections in the system). */
93const int SignalPlanOffsets[]  = {  0, 42 };
94const int QueueLengthOffsets[] = {  6, 48 };
95const int MeasurementOffsets[] = { 12, 54 };
96
97AimsunDS::AimsunDS () : DS()
98{
99  /* Description of the channels of the data vector. */
100  Drv = RV ( "{"
101    "495_VA  495_VB   495_VC   495_VD   495_VE   495_VF "
102    "495_QA  495_QB   495_QC   495_QD   495_QE   495_QF "
103    "495_DVA 495_DVB  495_DVA1 495_DVB1 495_DVC  495_DVD  495_DVE  495_DVF  495_DVF1 "
104    "495_S1  495_S2   495_S3   495_S4   495_S5   495_S5a "
105    "601_VA  601_VB   601_VC   601_VD   601_VE   601_SE "
106    "601_QA  601_QB   601_QC   601_QD   601_QE   601_QSE "
107        "601_DVA 601_DVAa 601_DVB  601_DVBa 601_DVB1 601_DVC  601_DVD  601_DVD1 601_DSE 601_DVE 601_DSE1 601_DVE1 "
108    "601_S6  601_S6a  601_S7   601_S8   601_S9   601_S9a "
109    "}",
110        "    1,      1,      1,      1,      1,       1,      "
111        "    1,      1,      1,      1,      1,       1,      "
112        "    2,      2,      2,      2,      2,       2,      2,      2,      2,"
113        "    2,      2,      2,      2,      2,       2,"
114        "    1,      1,      1,      1,      1,       1,      "
115        "    1,      1,      1,      1,      1,       1,      "
116        "    2,      2,      2,      2,      2,       2,       2,       2,       2,       2,       2,       2,"
117        "    2,      2,      2,      2,      2,       2"
118        );
119  /* Remember the size of the data vector. */
120  dtsize = Drv._dsize();
121
122  /* Description of the channels of the input vector. */
123  Urv = RV ( "{"
124          "Tc"
125          "495_offset"
126          "495_VA  495_VB   495_VC   495_VD   495_VE   495_VF "
127          "601_offset"
128          "601_VA  601_VB   601_VC   601_VD   601_VE   601_SE "
129          "}" );
130  /* Remember the size of the input vector. */
131  utsize = Urv._dsize();
132
133  /* Initialise the pointer to received data. */
134  p_rsp = NULL;
135}
136
137void AimsunDS::from_setting ( const Setting &cfg )
138{
139        /* Check the `stop time` field in configuration. */
140        UI::get ( stopTime, cfg, "stop_time" );
141
142        /* Query the configuration file for the name of the file containsing
143           vehicle entrances. */
144        UI::get ( entranceFileName, cfg, "entrances" );
145}
146
147void AimsunDS::validate ()
148{
149        HKEY  hKey;
150        TCHAR szBasePath[MAX_PATH];             /**< Base path of the whole application, root of the tree. */
151        TCHAR szDllPath[MAX_PATH];              /**< Directory where all DLLs reside. Will be added to PATH. */
152        TCHAR szSceDllPath[MAX_PATH];   /**< Temporary storage for DLL path rewritten in the scenario file. */
153        TCHAR szSceDir[MAX_PATH];               /**< Directory of the simulated scenario. */
154        TCHAR szScePath[MAX_PATH];              /**< Full path to the Aimsun scenario file. The file resides in `szSceDir`. */
155        TCHAR szScePathA[MAX_PATH];
156        TCHAR szScePathB[MAX_PATH];
157        TCHAR szScePathC[MAX_PATH];
158        TCHAR szNetPath[MAX_PATH];
159        TCHAR szHomeDir[MAX_PATH];              /**< Installation directory of Aimsun 4.2.x */
160        TCHAR szELS3Path[MAX_PATH];             /**< Full path of the simulator of ELS3 controller. */
161        TCHAR szExePath[MAX_EXE_PATH];  /**< Command line when staring ELS3 controllers. */
162        TCHAR szEntrancePath[MAX_PATH]; /**< Points to the CSV file with vehicle entrances for the simulation. */
163        DWORD dwBufLen = MAX_PATH_BYTES;
164        LONG  res;
165
166        intptr_t hPid;
167
168        int verIndex = 1; //@TODO@: 0 is for release, 1 for debug build of the DLL libraries.
169
170        /* The root directory of the simulator tree is defined externally
171           in "CMakeLists.txt". */
172        StringCbCopy ( szBasePath, MAX_PATH_BYTES, BASE_PATH );
173
174        /* Create the path to DLL directory. The path is defined externally
175           in  "CMakeLists.txt".
176           The path will be used to inject the appropriate location of
177           Getram extensions into the selected Aimsun scenario and also
178           to modify PATH variable of executed processes in order to
179           provide access to API DLLs. */
180        StringCbCopy ( szDllPath, MAX_PATH_BYTES, DLL_PATH );
181
182        /* Add the DLL directory to the PATH used by this process.
183           The PATH will be passed to all other processes started
184           by this one and hence they will be able to find API
185           DLLs. */
186        _addpath ( szDllPath );
187
188#ifdef LATER_OR_NEVER
189        GetPrivateProfileString (
190                TEXT("paths"),
191                TEXT("base"),
192                NULL,
193                szBasePath,
194                MAX_PATH,
195                TEXT(".\\simulate.ini")
196                );
197#endif
198
199        /* Find the location of Aimsun executable. It is stored in registry tree as
200           \\HKEY_LOCAL_MACHINE\SOFTWARE\TSS-Transport Simulation Systems\GETRAM\4.2.0 */
201        res = RegOpenKeyEx (
202                HKEY_LOCAL_MACHINE,
203                TEXT("SOFTWARE\\TSS-Transport Simulation Systems\\GETRAM\\4.2.0"),
204                0,
205                KEY_QUERY_VALUE,
206                &hKey
207                );
208        if ( res != ERROR_SUCCESS )
209        {
210                perror ( "Cannot get handle to Aimsun registry entry" );
211                return;
212        }
213
214        /* The executable location is `HomeDir` key. */
215        res = RegQueryValueEx (
216                hKey,
217                TEXT("HomeDir"),
218        NULL, NULL,
219                (LPBYTE) szHomeDir,
220                &dwBufLen
221                );
222        RegCloseKey( hKey );
223    if (( res != ERROR_SUCCESS ) || ( dwBufLen > MAX_PATH_BYTES ))
224        {
225                perror ( "Cannot read the Aimsun home directory from registry" );
226        return;
227        }
228
229        /* Concatenate the home path with the executable name. */
230        StringCbCat ( szHomeDir, MAX_PATH_BYTES, TEXT("\\aimsun42.exe") );
231
232        /* Create the version of home path including the quotation marks. */
233        StringCbCopy ( szExePath, MAX_EXE_PATH, TEXT("\"") );
234        StringCbCat ( szExePath, MAX_EXE_PATH, szHomeDir );
235        StringCbCat ( szExePath, MAX_EXE_PATH, TEXT("\"") );
236
237        /* Create the path to ELS3 executable. */
238        StringCbCopy ( szELS3Path, MAX_PATH_BYTES, TEXT("\"") );
239        StringCbCat ( szELS3Path, MAX_PATH_BYTES, szBasePath );
240        StringCbCat ( szELS3Path, MAX_PATH_BYTES, TEXT("\\els3\\els3sample.exe\"") );
241
242        /* Aimsun scenario modification.
243           We have to take care of items that are specified by absolute
244           paths in the scenario file. These items include:
245           - network path (section #NETWORK),
246           - ELS3 Getram extension DLL (section #EXTENSIONS),
247           - VGS Getram extension DLL (section #EXTENSIONS).
248
249           We will start with constructing the new network path.*/
250        StringCbCopy ( szSceDir, MAX_EXE_PATH, szBasePath );
251        StringCbCat ( szSceDir, MAX_EXE_PATH, TEXT("\\scenarios\\zlicin_495_601") );
252        StringCbCopy ( szNetPath, MAX_EXE_PATH, szSceDir );
253        StringCbCat ( szNetPath, MAX_EXE_PATH, TEXT("\\zlicin_495_601") );
254
255        /* Our convention is that the scenario file name corresponds
256           to the network path name. */
257        StringCbCopy ( szScePath, MAX_EXE_PATH, szNetPath );
258        StringCbCat ( szScePath, MAX_EXE_PATH, TEXT(".sce") );
259
260        /* First modification step: Replace the location of ELS3 Getram
261           extension.
262           Start with constructing full path to the extension DLL.*/
263        StringCbCopy ( szSceDllPath, MAX_EXE_PATH, szDllPath );
264        StringCbCat ( szSceDllPath, MAX_EXE_PATH, TEXT("\\") );
265        StringCbCat ( szSceDllPath, MAX_EXE_PATH, PatternsELS3[verIndex] );
266        /* We are not allowed to modify scenario in place (it is part
267           of SVN snapshot and we do not want our local changes to
268           propagate to the trunk with every commit). Therefore we
269           need an alternative scenario name that will be constructed
270           now. */
271        StringCbCopy ( szScePathA, MAX_EXE_PATH, szScePath );
272        StringCbCat ( szScePathA, MAX_EXE_PATH, TEXT(".a") );
273        /* And do the replacements. */
274        replace_in_scenario (
275                szScePath, szScePathA,
276                TEXT("#EXTENSIONS"),
277                PatternsELS3,
278                2,
279                szSceDllPath
280                );
281
282        /* Second modification step.
283           Replace the location of VGS Getram extension. */
284        StringCbCopy ( szSceDllPath, MAX_EXE_PATH, szDllPath );
285        StringCbCat ( szSceDllPath, MAX_EXE_PATH, TEXT("\\") );
286        StringCbCat ( szSceDllPath, MAX_EXE_PATH, PatternsVGS[verIndex] );
287        StringCbCopy ( szScePathB, MAX_EXE_PATH, szScePath );
288        StringCbCat ( szScePathB, MAX_EXE_PATH, TEXT(".b") );
289        replace_in_scenario (
290                szScePathA, szScePathB,
291                TEXT("#EXTENSIONS"),
292                PatternsVGS,
293                2,
294                szSceDllPath
295                );
296
297        const TCHAR * pattern_net[] = { TEXT("zlicin_495_601") };
298
299        /* Third modification step.
300           Replace the network path. */
301        StringCbCopy ( szScePathC, MAX_EXE_PATH, szScePath );
302        StringCbCat ( szScePathC, MAX_EXE_PATH, TEXT(".c") );
303        replace_in_scenario (
304                szScePathB, szScePathC,
305                TEXT("#NETWORK"),
306                pattern_net,
307                1,
308                szNetPath
309                );
310
311        /* Fourth modification step.
312           Replace the `stop time` field of RunTime information. */
313        replace_stoptime (
314                szNetPath,
315                stopTime.c_str()
316                );
317
318        //???
319        //StringCbCat ( szScePath, MAX_EXE_PATH, TEXT("\"") );
320        //StringCbCat ( szScePath, MAX_EXE_PATH, TEXT("\"") );
321
322        /* Spawn the process. */
323        hPid = _tspawnl (
324                _P_NOWAIT,
325                szHomeDir,
326                szExePath,
327                TEXT("-run"),
328                szScePathC,
329                NULL
330                );
331
332        if ( hPid < 0 )
333        {
334                perror ( "Cannot start Aimsun by _spawnl()" );
335                return;
336        }
337
338        /* Now that Aimsun is running, we need to start also the controllers. */
339        for ( int c = 0 ; c < NUM_CONTROLLERS ; c++ )
340        {
341                TCHAR szELS3Config[MAX_PATH];
342                szELS3Config[0] = 0;
343                StringCbCat ( szELS3Config, MAX_PATH_BYTES, TEXT("\"") );
344                StringCbCat ( szELS3Config, MAX_PATH_BYTES, szBasePath );
345                StringCbCat ( szELS3Config, MAX_PATH_BYTES, TEXT("\\els3\\configs\\") );
346                StringCbCat ( szELS3Config, MAX_PATH_BYTES, ControllerList[c] );
347                StringCbCat ( szELS3Config, MAX_PATH_BYTES, TEXT(".ini\"") );
348
349                /* Create the command line for the controller. */
350                szExePath[0] = 0;
351                StringCbCat ( szExePath, MAX_EXE_PATH, TEXT("start \"") );
352                StringCbCat ( szExePath, MAX_EXE_PATH, WindowStr[c] );
353                StringCbCat ( szExePath, MAX_EXE_PATH, TEXT("\" ") );
354                StringCbCat ( szExePath, MAX_EXE_PATH, szELS3Path );
355                StringCbCat ( szExePath, MAX_EXE_PATH, TEXT(" -a") );
356                StringCbCat ( szExePath, MAX_EXE_PATH, TEXT(" -l frm,det,spl") );
357                StringCbCat ( szExePath, MAX_EXE_PATH, TEXT(" -c 12.12.2007 00:00:00") );
358                StringCbCat ( szExePath, MAX_EXE_PATH, TEXT(" -f ") );
359                StringCbCat ( szExePath, MAX_EXE_PATH, szELS3Config );
360
361                /* Spawn the process. */
362                _tsystem ( szExePath );
363        }
364
365        /* Aaaaggggrrrrrhhhh!
366           C++ is much much faster than Matlab and we have a synchronisation
367           issue with els3 controllers starting too late. */
368        Sleep ( 5000 );
369
370
371        /* Prepare full path for vehicle input data. */
372        StringCbCopy ( szEntrancePath, MAX_EXE_PATH, szSceDir );
373        StringCbCat  ( szEntrancePath, MAX_EXE_PATH, TEXT("\\") );
374        StringCbCat  ( szEntrancePath, MAX_EXE_PATH, entranceFileName.c_str() );
375
376        /* Initialise and start the vehicle input.
377           The function call refers to delay-loaded DLL, so expect possible
378           complainst in case that the DLL canot be found in PATH. */
379        initVGS (
380                HEADWAY_UNIFORM,
381                szEntrancePath,
382                TEXT("sect_stats.csv"),
383                TEXT("glob_stats.csv")
384                );
385
386        /* Create LaneQueuesStatPos holding indices to the statistical data for the
387           sections listed in LaneQueuesSectIds in the same order. */
388        LaneQueuesStatPos = (int *) calloc ( NumLaneQueuesSectIds, sizeof(int));
389        for ( int i=0 ; i < NumLaneQueuesSectIds ; i++ )
390        {
391                int p = _search_index ( StatIds, NumStatIds, LaneQueuesSectIds[i] );
392                if ( p >= 0 )
393                {
394                        LaneQueuesStatPos[i] = p;
395                }
396                else
397                {
398                        fprintf ( stderr, "Cannot find index  LaneQueuesStatIds[%d]=%d in StatIds!\n",
399                                i, LaneQueuesSectIds[i] );
400                    exit(1);
401                }
402        }
403
404}
405
406void AimsunDS::initVGS (
407        const vgs_headway_mode headway,
408        const string &entrancePath,
409        const string &sectionStatsPath,
410        const string &globalStatsPath
411        )
412{
413    int res;
414       
415        /* Allocate space for the section statistics.
416           TODO: This is ugly. This should be part of VGS API. */
417        sections_stats.queues = (int*) calloc ( MAX_SECTS*MAX_LANES, sizeof(int) );
418        sections_stats.stats  = (vgs_se_stat_entry*) calloc ( MAX_SECTS, sizeof(vgs_se_stat_entry) );
419
420        /* Pass information about entrance sections to VGS API (and so to the
421       GetramVGS extension that will be generating vehicles for these
422           entrances). */
423    vgs_set_entrance_sections ( EntranceSections, NumEntranceSections );
424   
425    /* Check the validity of the headway mode. */
426    res = vgs_is_valid_headway_mode ( headway );
427    if ( !res )
428        {
429        fprintf ( stderr, "Invalid headway mode '%d'\n", headway );
430                exit ( -1 );
431        }
432   
433    /* Specify where to find the CSV with vehicle entrances and which
434           headway mode to use for generating vehicle flows. */
435        vgs_generate_vehicles ( entrancePath.c_str(), headway );
436   
437    /* Pass to VGS API information about section identifiers we want to
438       collect statistics for (and VGS will pass it to the GetramVGS
439       extension). */ 
440        vgs_set_stats_sections ( StatIds, NumStatIds );
441   
442    /* Specify where to store CSV files with statistical data. */
443        vgs_set_stats_file_names ( sectionStatsPath.c_str(), globalStatsPath.c_str() );
444   
445    /* Specify the maximum queuing speed in kmph. */
446    vgs_set_max_qspeed ( 3.6f );
447   
448    /* Unlock the semaphore blocking Aimsun from execution. */
449    vgs_unlock_aimsun();
450}
451
452void AimsunDS::getdata ( vec &dt ) const
453{
454        /* Return the last data. */
455        printf ( "\n\tAimsunDS::getdata() starting\n" );
456
457        if ( p_rsp == NULL )
458        {
459                fprintf ( stderr, "ERROR: AimsunDS::getdata() - no data available yet!\n" );
460                return;
461        }
462
463        /* Loop over all controllers in the measurement set. */
464        for ( int i = 0; i < p_rsp->count; i++)
465        {
466                det_stats * ds_ptr  = p_rsp->dets + i;
467                sp_stats *  sp_ptr  = p_rsp->sps  + i;
468
469                printf ( "\tRealised signal plans:\n" );
470
471                /* Loop over all measurement sets. We will deliver just
472                   the last one. */
473                for ( int j = 0; j < sp_ptr->count ; j++ )
474                {
475                        sp_stattab * dat_ptr = sp_ptr->splans + j;
476                        int          pos     = _search_index ( IntersectionIDs, NumIntersections, dat_ptr->its_id );
477                        int          offset  = SignalPlanOffsets[pos];
478
479                        printf ( "\t[%3d] t=%6ds ", j, dat_ptr->global_time );
480
481                        /* Copy particular signals. */
482                        for ( int k = 0 ; k < dat_ptr->num_siggroups ; k++ )
483                        {
484                                dt[k+offset] = dat_ptr->green_time[k];
485                                printf ( "%3d ", dat_ptr->green_time[k] );
486                        }
487                        printf ( "\n" );
488                }
489
490                printf ( "\n\tDetector data:\n" );
491
492                /* Loop over all mesurement records with intensities and
493                   occupancies. */
494                for ( int j = 0 ; j < ds_ptr->count ; j++ )
495                {
496                        det_aggreg_table * dat_ptr = ds_ptr->stats + j;
497                        int  pos     = _search_index ( IntersectionIDs, NumIntersections, dat_ptr->its_id );
498                        int  moffset = MeasurementOffsets[pos];
499
500                        printf ( "\t[%3d] t=%6ds ", j, dat_ptr->global_time );
501
502                        for ( int k = 0 ; k < dat_ptr->num_det ; k++ )
503                        {
504                                dt[2*k+moffset]   = dat_ptr->dt_intensity[k];
505                                dt[2*k+moffset+1] = dat_ptr->dt_occupancy[k];
506                                printf ( "{%2d/%2d} ",
507                                        dat_ptr->dt_intensity[k], dat_ptr->dt_occupancy[k] );
508                        }
509                        printf ( "\n" );
510                }
511        }
512
513        /* Loop over the statistical data. We will extract the queue length for
514           every intersection and store it into the data vector. */
515        int oLanes = 0; // lane offset for the actual intersection
516        int oLpos  = 0;
517        for ( int i = 0 ; i < NumIntersections ; i++ )
518        {
519                /* Every intersection has a certain number of lanes that (roughly)
520                   correspond to the number of signal groups. */
521                int nLanes  = NumLanes[i];
522                int qoffset = QueueLengthOffsets[i];
523                for ( int j = 0 ; j < nLanes ; j++ )
524                {
525                        /* Initial queue length for this lane is zero. */
526                        int qLen = 0;
527                        /* Every lane has one or more section identifiers at certain
528                           positions in LaneQueuesStatIds. The sequence of lanes
529                           is given by offsets in LaneQueueOffsets, the position of
530                           the statistical information is stored in LaneQueuesStatPos. */
531                        for ( int k = oLpos ; k < LaneQueueOffsets[oLanes+j+1] ; k++ )
532                        {
533                                /* Get the index into statistical information records. */
534                                int pi = LaneQueuesStatPos[k];
535                                int pl = LaneQueuesLaneIds[k]-1; // indices are not zero-based
536                                /* Now query the last queue length (section with more than
537                                   one lane holds several queue lengths) and add it to the
538                                   acumulated queue length value. */
539                                qLen += sections_stats.queues[pi*sections_stats.max_lanes+pl];
540                        }
541                        /* Move the lane position offset. */
542                        oLpos = LaneQueueOffsets[oLanes+j+1];
543                        /* Update the data vector. */
544                        dt[qoffset+j] = qLen;
545                }
546                oLanes = oLanes + nLanes;
547        }
548
549        printf ( "\tAimsunDS::getdata() finished\n" );
550        cout << dt ;
551}
552
553
554void AimsunDS::write ( vec &ut )
555{
556    eh_res     sp_res;   /* Result code from write operation. */
557        eh_hrdels3 hrdsp[2]; /* Signal plan for two intersections. */
558   
559    /* Check that the length of the vector is correct. */
560    if ( ut.size() != utsize )
561    {
562      fprintf ( stderr, "Incorrect length of data vector (should be %d)", utsize );
563      exit(-1);
564    }
565    /* Check that the phase lengths sum to correct cycle time. */
566    /*
567        if ( ut[0]+ut[1]+ut[2] != 80 )
568    {
569      fprintf ( stderr, "Intersection 495: F1+F2+F3 != Tc (should be 80)" );
570      exit(-1);
571    }
572    if ( ut[3]+ut[4]+ut[5] != 80 )
573    {
574      fprintf ( stderr, "Intersection 601: F1+F2+F3 != Tc (should be 80)" );
575      exit(-1);
576    }*/
577
578    hrdsp[0].id = 495;
579    hrdsp[0].sp.cycle_time   = int ( ut[0] );
580        hrdsp[0].sp.offset       = int ( ut[1] );
581        hrdsp[0].sp.phase_len[0] = int ( ut[2] );
582    hrdsp[0].sp.phase_len[1] = int ( ut[3] );
583    hrdsp[0].sp.phase_len[2] = int ( ut[4] );
584    hrdsp[0].sp.phase_len[3] = -1;
585
586    hrdsp[1].id = 601;
587    hrdsp[1].sp.cycle_time   = int ( ut[ 0] );
588    hrdsp[1].sp.offset       = int ( ut[ 8] );
589    hrdsp[1].sp.phase_len[0] = int ( ut[ 9] );
590    hrdsp[1].sp.phase_len[1] = int ( ut[10] );
591    hrdsp[1].sp.phase_len[2] = int ( ut[11] );
592    hrdsp[1].sp.phase_len[3] = -1;
593
594        /* Write new signal plan to the shared memory of active controllers. */
595    sp_res = eh_write_hrd_data( hrdsp, 2 );
596
597        if ( sp_res != EH_RES_OK )
598        {
599                printf ( "eh_write_hrd_data(): " );
600                if ( sp_res == EH_RES_WCNT )
601                {
602                        printf ( "Wrong count of ELS3...\n" );
603                }
604                else if ( sp_res == EH_RES_WRID )
605                {
606                        printf ( "Wrong intersection ID...\n" );
607                }
608                else
609                {
610                        printf ( "Unknown error [%d] ...\n", sp_res );
611                }
612        }
613}
614
615
616void AimsunDS::step()
617{
618        eh_wres      wsp_res;   /* Result code of the wait operation. */
619    int          count;         /* Count of measurement sets. */
620   
621    /* Wait for 100 seconds until data from all ELS3 controllers arrive. */
622        wsp_res = eh_wait_on_rsp_complete( 100000 );
623
624        if ( wsp_res != EH_WRES_OK )
625        {
626                printf ( "eh_wait_on_rsp_complete(): " );
627
628                if ( wsp_res == EH_WRES_TIMEOUT )
629                {
630                        printf ( "Timeout elapsed ...\n" );
631                }
632                else if ( wsp_res == EH_WRES_EXIT )
633                {
634                        printf ( "Some ELS3 has exited ...\n" );
635                }
636                else
637                {
638                        printf ( "Unknown error [%d] ...\n", wsp_res );
639                }
640                exit(-1);
641        }
642
643        /* This will copy the detector data out. It is needed by the
644           Matlab HRDS version due to its internal structure - realised
645           signal plans are read asynchronously and later. The value
646       of `count` reports the number of data sets that will be
647       returned by the call to `eh_read_realised_sp()`. This coount
648       will be at least 1 but it may be higher in cases where the
649       controller reports measurements in short intervals but we are
650       reading them less frequently. */
651        count = eh_copy_out_measurements ();
652
653        printf ( "got %d measurements from controllers ...", count );
654
655        /* Read realised signal plan from shared memory. */
656        if ( eh_read_realised_sp( &p_rsp ) == EH_RES_OK )
657        {
658                printf("\nsuccesfully read data from controllers\n" );
659        }
660        else
661        {
662                printf(" but got no data ???\n");
663        }
664
665        /* Finally we will also read the last statistical information
666           from the VGS interface. */
667        vgs_get_last_stats ( &sections_stats );
668}
Note: See TracBrowser for help on using the browser.