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

Add Stops across all of MDS #554

Closed
schnuerle opened this issue Jul 16, 2020 · 31 comments · Fixed by #603
Closed

Add Stops across all of MDS #554

schnuerle opened this issue Jul 16, 2020 · 31 comments · Fixed by #603
Labels
Policy Specific to the Policy API

Comments

@schnuerle
Copy link
Member

schnuerle commented Jul 16, 2020

Is your feature request related to a problem? Please describe.

Stops has been added to Agency and Provider as a new beta feature in 1.0.0, but is not a part of Policy yet.

Describe the solution you'd like

Add a way to specify Stops so they can be used by Policy, so that cities can geographically define and communicate details around docking stations, charing stations, parking locations, corrals, etc.

Is this a breaking change

  • No, not breaking - would be an addition to the spec

Impacted Spec

For which spec is this feature being requested?

  • policy

Describe alternatives you've considered

N/A

Additional context

This is a requested addition that was not ready for the 1.0.0 release.

@schnuerle schnuerle added this to the 1.1.0 milestone Jul 16, 2020
@schnuerle schnuerle added the Policy Specific to the Policy API label Jul 16, 2020
@schnuerle
Copy link
Member Author

schnuerle commented Aug 13, 2020

Tony Cruz from Long Beach CA mentioned on the Provider call today a use case related to this. The city defines preferred parking areas for events (temporary mobility hubs) and emails them to each provider a few days before the events. Thinks defining them with GeoJSON would work for the city.

Another use case is in Louisville where they've setup stops in Policy to communicate spray painted scooter parking areas along a corridor. It's a hack right now with Stae and using some combination of when speed is 0 and the trip_end event.

If Stops are added in Policy these can be defined here. Since Policy is currently not meant to be real time, he could then mass email the providers to say that the Policy feed has been updated, and they can ingest the parking locations digitally instead.

@avatarneil
Copy link
Contributor

The most straight-forward way I can think about implementing this would be just allowing an array of stop_ids. Additionally, depending on the work in #549 we may want to allow policies to specify particular Spaces within a Stop too; that could be represented by having a key/val store as opposed to just an array, so like { stops: { stop_id: space_ids } } (e.g. { stops: { 68bbdc6e-8666-416e-88cb-cabbbe5a2085: ['4e8bb731-ebb5-4244-adc0-ad4d09aa0b03', '39f603a2-ee13-4d99-a96d-67d38f392659'] } } or something.

@schnuerle
Copy link
Member Author

We will be discussing this tomorrow at our Joint Working Group meeting, so attend if you are interested.

https://github.com/openmobilityfoundation/mobility-data-specification/wiki/Web-conference-notes,-2020.09.17-(Joint-Working-Group-City-Services)

@schnuerle schnuerle changed the title Add Stops to Policy Add Stops across MDS Sep 18, 2020
@schnuerle schnuerle changed the title Add Stops across MDS Add Stops across all of MDS Sep 18, 2020
@schnuerle
Copy link
Member Author

schnuerle commented Sep 18, 2020

From the WG call yesterday.

Vianova, Louisville, and LADOT have existing use cases for this.

Note the city defines these stops and publishes the API. Stops can be physically or virtually created by the city and communicated via this API. Some cities already doing this with GIS files to providers. Also providers can define them and tell the city to be included in this API officially - cities need to approve these anyway.

Can the 'user' rule type be used for this? Maybe but it's not clear enough and is meant to be for end user/rider consumption.

Vianova has use cases in South America and Europe now.
The idea is Enforceable Mobility Hubs.
2,700 hubs in Paris,
Has it 'working' with current MDS, but it's not elegant or understandable by providers,
Eg - mark an entire city as a no parking zone except for cutouts where mobility hubs are,
Want to instead define the hubs, not the areas that are not the hubs.
Vianova and others to add comments here clarifying their use cases.

Maybe this can be added to Geography, as a type of geography, eg 'stop'.
Geography is intended to be generic, but this and other use cases may be a reason to add an enumerated 'type' field and an 'id' field to it to reference things from Geography.

Per suggestion, Michael renamed this issue to have the solution be assumed to be in Policy.
Was previously 'Add Stops to Policy.'

Discussion about making stops non-authenticated/public, just like Geography.
Maybe, but consider privacy, eg device IDs.
Device IDs could only be returned if the feed is authenticated, but left out when public.
Check GBFS - add fields like theirs, what is the overlap?
Here is their 'station_information' endpoint, similar to Stops.
And their 'geofencing_zones' endpoint, similar to Policy.

@marie-x
Copy link
Collaborator

marie-x commented Sep 21, 2020 via email

@schnuerle
Copy link
Member Author

Would anyone who thinks this proposal is of high value to them like to make a PR for this to get ball rolling on the implementation details? Alternatively, we can flesh out the details here and then make a PR. We'd need to move it along soon to have time to review and include in the 1.1.0 release.

@schnuerle
Copy link
Member Author

@tybaltspark per your comment in #557, would you like to try a PR here to for getting Stops into Policy and all of MDS? I'm also thinking of a feature-stops feature branch to try and capture all the proposed changes to stops in one place.

@jackdreillyvia
Copy link

jackdreillyvia commented Oct 15, 2020

Hi @schnuerle , this is Jack with Vianova

Our proposal is adding an exclusions field to Rules schema that explicitly excludes a list of geographies and stops from inclusion in a Rule:

"exclusions": { 
  "stops": [list-of-stop-uuids], 
  "geographies": [list-of-geography-uuids]
}

This allows us to directly address the "mobility hubs" use-case that Brussels wants to implement. The rule is to only allow parking in mobility hubs while within the city border would be stated as:

{
  "name": "No Parking except for Mobility Hubs in Brussels",
  "rule_type": "count",
  "maximum": 0,
  "states": ["available"],
  "geographies": ["uuid-brussels-city-extents"],
  "exclusions": {
    "stops": [
       "uuid-mobility-hub-1",
       "uuid-mobility-hub-2",
       "uuid-mobility-hub-3"
    ],
    "geographies": [
       "non-stop-geography-1"
    ]   
}

By permitting both "stops" and "geographies" in "exclusions", one may attach meaning to an exclusion, or fall-back to a plain geography otherwise.

Additionally, by making an explicit distinction between the top-level geographies and the exclusion geographies, one can naturally create more intricate policies like "forbid parking in NeighborhoodA excluding these 5 mobility hubs, but allow parking everywhere outside NeighborhoodA"

This is an improvement over "geographies with cutouts" since the explicit presentation is more natural, and is semantically richer (e.g., stop information).

This is also an improvement over layering multiple, contradictory rules like

  1. Forbid parking everywhere in city extent
  2. Allow parking in Stop A, B, C

, since rule 1 would contain spurious infractions while vehicles are complying with rule 2.

Exclusions are also useful across any geographically-constrained rule, and the logic for checking for infraction is simple:

  1. Is the device in any excluded geography?
  2. YES: NOT CONTAINED
  3. NO:
    1. Is the device in any top-level geography?
    2. YES: CONTAINED
    3. NO: NOT CONTAINED

This logic for CONTAINED can be compacted into a single geographical check:

  • device in [(UNION all top-level geos) DIFF (UNION all excluded geos)]

What are your thoughts? We can certainly get started on a proposal PR if this is suitable.

@marie-x
Copy link
Collaborator

marie-x commented Oct 15, 2020

@jackdreillyvia I don't think this is the ticket for discussing this sort of change to Policy. But also, your "contradictory" example is not a good one. The way you would structure this is

  1. Allow parking in A, B, C
  2. Forbid parking everywhere else

These are not "contradictory". This is how Policy is fundamentally meant to work.

I still have yet to see an example where exclusions are necessary.

@schnuerle
Copy link
Member Author

Does anyone want to take on a PR for this idea for inclusion in 1.1.0? We've got about 2 weeks of development time left before features that are not complete and have consensus may be moved to the next release.

@fractalf
Copy link
Contributor

Hi,
I was discussing this exact same thing on the mds mail-list.

5 cent..

We have to implement a scenario where a city want to define a big "no parking" zone and many (50+) small "parking" zones within that big zone.

We will probably implement this using the "Order of operations" as mentioned here, ex:

  • Rule 1
    • type: count
    • maxiumum: 20
    • geographies: [ .. 50+ small parking zones .. ]
  • Rule 2
    • type: count
    • maxiumum: 0
    • geographies: [ .. 1 big no parking zone .. ]

Probably there will be a last rule as well defining the outer municipality boundary

  • Rule 3
    • type: count
    • maxiumum: .. some large number
    • geographies: [ .. municipality boundary zone .. ]

My first thought about the proposed solution by @jackdreillyvia regarding "exclusions" is that this seems to specific, unnecessary and not generic enough. That being said, it could be my understanding of their scenario is not good enough.

Internally we have used a property called priority on all zones, which solves all our problems when it comes to overlapping zones. This can be directly translated to the policy api via the "Order of operations".

@marie-x
Copy link
Collaborator

marie-x commented Oct 27, 2020

@fractalf Yes, using Rule order-of-operations as you describe is exactly how parking zones are intended to be implemented.

The municipal boundary is what the Jurisdiction API is intended for. :) Also you can just have an "INFO" policy for that if you don't need to measure against it.

@fractalf
Copy link
Contributor

@Karcass

The municipal boundary is what the Jurisdiction API is intended for. :) Also you can just have an "INFO" policy for that if you don't need to measure against it.

You mention two terms I've not yet encountered reading the docs.

  • Juristiction API - What exactly is this?
  • INFO policy - Is this a "thing"?

I'm asking 'cause I want to get my implementation right the first time :)

@marie-x
Copy link
Collaborator

marie-x commented Oct 29, 2020

The Jurisdiction API is described in issue #491 and PR #593

An "Info" Policy is described in the Policy API specification

@jackdreillyvia
Copy link

jackdreillyvia commented Oct 29, 2020

@Karcass @Retzoh Thanks for the clarification regarding Rule Order of Operations.

While your advice is clear, would you mind explaining the interpretation that Henri gives on the mds-city-services mailing list?

From: Henri
Subject: Re: [mds-city-services] Policy API: Rules with overlapping geographies
To: Alf
Cc: mds-city-services [email protected]

Hi Alf,

Generally speaking, the first rules of a policy take precedence over the later rules in the list. See the Order of operations section of the Policy spec for more details.
So you would want to start with small specific rules, and end with large broad rules.

For your "no parking" use-case however, it is not possible to create a rule authorizing trip ends in an area : they are authorized by default, and you can only prohibit them.
So bad news for you: you would have to make n holes in the big zone. This is quite easy to do with a GIS library or software such as ArcGIS or QGIS.
Note that this is true when technically sharing a policy using the MDS APIs. You can do how you want in your user-interfaces.

Hope this helps,

Henri

On Mon, 26 Oct 2020 at 14:20, Alf wrote:

I can't seem to find a property "priority" that would determine which rule is "master" if two rules have overlapping geographies.

How is this solved in MDS?

Typical scenario:
A city has a big zone with "no parking", except n small parking zones within.

Please don't say that the solution to this is to make n holes in the big zone :)

Thank you,

-Alf

The above exchange seems to conclude that holes are necessary, since rules do not have the capacity to permit behavior, only disallow behavior. In other words, your interpretation permits rule-searching to terminate at the first matching rule (whether the rule allows OR disallows behavior), while Henri's interpretation only permits rule-searching to terminate on a disallowing rule.

Am I misunderstanding something, or is there a disagreement in the two interpretations discussed?

@jackdreillyvia
Copy link

jackdreillyvia commented Oct 29, 2020

Addressing specifically the title of this issue (separate from the holes vs. not holes discussion above), I'd like feedback on the following proposal for linking Stops with Policies:

The core use case seems to be creating counting rules that reference the properties of a Stop, such as capacity, and allowing providers to gain real-time insight into the occupancy and capability of such zones. Since this is not possible today, one must duplicate the capacity field of the Stop and set it as the maximum value in the Rule.

One solution to this duplication-problem is to add a stop_id field to Rule. A non-empty stop_id serves two purposes:

  • If geographies is empty, then the geographical extent of the Rule is derived from the stop Geography
  • If rule_type = count, rule_unit = devices, and maximum is empty, then the maximum field is set to the Stop's capacity

This connection allows cities the convenience of having tightly-bound relationships between
Rules and Stops, so that changes in Stops are always kept in sync with related Rules. It also allows providers to leverage the Agency /stops endpoint to gain visibility into the current occupancy of a geography that is bound to a rule (e.g., so that they may forbid drop-off in zones that are already at capacity).

In general, our clients would find this rule useful: the ability to tie policies directly to the properties of specific stops.

Besides this proposal (linking capacity directly to a stop), it appears that Stop information can already be inferred from the existing Policy definition, via the stop_id field on stop-based-geographic-data. Thus, if one simply wants to track down extra information regarding a geography attached to a policy, this already seems possible by using the Policy API in tandem w/ existing API's such as the Agency /stops endpoint.

@marie-x
Copy link
Collaborator

marie-x commented Oct 29, 2020

@jackdreillyvia: the @Retzoh interpretation is not correct. A Rule can absolutely "permit" something (e.g. a count rule with a minimum of 0 and no maximum), followed by another rule that forbids something (e.g a count rule with a maximum of 0). But this ticket is still not the best place to discuss it. :)

@fractalf
Copy link
Contributor

fractalf commented Oct 30, 2020

@Karcass

An "Info" Policy is described in the Policy API specification

Sorry, I've read the Policy API spec doc up and down many times now, even searching for the string info, but just can't see any concept of "Info Policy". What am I missing?

This is the document you are refeering to right?

https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/policy

@jackdreillyvia
Can you please edit out the emails from your posts where you site from the mail-list? Thank you

@marie-x
Copy link
Collaborator

marie-x commented Oct 30, 2020

Wow, I'm sorry @fractalf. I was mis-remembering, I was thinking of the user type. I thought we called it info -- that must have been in an earlier draft. Sorry about that! It just makes the argument for the Jurisdiction API stronger, I think. ;)

@jackdreillyvia
Copy link

jackdreillyvia commented Nov 4, 2020

@Karcass

An "Info" Policy is described in the Policy API specification

Sorry, I've read the Policy API spec doc up and down many times now, even searching for the string info, but just can't see any concept of "Info Policy". What am I missing?

This is the document you are refeering to right?

https://github.com/openmobilityfoundation/mobility-data-specification/tree/main/policy

@jackdreillyvia
Can you please edit out the emails from your posts where you site from the mail-list? Thank you

Apologies for that, I just noticed your request now. I've edited out identifiable information from the email.

@schnuerle
Copy link
Member Author

Based on this discussion, what are some proposals people have for modifying Policy or other parts of MDS so that stops can be communicated via Policy from the city?

Question, can stops be defined with a rule using trip_end states (and speed=0) with point or polygon geographies? Throwing in a $1 rate subsidy example with it.

This is how Louisville is handling this now. If this is good it should be added to the examples.

{
  "policy_id": "d2567b3c-3071-48a6-bbeb-3424721dbd12",
  "published_date": 1586736000000,
  "name": "Preferred Vehicles Stopping Locations",
  "description": "Places where riders are encouraged to end their trip and park. Some of these are physical corrals and some are spray painted on the street.",
  "messages": {
    "en-US": "Thank you for parking in a preferred location."
  },
  "start_date": 1586822400000,
  "end_date": 1587427200000,
  "prev_policies": null,
  "rules": [
    {
      "name": "Stops",
      "rule_id": "4137a47c-836a-11ea-bc55-0242ac130003",
      "rule_type": "speed",
      "rule_units": "mph",
      "minimum": 0,
      "maximum": 0,
      "rate_amount": "100",
      "rate_recurrence": "once",
      "geographies": [
        "b4bcc213-4888-48ce-a33d-4dd6c3384bda"
      ],
      "states": {
        "available": [
          "trip_end"
        ]
      }
    }
  ]
}

If this not accurate, then what needs to be changed to communicate a stop? What would your edits be to this example? It's almost as if rule_type is irrelevant (optional?) for this 'Stops' purpose. You just want a rule to refer to a geometry for a trip end status.

This is where I think a change is needed to more clearly support stops. Eg, a rule_type called "stop"? I think @jackdreillyvia is getting at this a bit here but in a different way, and I'm not sure a stop_id is best.

It also seems a bit counter intuitive to make it relevant on the 'available' state, though I realize that's where trip_end is. You want to encourage people who are on_trip to take this action, not after their trip is over. And that affects the messages text. But maybe this is just how it needs to be.

@jackdreillyvia
Copy link

@schnuerle The main use-case we have with cities is in defining geographical regions where vehicles must be parked. For this purpose, it's not strictly necessary to use stops, just geographies. From the prior discussions above w/ @Karcass it appears sufficient to implement our use-case with 2 rules:

  1. allow-parking in inner-geographical regions, up to a maximum count equal to the stop's capacity
  2. disallow-parking in the outer geographical region

As a counter-argument to your example of rule-types being irrelevant for stops-related policies, it's evident that our policy would actually leverage rule_type=count, and is not ignored or optional in this case.

Admittedly, my proposal above was meant to serve as a straw-man to understand what are the specific requirements that others need from stops in policies. Since a stop is just a geography w/ additional properties, it's hard to ascertain use-cases where stops are strictly necessary to specify a rule, thus the proposal to make a link between stop-capacity and policy-max-count. But this link may be too implicit and more confusing than helpful. So we're keen to hear others' ideas on what is the best way to evolve the specification.

@jackdreillyvia
Copy link

jackdreillyvia commented Nov 6, 2020

Following up on our conversation in the meeting last night, I give an example policy which dictates, within the downtown region, parking of scooters and bicycles must take place within specific geographies.

{
  "name": "Test City Mobility Hubs",
  "description": "Enforced parking in specific mobility hubs for downtown area",
  "policy_id": "99f7a469-6e3a-4981-9313-c2f6c0bbd5ce",
  "start_date": 1558389669540,
  "end_date": null,
  "published_date": 1558389669540,
  "prev_policies": null,
  "rules": [
    {
      "name": "Allow parking in specific locations",
      "rule_id": "8a61de66-d9fa-4cba-a38d-5d948e2373fe",
      "minimum": 0,
      "rule_type": "count",
      "rule_units": "devices",
      "geographies": [
        "e3ed0a0e-61d3-4887-8b6a-4af4f3769c14",
        "1512a3f4-313c-45fc-9fae-0dca6d7ab355"
      ],
      "states": {
        "available": ["trip_end"]
      },
      "vehicle_types": ["bicycle", "scooter"]
    },
    {
      "name": "Disallow parking elsewhere in downtown area",
      "rule_id": "0240899e-a8ad-4263-953a-6e278ff859ab",
      "rule_type": "count",
      "maximum": 0,
      "rule_units": "devices",
      "geographies": ["075a5303-2571-4ca5-b429-841bcc4025d1"],
      "states": {
        "available": ["trip_end"]
      },
      "vehicle_types": ["bicycle", "scooter"]
    }
  ]
}

@marie-x
Copy link
Collaborator

marie-x commented Nov 6, 2020

That's how I'd do it. ;). Although you could also omit the maximum and put minimum: 0 as a way to express that it's unlimited.

@jackdreillyvia
Copy link

That's how I'd do it. ;). Although you could also omit the maximum and put minimum: 0 as a way to express that it's unlimited.

Thanks, I've included your suggestion above

@schnuerle
Copy link
Member Author

FYI @jackdreillyvia I added your example to this branch.

@schnuerle
Copy link
Member Author

schnuerle commented Nov 19, 2020

Based on the consensus and discussions, I've added stops to policy rules here.

@schnuerle schnuerle linked a pull request Nov 19, 2020 that will close this issue
@schnuerle
Copy link
Member Author

This feature was pulled for this release, but we can discuss for next release in a larger context.

@schnuerle schnuerle modified the milestones: 1.1.0, Future Dec 9, 2020
@schnuerle
Copy link
Member Author

We will be talking about this on today's working group call. Please join if you can.

@schnuerle
Copy link
Member Author

See meeting minutes here.

There are three main use cases for stops

  1. For providers to communicate to agencies the features and status of their own dedicated docking/charging infrastructure in the public right of way.
    • This is what is implemented now since MDS 1.0.0 in Provider
    • In beta. Not in use enough yet to know how to improve it or move it out of beta.
    • Examples: Docked bikeshare, scooter charing stations
  2. For cities to communicate to providers where required or preferred parking locations are.
    • Would be added to Policy via a change
    • Policy handles this now so it's not an urgent necessity, but it's a little clunky/unclear.
    • Examples: spray painted corrals, required parking areas, lock to hardware
  3. For cities to communicate to providers/public the current occupancy of generic charging/docking infrastructure so they know whether to direct riders to that location or not
    • Not currently in existence as far as we know. Could be a future possibility
    • Examples: City owned universal charing station for multiple providers to use

The discussion for this issue is aligned to use case number 2. It may be that the way Policy works now, we don't need to modify it to more explicitly support a 'Stop' concept.

@schnuerle schnuerle removed this from the Future milestone Aug 11, 2021
@schnuerle
Copy link
Member Author

Implemented with PR #603 in MDS 1.1.0.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Policy Specific to the Policy API
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants