-
Notifications
You must be signed in to change notification settings - Fork 1k
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
If configured, add subway station entrances from OSM to walk steps #6076
base: dev-2.x
Are you sure you want to change the base?
If configured, add subway station entrances from OSM to walk steps #6076
Conversation
We need to harmonise our approaches as #6082 does something similar. |
# Conflicts: # application/src/main/java/org/opentripplanner/model/plan/Entrance.java # application/src/main/java/org/opentripplanner/model/plan/StepEntity.java # application/src/main/java/org/opentripplanner/street/model/vertex/StationEntranceVertex.java # application/src/main/java/org/opentripplanner/street/model/vertex/VertexFactory.java # application/src/main/java/org/opentripplanner/transit/service/datafetchers/StepEntityTypeResolver.java # doc/user/BuildConfiguration.md
...ication/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/StepEntityTypeResolver.java
Outdated
Show resolved
Hide resolved
@@ -61,6 +72,10 @@ public ZoneId getTimeZone() { | |||
return timeZone; | |||
} | |||
|
|||
public boolean getIncludeOsmSubwayEntrances() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This could probably be just named includeOsmSubwayEntrances
.
@@ -0,0 +1,3 @@ | |||
package org.opentripplanner.model.plan; | |||
|
|||
public abstract class StepEntity {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could discuss in a dev meeting if this is the best approach.
application/src/main/java/org/opentripplanner/osm/model/OsmNode.java
Outdated
Show resolved
Hide resolved
...ion/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java
Outdated
Show resolved
Hide resolved
public StationEntranceVertex(double x, double y, long nodeId, String entranceName) { | ||
super(x, y, nodeId); | ||
this.entranceName = entranceName; | ||
} | ||
|
||
public String getEntranceName() { | ||
return entranceName; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this should be called entranceCode
for the purpose we use. In the future, if we include entrances from GTFS with the same model, the name and code will be different things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or perhaps just code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not publicCode
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In GTFS terminology, it's called stop_code in stops.txt. I'm not a native english speaker, but public code doesn't make it more understandable for me vs code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public
say it is used as information to the public. There are also other codes used for other things, like privateCode
used by agencies for internal references.
application/src/main/java/org/opentripplanner/street/model/vertex/StationEntranceVertex.java
Outdated
Show resolved
Hide resolved
application/src/main/java/org/opentripplanner/street/model/vertex/VertexFactory.java
Outdated
Show resolved
Hide resolved
application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls
Outdated
Show resolved
Hide resolved
application/src/main/resources/org/opentripplanner/apis/gtfs/schema.graphqls
Outdated
Show resolved
Hide resolved
public Object getEntity() { | ||
return entity; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would like to se a diagram with boxes - forget about the class design for a moment and just draw the things we want to add in the future (next 1- 2 years). Then we can discuss how to group them and map the relationship.
Return an Object
is no-go, and so is Entrance extends StepEntity
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I drew some sort of a process diagram with boxes together with @HenrikSundell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this method should probably still return StepEntity instead of Object but I think the step impl must return an Object for the entity which is then handled by StepEntityTypeResolver. It's possible that instead of doing the instanceof checks that are currently done to return correct schema types, we could cast the object to a StepEntity and then check if entrance field is non-null, or escalator field is non-null etc., but I'm not sure how much cleaner that solution is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just quickly tested and seems like it's possible to define a class that is used for an union from GraphQL (through codegen configuration). So with this current setup where the different entity types would have a shared base class, you could use that for the union. However, if they don't, then you need to return an Object from the stepImpl#entity()
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...ion/src/main/java/org/opentripplanner/routing/algorithm/mapping/StatesToWalkStepsMapper.java
Outdated
Show resolved
Hide resolved
Co-authored-by: Joel Lappalainen <[email protected]>
Co-authored-by: Joel Lappalainen <[email protected]>
application/src/main/java/org/opentripplanner/apis/gtfs/datafetchers/EntranceImpl.java
Outdated
Show resolved
Hide resolved
return entrance.getName() != null | ||
? org.opentripplanner.framework.graphql.GraphQLUtils.getTranslation( | ||
entrance.getName(), | ||
environment | ||
) | ||
: null; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import org.opentripplanner.framework.graphql.GraphQLUtils and just use GraphQLUtils.getTranslation
. Also, you can mark the input
parameter in the getTranslation method as nullable and just pass in the entrance's name to the method as it does the null checks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason for the full path is that org.opentripplanner.apis.gtfs.GraphQLUtils
is already imported.
@@ -130,6 +134,13 @@ public String getExit() { | |||
return exit; | |||
} | |||
|
|||
/** | |||
* Get information about building entrance or exit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we should say "subway stations's entrance" instead of building here. Also since there is already getExit
here, maybe rename this and the highway exit rename methods so it's really clear that one is for highways, and the other is for stations.
// don't care what came before or comes after | ||
var step = createWalkStep(forwardState, backState); | ||
|
||
step.withRelativeDirection(RelativeDirection.ENTER_OR_EXIT_STATION); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could add a comment here to explain that figuring out if something is an entrance or exit is difficult here.
private final String code; | ||
private final boolean accessible; | ||
|
||
public StationEntranceVertex(double x, double y, long nodeId, String code, boolean accessible) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already a class called TransitEntranceVertex
. I think we could probably use that instead of this. Although, I don't know if we should reserve the use of it just for pathways? Thoughts @leonardehrenfried ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We decided we try to reuse the TransitEntranceVertex.
@@ -444,6 +444,18 @@ type Emissions { | |||
co2: Grams | |||
} | |||
|
|||
"Station entrance or exit." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could clarify here that this can originate either from GTFS or from OSM.
type Entrance { | ||
"Short text or a number that identifies the entrance or exit for passengers. For example, `A` or `B`." | ||
code: String | ||
"ID of the entrance in the format of `FeedId:EntranceId`." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, you could mention that if the feed is osm
, the entrance is from OSM data.
"Short text or a number that identifies the entrance or exit for passengers. For example, `A` or `B`." | ||
code: String | ||
"ID of the entrance in the format of `FeedId:EntranceId`." | ||
entranceId: String |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
entranceId: String | |
entranceId: String! |
@@ -2645,6 +2657,8 @@ type step { | |||
distance: Float | |||
"The elevation profile as a list of { distance, elevation } values." | |||
elevationProfile: [elevationProfileComponent] | |||
"Information about an station entrance or exit" | |||
entrance: Entrance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless I'm totally mistaken, I think on this API level we still want to have the entity field which returns an entity union.
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev-2.x #6076 +/- ##
=============================================
- Coverage 69.75% 69.70% -0.06%
- Complexity 17657 17704 +47
=============================================
Files 2007 2011 +4
Lines 75573 75899 +326
Branches 7734 7764 +30
=============================================
+ Hits 52716 52902 +186
- Misses 20144 20279 +135
- Partials 2713 2718 +5 ☔ View full report in Codecov by Sentry. 🚨 Try these New Features:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed yesterday in a developer meeting if ENTER_OR_EXIT_STATION needs to be exposed through the API at all or should we just use CONTINUE. I've thought about this a bit more and I think I would be ok with just using CONTINUE but we need to document on the enum in the schema that it's used also when going through entrances and we don't know into what direction. We can still keep the ENTER_OR_EXIT_STATION in the internal model but just map it into CONTINUE on API level.
private final String code; | ||
private final boolean accessible; | ||
|
||
public StationEntranceVertex(double x, double y, long nodeId, String code, boolean accessible) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We decided we try to reuse the TransitEntranceVertex.
@@ -3328,6 +3345,7 @@ enum RelativeDirection { | |||
CONTINUE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add description for this enum value. Maybe we could add descriptions for some other values in this enum as well as not all of them are clear.
.withCoordinate(new WgsCoordinate(coordinate)) | ||
.withCode(ref) | ||
.withWheelchairAccessibility( | ||
accessible ? Accessibility.POSSIBLE : Accessibility.NOT_POSSIBLE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we also check if the tag is defined? If not, the value should be NO_INFORMATION
.
@@ -356,19 +354,19 @@ private StreetVertex link( | |||
ll.getSegmentIndex() == 0 && | |||
(ll.getSegmentFraction() < 1e-8 || ll.getSegmentFraction() * length < 0.1) | |||
) { | |||
start = (IntersectionVertex) edge.getFromVertex(); | |||
start = (Vertex) edge.getFromVertex(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are these casts necessary here?
@@ -380,7 +378,7 @@ else if ( | |||
if (!linkedAreas.add(ael)) { | |||
return null; | |||
} | |||
if (vertex instanceof IntersectionVertex iv) { | |||
if (vertex instanceof Vertex iv) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there vertices which are not instance of vertex?
protected StreetTransitEntityLink( | ||
StreetVertex fromv, | ||
T tov, | ||
Vertex fromv, | ||
TransitEntranceVertex tov, | ||
Accessibility wheelchairAccessibility | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be enough to have a constructor that accepts (Vertex
, Vertex
, Accessibility
)?
@@ -3328,6 +3345,7 @@ enum RelativeDirection { | |||
CONTINUE | |||
DEPART | |||
ELEVATOR | |||
ENTER_OR_EXIT_STATION |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't want to expose this enum value to users, it should be mapped to CONTINUE.
import org.opentripplanner.street.search.TraverseMode; | ||
import org.opentripplanner.street.search.state.State; | ||
import org.opentripplanner.transit.model.basic.Accessibility; | ||
import org.opentripplanner.transit.model.site.AreaStop; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These imports (o.o.street.search
and o.o.transit
) is to me a "code smell". Does it create circular dependencies?
@@ -35,6 +42,8 @@ public abstract class Vertex implements AStarVertex<State, Edge, Vertex>, Serial | |||
|
|||
private transient Edge[] outgoing = new Edge[0]; | |||
private RentalRestrictionExtension rentalRestrictions = RentalRestrictionExtension.NO_RESTRICTION; | |||
private static final Set<AreaStop> EMPTY_SET = Set.of(); | |||
private Set<AreaStop> areaStops = EMPTY_SET; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very few Vertexes have areaStops, I am not an expert on the AStar routing and design, but this does not look right to me.
Summary
This PR gets subway station entrance names from osm and adds the to walk steps.
Issue
Closes #6078