Skip to content

Grand Unified Obstacle Treatment #7130

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

Merged
merged 8 commits into from
Mar 19, 2025

Conversation

MarcelloPerathoner
Copy link
Contributor

@MarcelloPerathoner MarcelloPerathoner commented Mar 15, 2025

Issue

Currently OSRM:

  • does not take into account stop signs, give-way signs, and crossings,
  • does not take into account traffic calming,
  • does not take into account designated turning points,
  • uses separate code-paths for traffic signals and barriers.

This patch

  • implements stop signs and give-way signs,
    • understands 'minor' stop signs,
    • can infer stop direction from adjacent edge lengths,
  • implements designated turning points,
  • allows for multiple obstacles at a single node,
  • implements a single code-path for all kinds of obstacles like: traffic signals, stop
    signs, barriers, traffic calming, and turning points,
    • reduces the (already crowded) signature of many functions.

Related work

Similar to pull requests: #6426, #6153, #4828. Thanks to their authors, who gave many ideas.

Fixes issue: #7089

Implementation description

A class ObstacleMap singleton is injected globally into the LUA scripting environment.
The ObstacleMap offers functions to add and query different kinds of 'obstacle' nodes.
(For want of a better name since 'waypoint' was already taken.)

The LUA process_node() function (repeatedly) calls ObstacleMap::add() to register
discovered obstacles. This function is thread safe. The data is directly stored in the
final place and not moved again after.

A compatibilty layer for process_node() has been provided to emulate the current
behaviour: to return result.barrier and result.traffic_signal.

The LUA process_turn() function can call ObstacleMap::any() and ObstacleMap::get() to
retrieve registered obstacles.

The length of the road has been added to the ExtractionTurnLeg LUA table and legs for
the start and target roads have been added to ExtractionTurn (a parameter of process_turn()).

Tasklist

@DennisOSRM
Copy link
Collaborator

DennisOSRM commented Mar 15, 2025

Thanks so much for the pull request. This looks very nice, indeed. I love the simplification of the code, the documentation, and the added tests look well written at first glance. Once CI passes, I will do a deeper review.

From the first impression, this patch has a high chance of getting merged. Well done. 👍

Copy link
Collaborator

@DennisOSRM DennisOSRM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks pretty good to me. Left some minor comments that should be easy to address. The only bigger question is around the use of the extern keyword which should be avoided. Again, thanks so much for the contribution.

RoadPriorityClass::Enum priority_class;
bool is_incoming;
bool is_outgoing;
};

extern const std::vector<ExtractionTurnLeg> NO_OTHER_ROADS;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the extern keyword needed here? We should avoid it, if possible, since it implies a global variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

//
// This may be a completely impassable obstacle like a barrier, a temporary obstacle
// like a traffic light or a stop sign, or an obstacle that just slows you down like a
// traffic calming bump. The obstacle may be present in both directions or in one
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// traffic calming bump. The obstacle may be present in both directions or in one
// traffic calming bump. The obstacle may be present in both directions or in one

//
struct Obstacle
{
// clang-format off
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How bad does it look with formatting on?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.


// The type of an obstacle
// Note: must be kept in sync with scripting_environment_lua.cpp
enum class Type : uint16_t
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance to factor this out into the same header?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can try. But then it is the same story with all enums passed to sol / LUA.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, then let's not overthink it. We can leave the enum as is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to pull it into the obstacles.cpp file but not into the header. In the header I had to use a constexpr, but the Microsoft compiler choked on it.

// pass SPECIAL_NODEID as 'from' to get all obstacles at 'to'
// 'type' can be a bitwise-or combination of Obstacle::Type
using GetType =
boost::any_range<Obstacle, boost::forward_traversal_tag, Obstacle, std::ptrdiff_t>;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance to implement this without boost?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can try

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sol does not recognize a std::ranges::subrange as a container. It did recognize a boost::any_range though. As a compromise I used a std::vector hoping the performance hit is not too bad.

@@ -0,0 +1,53 @@
-- Assigns obstacle value to node as defined by
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-- Assigns obstacle value to node as defined by
-- Assigns obstacle value to nodes as defined by

function Obstacles.process_node(profile, node)
local highway = node:get_value_by_key("highway")
if highway then
local typ = obstacle_type[highway]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should the variable name be type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought type was reserved in LUA, but it is not. Will change.


void ObstacleMap::fixupNodes(const NodeIDVector &node_ids)
{
const NodeIDVector::const_iterator begin = node_ids.cbegin();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps use the auto keyword?

Copy link
Collaborator

@DennisOSRM DennisOSRM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 well done

@@ -99,11 +99,12 @@ void handle_lua_error(const sol::protected_function_result &luares)
const auto msg = luaerr.what();
if (msg != nullptr)
{
std::cerr << msg << "\n";
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is why some tests are flaky. std::cerr is not thread-safe.

@DennisOSRM DennisOSRM merged commit 7ee6245 into Project-OSRM:master Mar 19, 2025
21 checks passed
fenwuyaoji pushed a commit to fenwuyaoji/osrm-backend that referenced this pull request Mar 25, 2025
* Grand Unified Obstacle Treatment

* add changelog

* Address comments

* fix formatting

* fix ci

* fix ci

* fix ci

* simplify ObstacleMap::get
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants