averbraeck / opentrafficsim

Open Source Multi-Level Traffic Simulator
BSD 3-Clause "New" or "Revised" License
28 stars 8 forks source link

Injections Id order #115

Closed WJSchakel closed 4 months ago

WJSchakel commented 4 months ago

When using Injections to generate vehicles one can add an id column. If the injections involve multiple locations (e.g. multiple lanes), generation may be delayed on one location, causing a GTU that was scheduled later to be generated on another lane before the delayed GTU. Then, the Injections will provide the id's in the wrong order.

WJSchakel commented 4 months ago

First of all it is important that the input Table is sorted in generation time. This was not checked. The constructor now uses sortTable to make sure the data is sorted:

    private static Table sortTable(final Table table)
    {
        int timeColumn = table.getColumnNumber(TIME_COLUMN);
        Iterator<Row> iterator = table.iterator();
        Duration prev = iterator.hasNext() ? (Duration) iterator.next().getValue(timeColumn) : null;
        while (iterator.hasNext())
        {
            Duration next = (Duration) iterator.next().getValue(timeColumn);
            if (next.lt(prev))
            {
                // data is not in order
                List<Row> data = new ArrayList<>();
                for (Row row : table)
                {
                    data.add(row);
                }
                Collections.sort(data, new Comparator<Row>()
                {
                    /** {@inheritDoc} */
                    @Override
                    public int compare(final Row o1, final Row o2)
                    {
                        return ((Duration) o1.getValue(timeColumn)).compareTo((Duration) o2.getValue(timeColumn));
                    }
                });
                ListTable out = new ListTable(table.getId(), table.getDescription(), table.getColumns().toList());
                for (Row row : data)
                {
                    out.addRow(row.getValues());
                }
                return out;
            }
            prev = next;
        }
        return table;
    }
WJSchakel commented 4 months ago

The public String get() method of Injections which implements Supplier<String> as the id generator, knows nothing on whether GTU generation was delayed. Therefore there is no way for this method to check what id should be returned. This issue has to be solved in the LaneBasedGtuGenerator.

WJSchakel commented 4 months ago

With a change in LaneBasedGtuGenerator it can now generate the GTU ids either when the GTU characteristics are drawn, or when the vehicle is successfully generated. By default this is:

The behavior can be overruled with setIdsInCharacteristicsOrder(boolean) on the generator.

WJSchakel commented 4 months ago

There is also a Unit test which tests GTU ids on two separate lanes on two links, being defined in one instance of Injections.