Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hilight problematic short segments when mouse hovers node #1229

Open
originalfoo opened this issue Dec 11, 2021 · 45 comments · May be fixed by #1730
Open

Hilight problematic short segments when mouse hovers node #1229

originalfoo opened this issue Dec 11, 2021 · 45 comments · May be fixed by #1730
Assignees
Labels
feature A new distinct feature JUNCTION RESTRICTIONS Feature: Junction restrictions PRIORITY SIGNS Feature: Stop / Yield / Priority signs TRAFFIC LIGHTS Feature: Traffic lights - toggle, timed, etc Vehicle Behavior Vehicle behavior related issue

Comments

@originalfoo
Copy link
Member

Describe your idea

Very short segments cause vehicle AIs to behave unexpectedly when connected to nodes customised with the following tools:

Those tools all require user to first select a node to edit before they can customise it; we can warn user about short node prior to selecting the node:

  1. When user hovers mouse over the node they want to edit, check for short segments.
  2. If found:
    • Highlight short segment(s) with red outline
    • Change mouse-following tooltip to "Tiny segments cause problems" (or something like that)
    • If not too painful, change mouse cursor to a warning symbol ⚠️
  3. When mouse leaves node, or node selected for editing, clear the warning

See also: #698

Screenshots?

n/a

Notes or questions?

Broken Nodes Detector mod has code that scans for short segments; could use that code but only check segments attached to the hovered node to reduce overheads.

Code for checking the segments attached to a node, and showing/clearing the warning could be centralised making it easier to incorporate in to any tools that need it. If memory serves, all those tools change the node highlight when mouse is over the node, so it would just be a case of adding maybe 1 line of code to the tools' node hover/leave/select handling methods.

The class should probably cache the node it just checked (and the result) so that it doesn't need to do expensive checks every frame. The cache would be cleared when the mouse leaves a node, or the node is selected for editing.

User could still select the node and customise it if they want to take the risk, but at least now they'll know what's causing problems if vehicles are ignoring their customisations.

Additional future enhancements:

  • If we learn of other problems, eg. sometimes weird stuff like 'overlapping nodes' (user didn't properly connect two segments together), the central class could be updated to check for that too.
  • A "Try and fix short segments" mod option; it's confirmed that reducing speed of a short segment can sometimes mitigate problems, at least for TTL. See also: Nerf road speed at traffic lights / stop signs. #757
@originalfoo originalfoo added feature A new distinct feature triage Awaiting issue categorisation JUNCTION RESTRICTIONS Feature: Junction restrictions TRAFFIC LIGHTS Feature: Traffic lights - toggle, timed, etc PRIORITY SIGNS Feature: Stop / Yield / Priority signs Vehicle Behavior Vehicle behavior related issue labels Dec 11, 2021
@krzychu124
Copy link
Member

Honestly I will see is as a new overlay/icon layer just for warnings. Could be enabled and filtered based on active tool or something. Similar to what we see when one-way has a dead end, trolleybus/tram segment end is not connected, etc.

@krzychu124
Copy link
Member

I've reviewed the code and found one big bug 😱 or I would say huge design flaw that makes junction features to work only when segment is long enough... segment length doesn't really matter if you know what you are doing and how simulation works (yes I've spent few days figuring out how simulation works in tiny details while working on EVE revival and improvements recently).

Test case (impossible to handle correctly running any version of the mod - yes, they have green here but as described, it doesn't matter - try yourself) :

2021-12-12_05-41-06.mp4

Here the same scenario but with one little change in the code:

2021-12-12_05-42-27.mp4

Bonus points:
Yield signs are way more accurate, vehicle will wait patiently for perfect spot before start moving, no longer crawling to forcefully join with the traffic.

Big downside of the change:
Makes whole implementation a lot slower, no fallback behavior, no shortcuts, no testing previous state, everything is calculated each time vehicle approach new segment.

Important note:

Game can process even multiple segments/nodes per each simulation step for each vehicle in chunk (1024/step), number of processed segments is correlated with vehicle speed, speed limit and segments length.
In above scenario I'm pretty sure it processed all 10 short segments in one step, then... 7-9 remaining, depends on how far vehicle was moved between steps and so on 😉

@originalfoo
Copy link
Member Author

Big downside of the change:
Makes whole implementation a lot slower, no fallback behavior, no shortcuts, no testing previous state, everything is calculated each time vehicle approach new segment.

How much impact is there in relation to "a lot slower"? Is there some way we could embed "junction coming up, enable extra checks" in to the path units? That way the vehicle AI isn't doing all the extra work while driving down long stretches of road, it's only doing heavy lifting a few segments from a junction?

@krzychu124
Copy link
Member

Each simulation step vehicle calculates 4 next positions (circles). Between steps it travels between current and next frame (rectangles) not further than to the first target, in the next step target0 is usually "converted" to "next" frame if speed is constant.

130 km/h (cur. segment is the segment of current pathUnit)

image
image

40 km/h

image
image

That change shouldn't have big impact for highways since segments are pretty long and also roads where junction node connects only two segments. I need to do some benchmarking, but keeping in mind user "cried" that simulation accuracy at very high was forced some time ago, this will be like multiple times of it if you place a lot of short segments and set medium speed (50-70km/h) with either traffic lights or priority signs.

@originalfoo
Copy link
Member Author

originalfoo commented Dec 16, 2021

Could it scale based on vehicle speed? So slower vehicle speed = less look-ahead?

EDIT: Also, are those diagrams rendered in game (the circles/squares, not the text/arrows heh)?

@krzychu124
Copy link
Member

Could it scale based on vehicle speed? So slower vehicle speed = less look-ahead?

Distance between target positions is dynamic, based on vehicle speed, ability to brake and some other minor details.

EDIT: Also, are those diagrams rendered in game (the circles/squares, not the text/arrows heh)?

It's a part of my Pathfind Sandbox (will be). I found nice and clean way to select/follow instance you want to observe so I started attaching more stuff to it in form of overlays.

@originalfoo
Copy link
Member Author

originalfoo commented Dec 17, 2021

Regarding EVE, there might be some possibility to use Vehicle.Flags? Specifically, the m_setvehicleflags of a segment is transposed on to vehicles driving on it... As this is only for roads, you could repurpose existing flags that are used for other AIs, such as TakingOff, Flying, Landing...? Also I see there's Emergency1 and Emergency2 flags - no idea what they are used for (not checked). Also note Congestion flag... could maybe use that near junctions? Eg. few frames before traffic light turns red set the congestion flag and have vehicles act accordingly?

@krzychu124
Copy link
Member

Congestion flag

Used in vanilla to force despawn vehicle approaching congested segment to prevent making longer traffic jams XD

Emergency2

Used when vehicle use emergency signal lights

Emergency1

Used in special cases, e.g. when fire truck stopped near the burning building and is extinguishing fire, similar for the fire copter, maintenance trucks when they maintain road, water trucks when pumping water, disaster response units searching for "problems" etc.

m_setvehicleflags

Is applied unconditionally to every vehicle that enter segment, problem is it is per netInfo, so for all segment instances on the map. Good to help with deciding if effects like dust should be rendered, but not that useful for EVE (need to think about that). I've been testing different approach with better results.

@originalfoo
Copy link
Member Author

Created wiki article to collate infos about Vehicle.Flags: https://github.com/CitiesSkylinesMods/TMPE/wiki/Vehicle-Flags

@krzychu124
Copy link
Member

I was experimenting with priority signs code and I think we could improve some behaviour, especially when vehicle is driving off main road (yield other vehicles incoming from the front).
Currently if junction does not have priority signs set or target and incoming vehicle are on main road they completely ignore a chance of possible collision.

Default behaviour, they will run into each other, ignoring priorities

image

One way to fix it, but may introduce problem/unwanted yield for traffic going straight Blue truck will patiently wait for enough space or a gap in incoming traffic because of congested exit of intersection

image

What I would like to see:

  • blue truck should yield always when turning left (crossing incoming traffic), even if there are no priority signs
    It might be active only when Simulation Accuracy is High or Very High

Probably there are other cases where vehicles should yield. I noticed in code that once vehicle enter intersection area only vehicle collision is calculated - no further priority checks, so at big intersections or roundabouts it increases a chance of causing fake congestion on main road (going around the roundabout) blocking the traffic (yielding traffic will start entering intersection because of traffic gap mentioned above)

Maybe I'm blind, do we have any thread/issue with regards to problems/suggestions about priorities/priority signs, similar to those for traffic lights, parking AI etc.?

@originalfoo
Copy link
Member Author

I remember some discussion of this, give me a few mins and I'll see if I can find it.

@originalfoo
Copy link
Member Author

It would be super-useful if we could set priority by lane, rather than segment. That way the far-side turn lane could be given a stop/yield and the straight-on lanes could be priority to allow smooth traffic flow.

There's some other stuff relating to T-junctions and Y-junctions (forks) that needs considering which I don't think is directly mentioned in the linked issues above, I'll try and jot down some thoughts on those in an hour or so.

@krzychu124
Copy link
Member

It would be super-useful if we could set priority by lane, rather than segment. That way the far-side turn lane could be given a stop/yield and the straight-on lanes could be priority to allow smooth traffic flow.

This is what I meant, but for all cases without even touching intersection with TM:PE settings. Traffic Priority feature should be ON at Maintenance tab, Sim Accuracy at least High since checking priorities at every intersection may cause small slowdown (maybe check only in 300-500m from camera or reuse 0,1,2 LOD levels of vehicle simulation)

2022-02-06.21-52-53.mp4

@originalfoo
Copy link
Member Author

that's freaking awesome!

@krzychu124
Copy link
Member

Priorities are not tested at node so they behave a bit rough,

2022-02-06.22-01-50.mp4

@originalfoo
Copy link
Member Author

originalfoo commented Feb 6, 2022

That's still a good improvement on what currently happens IMO

In terms of simulation workload, what's the "LOD level of vehicle simulation"? I assume the game is reducing complexity based on how far away the camera is?

EDIT: possibly related:

@krzychu124
Copy link
Member

In terms of simulation workload, what's the "LOD level of vehicle simulation"? I assume the game is reducing complexity based on how far away the camera is?

Yes there are 3 LOD levels, at level 2 all collision checks are skipped, at level 1 only vehicle-pedestrian iirc

@krzychu124
Copy link
Member

More "unprotected" turns.

Scenario:

  • left going up,
  • up going down,
  • down going left,
2022-02-07.03-44-50.mp4
2022-02-07.03-44-00.mp4
2022-02-07.03-41-18.mp4

@originalfoo
Copy link
Member Author

originalfoo commented Feb 7, 2022

For deadlock issues, some ideas:

  • Smaller / slower roads should yield to faster / larger roads
  • If that still doesn't solve it, road with most congestion/traffic should go first
  • If it looks like T-junction, perpendicular road should yeild to more straight road

As mentioned above we could also have pecking order based on ExtVehicleType - eg. emergency, then tracked, then road-PT, then services, then cargo, then passenger car?

@krzychu124
Copy link
Member

Yeah, we should write down info about priorities somewhere, maybe in the wiki as upcoming feature then just implement missing bits.
In above case giving auto higher-priority to the Tram would potentially help with deadlock but still needs to be fixed in case of other road vehicles. Honestly I was browsing history of changes and couldn't find anti-deadlock code mentioned in the old wiki

Functional priority signs seem to completely obsolete current functionality of enter blocked junction.

Yes it does not make sense if you put priority signs. I would apply it automatically under the hood e.g. for transition nodes when e.g.: road with median is connected to basic road.

ExtVehicleType will be good start then I think we could try introducing temporary priority, so e.g. once deadlock occurs we select best segment to get higher priority temporarily (e.g. for 30/60 sim frames to unload traffic from one side

@krzychu124
Copy link
Member

Yeah, I remember Advanced junction rule. I've got an brief idea how to implement it but I need to create basic version of priority check function for vehicles already at node or like you've mentioned in the box junction area. It will used by vehicles that are on road with priority (intersecting with vehicles also on priority segment) but degraded to yielding because of unprotected turn maneuver, so the number of possible combinations can be optimized to be as fast as possible keeping best accuracy.

Hehe, I'm watching how they move... it's so satisfying to look at 😄

@originalfoo
Copy link
Member Author

originalfoo commented Feb 7, 2022

For deadlock I also think what would happen IRL...

Usually bigger vehicles can muscle in (and are used to doing so if you've ever known a lorry driver lol - they still do it when driving cars), so things like service and transport. But also you could get things like reckless drivers pushing in, and people on way to work might be more likely to enter junction, etc. For cars in particular we could possibly have it affected by individual driving style feature? I still think individual driving style should be on by default and use the driver id as if it were a randomised bitmask defining traits of the driver, including how they behave at junctions (are they more passive or aggressive, etc). Driver age could also affect their behaviour.

@originalfoo
Copy link
Member Author

Another thing with individual styles, some drivers might be more willing to let others go first - eg. if there's a big queue they might flash lights to let car at front enter junction (or exit junction if they were part entered).

@krzychu124
Copy link
Member

Btw, now as I watch they wait for their turn I started thinking about fixing blinkers so even if vehicle does not move and e.g.: waiting to turn left it could have blink left ON (that's possible, just require a tiny patch).

Usually bigger vehicles can muscle in (and are used to doing so if you've ever known a lorry driver lol - they still do it when driving cars), so things like service and transport

Yeah, I thought about that too. At worst we can select them by ID -> decision is taken every sim step so every 1024/4096(MV) vehicles - we can "push" first found vehicle from current chunk 🙃
There are many ways to do so.

@originalfoo
Copy link
Member Author

Btw, now as I watch they wait for their turn I started thinking about fixing blinkers so even if vehicle does not move and e.g.: waiting to turn left it could have blink left ON (that's possible, just require a tiny patch).

Additionally, it would be great if they didn't use blinkers when simply driving round a curved segment (unless it's one-way street where it might be roundabout heh).

I have some really bendy roads snaking through mountains and it always irrates me how vehicles indicate round sharp bends lol.

@krzychu124
Copy link
Member

Fully manual prototype

2022-02-07.22-17-40_Trim.mp4

@originalfoo
Copy link
Member Author

Ooh, can we make it so if a vehicle breaks fast it puts both indicators on to warn other traffic?

@originalfoo
Copy link
Member Author

Could also do both indicators when vehicles are pulled in to a building to load/unload/etc.

@krzychu124
Copy link
Member

Ooh, can we make it so if a vehicle breaks fast it puts both indicators on to warn other traffic?

I have no idea how to detect it.

Could also do both indicators when vehicles are pulled in to a building to load/unload/etc.

Will be the easiest thing actually 😄

I was thinking about bus tops - emergency when boarding then turn to join traffic. Since most calls are invoked 4 times/per vehicle/per step it's not obvious where to put 'start' and 'reset' triggers 🤔

@originalfoo
Copy link
Member Author

Since most calls are invoked 4 times/per vehicle/per step

omg, wat?!

@krzychu124
Copy link
Member

Movement is interpolated between frames (last and next - rectangles). Next calculation occurs when vehicle is about to hit next frame. It needs to calculate 4 target positions (circles), they are used as next position (target0, closest), other to determine if vehicle will accelerate or slow down/ stop. Most of TM:PE methods, like eg. MayChangeSegment - when calculated target position will land as last position of current segment, at node or next segment. CalculateSegmentPosition is called for each calculated target position (circle) that should land on segment, otherwise simplified version is called to apply transition on the node. Etc. It's not that card to understand how it works and what to do in case of tweaks/changes

5% speed:

2022-02-08.00-33-58.mp4
2022-02-08.00-37-30.mp4

Normal speed XD

2022-02-08.00-39-17.mp4

@krzychu124
Copy link
Member

More or less _blinking_😄

2022-02-08.04-11-35.mp4
2022-02-08.04-09-24.mp4

@originalfoo
Copy link
Member Author

originalfoo commented Feb 8, 2022

nice!

How is the blinking done? Is it just a flag that gets set and the game does the rest, or do you have to write code to keep turning it on/off?

@krzychu124
Copy link
Member

How is the blinking done? Is it just a flag that gets set and the game does the rest, or do you have to write code to keep turning it on/off?

Currently I'm checking direction between current and next segment. If left or right then turn on turn signal otherwise reset. I need to add a little code to check if approaching node is a junction to eliminate turn signals on Bend nodes.
I wanted to add turn signals when changing lanes but I couldn't find performant solution for calculating if next lane changes and which direction compared to current movement direction. Also I couldn't find way to detect if a bus stop is on the left or right side...

@brunoais
Copy link

brunoais commented Feb 8, 2022

Can nodes store arbitrary metadata?
If so, maybe you can store in nodes when there's an intersection approaching in nodes nearby intersections (by distance, instead of by node count). I don't know how hard would it be to maintain such information for when the road changes.
Maybe you can use the agents themselves to report if no intersection was expected and an intersection is encountered so that information can be added to the close-by nodes.

@originalfoo
Copy link
Member Author

originalfoo commented Feb 8, 2022

I wanted to add turn signals when changing lanes but I couldn't find performant solution for calculating if next lane changes and which direction compared to current movement direction

The way lane changes are limited to nodes, and the speed at which vehicles just jolt in to next lane would make indicators look weird in that context anyway IMO.

It would be interesting to see the vehicle frames overlay (or whatever it's called) at 5% speed as a vehicle encounters a lane change.

Also I couldn't find way to detect if a bus stop is on the left or right side..

Very basic solution would be based on which side of road traffic drives on for the current city - Shortcuts.cs:

internal static bool LHT => Singleton<SimulationManager>.instance.m_metaData.m_invertTraffic == SimulationMetaData.MetaBool.True;

internal static bool RHT => !LHT;

But there are situations where bus stop is on a median, or even other side of road (in case of 1-way busways) - to discern that you'd need list of sorted lanes (there's already code for that) but ideally cached because it would be ludicrous to keep recalculating when segments very rarely change (geometry observer can help invalidate cache where necessary - this is also something desperately needed for overlays and which I'll probably make a start on after mod options chainsawing).

With cached list of sorted lanes for segment, it's simple case of checking if lane 0 (or lane Count-1?) in the lane that the bus enters the bus stop from.

Also would need to skip the whole thing if bus is stopping in a building (eg. bus terminal).

Actually, it doesn't matter if the code to determine which side the bus stop is on is bloaty and slow - it only needs to run once when the stop is created/moved. We need ExtTransportStop for buses, trams, trolleys :) lol

@originalfoo
Copy link
Member Author

Oh, one other scenario for which side bus is on that breaks my earlier assertion that we can just check a single lane position...

Roads with central bus lanes separated from normal road lanes by median, eg: various BRT roads like this one in workshop:

image

There are also inverted versions of that:

image

@krzychu124
Copy link
Member

krzychu124 commented Feb 8, 2022

Very basic solution would be based on which side of road traffic drives on for the current city

I just need a way to say that lane is directly connected or connection requires changing to the left or right.

The way lane changes are limited to nodes, and the speed at which vehicles just jolt in to next lane would make indicators look weird in that context anyway IMO.

Not at all. Just was clip with overlays - notice that gray lane marks current lane and I can add code for testing lane change at each circle (in the first clip after few sec. first yellow circle is calculating position on the next segment) so depends on speed I can turn on indicator even one or two segments before actual lane change occurs and even better, when congested you will see them blinking way before they actually change lane. It will be nice addition. I can also inject same thing into DLS code, so when TM:PE decide there is a better lane I can turn on signal in that case too - again segment or even multiple before lane change.
The main problem that needs to be solved and will basically fix all issues -> I need a function that for two laneIDs or lane indexes would tell me if lane transition involves lane change or not and if so, tell relative direction of it.

Notice how far vehicle needs to move after turning left till signal stops blinking. IMO, pretty nice.

2022-02-08.20-49-16.mp4

At 99% because of DLS but still, lane change is not instant. You can detect is pretty long ahead

2022-02-08.20-56-23.mp4
2022-02-08.21-02-09.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature A new distinct feature JUNCTION RESTRICTIONS Feature: Junction restrictions PRIORITY SIGNS Feature: Stop / Yield / Priority signs TRAFFIC LIGHTS Feature: Traffic lights - toggle, timed, etc Vehicle Behavior Vehicle behavior related issue
Projects
None yet
3 participants