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

Revision 1031, 22.6 kB (checked in by prikryl, 14 years ago)

Corrected queue tables for 5.601

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