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

Work on support relations in lua profiles #4438

Merged
merged 17 commits into from
Sep 14, 2017
Merged

Work on support relations in lua profiles #4438

merged 17 commits into from
Sep 14, 2017

Conversation

deniskoronchik
Copy link
Contributor

@deniskoronchik deniskoronchik commented Aug 24, 2017

Issue

#482

Tasklist

  • Add process_relation function into lua
  • Add parameter relation_data to process_way and process_node
  • Process relations logic (C++)
  • Change lua API to 3, an support this
  • Automation tests of new LUA features
  • Update documentation

@emiltin
Copy link
Contributor

emiltin commented Aug 24, 2017

very nice to see work on relation support :-)

@@ -284,7 +361,7 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"id",
&osmium::Node::id,
"version",
&osmium::Way::version);
&osmium::Node::version);
Copy link
Member

Choose a reason for hiding this comment

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

Good catch!

@TheMarex TheMarex added this to the 5.12.0 milestone Aug 30, 2017
@deniskoronchik
Copy link
Contributor Author

This version have some problems:

  • old restriction mechanism still using (need to replace it in future);
  • can pass just string values to process_relation result (maybe can be changed with boost::any)

@daniel-j-h
Copy link
Member

Great to see this moving forward! As a first use-case we should pass on cardinal directions from the route relation onto it's containing way members.

For now we're good with concatenating the route's cardinal direction (North, South, ..) onto the way's ref property.

In future versions (probably v6) we might want to reconsider this and properly split it off into own properties: #3304.

@TheMarex TheMarex modified the milestones: 5.13, 5.12.0 Aug 31, 2017
Copy link
Contributor

@oxidase oxidase left a comment

Choose a reason for hiding this comment

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

LGTM! Please add some feature tests with test profiles to show how data will look on Lua side.

Argument | Description
---------|-------------------------------------------------------
profile | The configuration table you returned in `setup`.
node | The input relation to process (read-only).
Copy link
Contributor

Choose a reason for hiding this comment

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

node -> relation

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

namespace detail
{

inline const char * checkedString(const char * str)
Copy link
Contributor

Choose a reason for hiding this comment

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

is it used somewhere? pls remove if will not be used

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

namespace util
{

class OsmIDTyped
Copy link
Contributor

Choose a reason for hiding this comment

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

Just as an alternative you can use union as

union OsmIDTyped
{
    OsmIDTyped(std::uint64_t id, std::uint8_t type) : detail{id, type} {}
    std::uint64_t hash;
    std::uint64_t GetID() const { return detail.id; }
    std::uint8_t GetType() const { return detail.type; }
private:
    struct
    {
        std::uint64_t id : 56;
        std::uint8_t type;
    } detail;
};

Copy link
Contributor Author

@deniskoronchik deniskoronchik Sep 1, 2017

Choose a reason for hiding this comment

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

I've think about this. And decide that it's not normal for OSRM (haven't seen union in project). If it good, i can do that.

for (const auto &result : parsed_buffer->resulting_restrictions)
{
extractor_callbacks->ProcessRestriction(result);
}
});

/* Main trick that we can use the same pipeline. It just receive relation objects
Copy link
Contributor

Choose a reason for hiding this comment

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

Another trick is to use HOF that returns a function that captures a reader as

    Reader reader1, reader2;
    auto make_buffer_reader = [](Reader& reader) {
                                  return [&reader]() { reader.bark(); };
                              };


    make_buffer_reader(reader1)();
    make_buffer_reader(reader2)();

and use on-stack allocated readers.

So pipelines will be

{
    osmium::io::Reader reader(input_file, osmium::osm_entity_bits::relation,...);
    tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 1.5,
                           make_buffer_reader(reader) & buffer_transform & buffer_storage_relation);
}
{
    osmium::io::Reader reader(input_file, osmium::osm_entity_bits::node | osmium::osm_entity_bits::way,,...);
   tbb::parallel_pipeline(tbb::task_scheduler_init::default_num_threads() * 1.5,
                            make_buffer_reader(reader) & buffer_transform & buffer_storage);
}

It also can be n

Copy link
Contributor Author

@deniskoronchik deniskoronchik Sep 1, 2017

Choose a reason for hiding this comment

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

yeah, that also was an idea. But there are some code that request reader before: ed5e00f#diff-edf14d92e413123a2b940ab0b8491ffbR298

This approach is much cleaner for me. But it can be implemented if we will create another reader to get header info.

osmium::item_type GetItemType() const { return item_type; }
osmium::object_id_type GetId() const { return id; }

util::OsmIDTyped ref() const { return util::OsmIDTyped(id, std::uint8_t(item_type)); }
Copy link
Contributor

Choose a reason for hiding this comment

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

conversion of osmium::item_type to std::uint8_t must be a hidden in OsmIDTyped

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You talk about store std::uint8_t instead of osmium::item_type or something else?

id = member.ref();
}

const char* GetRole() const { return role.c_str(); }
Copy link
Contributor

Choose a reason for hiding this comment

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

you don't need accessor function with pubic data members , it is better to pass references to sol and set r/o access as sol::readonly( &RelationMemberWrap::role )

Copy link
Contributor Author

@deniskoronchik deniskoronchik Sep 1, 2017

Choose a reason for hiding this comment

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

Then it would be a problem:

relation:id() -- used for nodes and ways before
member:role() -- will be similar
-- instead of
member:role

"members", [](const osmium::Relation &rel)
{
std::vector<RelationMemberWrap> members(rel.members().size());
size_t i = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

std::copy(...) of rel.members() to memeber?

@@ -276,6 +288,71 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"version",
&osmium::Way::version);

struct RelationMemberWrap
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not to expose osmium::RelationMember directly to avoid copying role strings?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Because it has deleted a lot of constructors and operators. So it doesn't compiles with sol.
I've tried for example:

context.state.new_usertype<osmium::Relation>("Relation",
                                                 "get_value_by_key",
                                                 &get_value_by_key<osmium::Relation>,
                                                 "id",
                                                 &osmium::Relation::id,
                                                 "version",
                                                 &osmium::Relation::version,
                                                 "members",
                                                 [](const osmium::Relation &rel) {
                                                     return sol::as_table(rel.members());
                                                 });

Copy link
Contributor

Choose a reason for hiding this comment

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

The wrapper can be removed return sol::as_table(rel.members()); should work well

@@ -1 +1 @@
n1 v1 dV c1 t2014-01-01T00:00:00Z i1 utest T x1.02 y1.02
Copy link
Contributor

Choose a reason for hiding this comment

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

This must be reverted

Copy link
Contributor Author

@deniskoronchik deniskoronchik Sep 1, 2017

Choose a reason for hiding this comment

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

Can't do that until will be fixed in master. It create this one automatically with git on any rebase. So moved it to a separate commit, that will be removed on fixed master rebase

docs/profiles.md Outdated
@@ -130,7 +130,7 @@ Attribute | Type | Notes
barrier | Boolean | Is it an impassable barrier?
traffic_lights | Boolean | Is it a traffic light (incurs delay in `process_turn`)?

## process_way(profile, way, result)
### process_way(profile, way, result)
Copy link
Contributor

Choose a reason for hiding this comment

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

form the code process_way has the 4th relations argument but here it is not mentioned

Should it be may be optional ? I feel we need some sort of sync here with location-dependent tags, that I would like to see optional. So we can add an additional positional argument that will hold a table with optional data items.
This will save from bumping api version every time when a new piece of data will be added to lua callback functions.

@deniskoronchik
Copy link
Contributor Author

@oxidase have test features of api_version 3: https://github.com/Project-OSRM/osrm-backend/pull/4438/files#diff-c86e1caf4e4a3c911f176b8f8b1c0d87

Or need more and if yes, then where to place them?

@oxidase
Copy link
Contributor

oxidase commented Sep 1, 2017

@deniskoronchik test looks good, somehow i missed it during review

Copy link
Member

@danpat danpat left a comment

Choose a reason for hiding this comment

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

Basic approach LGTM - only one minor comment for the OSMIDTyped class.

@deniskoronchik If you think there's a good reason not to make the type field an enum, then it's OK to not change it, but please add a code comment describing what the type field represents.

@deniskoronchik Can you please add an entry to CHANGELOG.md, then I think this is good to merge.

inline HashType Hash() const { return (std::uint64_t(id) | std::uint64_t(type) << 56); }

std::uint64_t GetID() const { return id; }
std::uint8_t GetType() const { return type; }
Copy link
Member

Choose a reason for hiding this comment

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

I think it would be good to do what osmium does here and make type an enum. We should have an explicit mapping from the osmium::item_type enum values to our own internal values.

osmium::item_type GetItemType() const { return item_type; }
osmium::object_id_type GetId() const { return id; }

util::OsmIDTyped ref() const { return util::OsmIDTyped(id, std::uint8_t(item_type)); }
Copy link
Member

Choose a reason for hiding this comment

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

This is the other side to my comment on OsmIDTyped - I think we should be very explicit about what values we store here. Something like:

switch(item_type) {
  case osmium::item_type.node:
      return util::OsmIDTyped(id, osrm::extractor::OSMIDType.NODE);
  case osmium::item_type.way:
      return util::OsmIDTyped(id, osrm::extractor::OSMIDType.WAY);
  default:
     throw util::exception("some error message");
}

Copy link
Contributor Author

@deniskoronchik deniskoronchik Sep 8, 2017

Choose a reason for hiding this comment

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

@danpat done there 5bd29dd

@1ec5
Copy link
Member

1ec5 commented Sep 8, 2017

Great to see this moving forward! As a first use-case we should pass on cardinal directions from the route relation onto it's containing way members.

For now we're good with concatenating the route's cardinal direction (North, South, ..) onto the way's ref property.

In future versions (probably v6) we might want to reconsider this and properly split it off into own properties: #3304.

Note that simply appending onto the ways’ ref property will produce incorrect refs for many route concurrencies in the U.S.: Project-OSRM/osrm-text-instructions#119 (comment).

Copy link
Contributor

@oxidase oxidase left a comment

Choose a reason for hiding this comment

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

LGTM! I still think that most of c++ wrappers can be removed, because sol2 is really great library and can create such wrappers invisible. Also it reduces copying data c++ -> lua -> c++

I can attach a patch or commit later a cleanup

@@ -366,6 +499,45 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
sol::property([](const ExtractionWay &way) { return way.backward_restricted; },
[](ExtractionWay &way, bool flag) { way.backward_restricted = flag; }));

struct ExtractionRelationData
Copy link
Contributor

Choose a reason for hiding this comment

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

The wrapper is not really needed. sol2 understands lambda return types:

    context.state.new_usertype<ExtractionRelation>(
        "ExtractionRelation",
        sol::meta_function::new_index,
        [](ExtractionRelation &rel, const RelationMemberWrap &member) -> ExtractionRelation::AttributesMap& {
            return rel.GetMember(member.ref());
        },
        sol::meta_function::index,
        [](ExtractionRelation &rel, const RelationMemberWrap &member) -> ExtractionRelation::AttributesMap& {
            return rel.GetMember(member.ref());
        },
        "restriction",
        sol::property([](const ExtractionRelation &rel) { return rel.is_restriction; },
                      [](ExtractionRelation &rel, bool flag) { rel.is_restriction = flag; }));

below

}

namespace osrm
{
namespace extractor
{

class RelationsContainerWrap
Copy link
Contributor

Choose a reason for hiding this comment

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

The wrapper is not needed and can be removed. Also context.state.new_usertype<RelationsContainerWrap>( ... can be removed. Relations can be forwarded to lua as

node_function(profile_table, node, result, sol::as_table(relations));
...
way_function(profile_table, way, result, sol::as_table(relations));sol::as_table(relations)

ExtractionRelation::AttributesMap &attrs;
};

context.state.new_usertype<RelationsContainerWrap>(
Copy link
Contributor

Choose a reason for hiding this comment

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

Not needed

sol::meta_function::index,
[](const RelationsContainerWrap &rel, size_t index) { return rel.GetAttributes(index); });

context.state.new_usertype<ExtractionRelationData>(
Copy link
Contributor

Choose a reason for hiding this comment

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

not needed

context.state.new_usertype<ExtractionRelation>(
"ExtractionRelation",
sol::meta_function::new_index,
[](ExtractionRelation &rel, const RelationMemberWrap &member) {
Copy link
Contributor

Choose a reason for hiding this comment

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

add -> ExtractionRelation::AttributesMap&

return ExtractionRelationData(rel.GetMember(member.ref()));
},
sol::meta_function::index,
[](ExtractionRelation &rel, const RelationMemberWrap &member) {
Copy link
Contributor

Choose a reason for hiding this comment

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

add add -> ExtractionRelation::AttributesMap&``

@@ -276,6 +288,71 @@ void Sol2ScriptingEnvironment::InitContext(LuaScriptingContext &context)
"version",
&osmium::Way::version);

struct RelationMemberWrap
Copy link
Contributor

Choose a reason for hiding this comment

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

The wrapper can be removed return sol::as_table(rel.members()); should work well

@oxidase
Copy link
Contributor

oxidase commented Sep 14, 2017

@deniskoronchik @TheMarex i have removed Lua 5.1 support because ThePhD/sol2#302 makes relations wrapping too complicated and requires copying of members for every node/way.

ATM windows build failed, because it requires Lua 5.1 -> 5.2 update.
I will try to build dependencies locally and update osrm-deps-win-x64-14.0.7z

@oxidase oxidase merged commit c065335 into Project-OSRM:master Sep 14, 2017
mloskot added a commit to mloskot/osrm-backend that referenced this pull request Jan 5, 2018
Pool instance has been removed from Reader ctor parameters
list in PR Project-OSRM#4438, presumably unintentionally.
It is required to prevent potential deadlock during
Pool shutdown as explained in PR Project-OSRM#4452.
mloskot added a commit to mloskot/osrm-backend that referenced this pull request Jan 5, 2018
Pool instance has been removed from Reader ctor parameters
list in PR Project-OSRM#4438, presumably unintentionally.
It is required to prevent potential deadlock during
Pool shutdown as explained in PR Project-OSRM#4452.
mloskot added a commit to mloskot/osrm-backend that referenced this pull request Jan 5, 2018
Pool instance has been removed from Reader ctor parameters
list in PR Project-OSRM#4438, presumably unintentionally.
It is required to prevent potential deadlock during
Pool shutdown as explained in PR Project-OSRM#4452.
oxidase pushed a commit that referenced this pull request Jan 7, 2018
Pool instance has been removed from Reader ctor parameters
list in PR #4438, presumably unintentionally.
It is required to prevent potential deadlock during
Pool shutdown as explained in PR #4452.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants