From 808f3e6ba796b3c243ac4b1c14b07d9d3ed56738 Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Thu, 18 Nov 2021 22:35:11 +0100 Subject: [PATCH 01/37] Draft for discussion: Logical Lanes in OSI This patch shows how logical lanes could be implemented inside OSI. These logical lanes (plus the lane assignments) would make it much easier to create agent models that work on OSI. For OpenDRIVE, the new data structures ensure that the lane information from OpenDRIVE is not lost (currently all the junction lane information from OpenDRIVE cannot be represented in OSI). Signed-off-by: Thomas Bleher --- CMakeLists.txt | 1 + osi_common.proto | 47 +++++ osi_groundtruth.proto | 13 ++ osi_logicallane.proto | 471 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 532 insertions(+) create mode 100644 osi_logicallane.proto diff --git a/CMakeLists.txt b/CMakeLists.txt index 1acc23fcf..634f22cdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,6 +76,7 @@ set(OSI_PROTO_FILES osi_trafficcommand.proto osi_roadmarking.proto osi_lane.proto + osi_logicallane.proto osi_featuredata.proto osi_logicaldetectiondata.proto osi_object.proto diff --git a/osi_common.proto b/osi_common.proto index 5085541c1..de46801c2 100644 --- a/osi_common.proto +++ b/osi_common.proto @@ -338,6 +338,45 @@ message Spherical3d optional double elevation = 3; } +// +// \brief Assignment of an object to a logical lane +// +// An object is assigned to a logical lane if it overlaps the logical lane. +// Assignment happens even if the reference point is outside the lane, and only +// a part of the object overlaps. +// +// As an exception to this, \c TrafficSign and \c TrafficLight are assigned to +// a logical lane if they control traffic on that lane. +// +message LogicalLaneAssignment +{ + // ID of the LogicalLane the object is assigned to. + // + optional Identifier assigned_lane_id = 1; + + // S position of the object reference point on the lane, in the ST + // coordinate system of the lane. + // + // s_position might be outside [s_start,s_end] of the lane (and even + // outside [startS,endS] of the reference line) if the reference point is + // outside the lane, but the object overlaps the lane or a TrafficSign or + // TrafficLight is assigned to a lane. + // + optional double s_position = 2; + + // T position of the object reference point on the lane, in the ST + // coordinate system of the lane. + // + optional double t_position = 3; + + // Angle of the object relative to the lane. + // See the ReferenceLine description how the angle is calculated. + // + // Unit: rad + // + optional double angle_to_lane = 4; +} + // // \brief The base attributes of a stationary object or entity. // @@ -398,6 +437,10 @@ message BaseStationary // The polygon is defined counter-clockwise. // repeated Vector2d base_polygon = 4; + + // Assignment of this object to logical lanes + // + repeated LogicalLaneAssignment logical_lane_assignment = 5; } // @@ -520,6 +563,10 @@ message BaseMoving // The polygon is defined counter-clockwise. // repeated Vector2d base_polygon = 7; + + // Assignment of this object to logical lanes + // + repeated LogicalLaneAssignment logical_lane_assignment = 9; } // diff --git a/osi_groundtruth.proto b/osi_groundtruth.proto index 10f9dceae..fc6920e3f 100644 --- a/osi_groundtruth.proto +++ b/osi_groundtruth.proto @@ -9,6 +9,7 @@ import "osi_trafficsign.proto"; import "osi_trafficlight.proto"; import "osi_roadmarking.proto"; import "osi_lane.proto"; +import "osi_logicallane.proto"; import "osi_object.proto"; import "osi_occupant.proto"; @@ -171,4 +172,16 @@ message GroundTruth // derives street geometries automatically from a map reference. // optional string model_reference = 16; + + // Reference lines used by LogicalLane + // + repeated ReferenceLine reference_line = 17; + + // Logical lane boundaries used by LogicalLane + // + repeated LogicalLaneBoundary logical_lane_boundary = 18; + + // Logical lanes used e.g. by traffic agents + // + repeated LogicalLane logical_lane = 19; } diff --git a/osi_logicallane.proto b/osi_logicallane.proto new file mode 100644 index 000000000..e8e90d2bd --- /dev/null +++ b/osi_logicallane.proto @@ -0,0 +1,471 @@ +syntax = "proto2"; + +option optimize_for = SPEED; + +import "osi_common.proto"; +import "osi_lane.proto"; + +package osi3; + +// +// \brief A reference line for defining a non-euclidean ST coordinate system +// +// A reference line is a 3D polyline, used for generating a non-euclidean +// ST coordinate system. +// +// Notes on design decisions: +// - This is a polyline, and not some more complex curve. The advantage of a +// polyline is that it is very simple to generate from various map formats, +// and it is also easy to handle. The downside is that a polyline has no +// direct curvature, and even the angle is not continuous (only C0 smooth). +// In the author's experience, the benefits of a polyline outweigh the costs. +// +// TODO Test whether the current definition is good enough for wide roads with +// strong curvature (e.g. roundabouts with several lanes). +// +message ReferenceLine +{ + // The ID of the logical lane. + // + // \note Note ID is global unique. + // + // \rules + // is_globally_unique + // \endrules + // + optional Identifier id = 1; + + // Points comprising the polyline. + // + // At least 2 points must be given. + // The polyline is defined as the lines between consecutive points. + // Each point has an S coordinate. There are a few requirements on the S + // position: + // - Later points in the list must have strictly larger S coordinates than + // earlier points. + // - For consecutive points, the S difference between them must be at + // least as large as the 2D euclidean distance between the points (2D + // distance == euclidean distance between the points taking only X and Y + // into account). + // - The S distance between two points may be larger than the 2D euclidean + // distance, but should be not much larger. It is allowed to be larger if + // the underlying reference line (e.g. in an OpenDRIVE map) is a curve, + // and thus the sampled road has a smaller length than the original + // curve. + // + // Together, these rules allow directly putting OpenDRIVE S coordinates + // into an OSI ReferenceLine. + // + // Between to ReferenceLinePoints, both the world coordinate and the S + // coordinate is interpolated linearly. So each S value uniquely describes + // a point on the polyline. + // + // For the purpose of this discussion, let's call the S position of the + // first point sStart, and the S position of the last point sEnd. + // + // For some purposes, S positions outside the normally defined range (i.e. + // outside [sStart,sEnd]) need to be defined. For this purpose, the first + // line of the polyline is infinitely extended in negative S direction. + // Similarly, the last line of the polyline is infinitely extended beyond + // the last point. The S value of points outside [sStart,sEnd] is defined + // by the euclidean 2D distance from the start or end point, respectively. + // So if sStart = 15, and a point is on the line extended from the start + // position, with a 2D euclidean distance of 10 from the first point, then + // it has an S position of 5. + // + // A point is "before" the reference line, if its s coordinate is < sStart. + // A point is "after" the reference line, if its s coordinate is > sEnd. + // + // To describe points that are not directly on the polyline, a T + // coordinate is added. T is the signed 2D distance (i.e. hypot(A.X-B.X, + // A.Y-B.Y), if A and B are the two points) between the point to describe + // and the nearest point on the polyline (this point might either be on a + // line segment or at an edge between two line segments). The distance is + // positive if the point is left of the polyline (in definition direction), + // negative if it is right of it. Note that the "nearest point on the + // polyline" is calculated in 3D, in order to choose the correct point for + // 3D curves (think reference lines for roads in parking decks). If there + // are several "nearest points", the one with the smallest S coordinate on + // the polyline is chosen. + // + // Sometimes an angle to a reference line is needed. This shall be defined + // as follows: + // First the nearest point on the polyline is determined, as described + // above. If this point is on a line segment, then the angle is calculated + // relative to the line segment on which the reference point lays. + // If the nearest point is at the edge between line segments, then the + // angle of the following line shall be chosen. + // + // Notes on OpenDRIVE compatibility: + // Ideally, one would want the polyline to be fully compatible with + // OpenDRIVE, so that calculations done for OpenDRIVE directly match those + // in OSI. There are a few difficulties with this: + // - The T coordinate is nearly the same as for OpenDRIVE, but + // unfortunately not perfectly. In OpenDRIVE, if the road is tilted using + // superElevation, then the t coordinate system is tilted along, so the T + // coordinate is no longer calculated in the XY plane (as proposed for + // OSI). It doesn't seem feasable to implement the same tilting for OSI, + // so simulation tools will have to consider superElevation and convert + // the T coordinate accordingly. + // - The angle will not be perfectly the same, due to the use of line + // segments in OSI, and curves in OpenDRIVE. In the authors opinion, the + // difference will be negligible if the poly_line is suitably sampled. + // + // Notes on design decisions: + // - The S coordinate is included directly, both for OpenDRIVE + // compatibility, and to speed up calculations. + // - The rules on S coordinates (e.g. the calculation in 2D space) are + // there to ensure OpenDRIVE compatibility. + // - The rules on T coordinates are there to ensure OpenDRIVE compatibility + // for lanes without superelevation, and to make it easier to convert + // between OSI and OpenDRIVE in case superelevation is present. + // + // TODO Describe needed precision. + // TODO Describe how large angles between line segments are allowed to be. + // + repeated ReferenceLinePoint poly_line = 2; + + // A point on the reference line + message ReferenceLinePoint { + // A world position + optional Vector3d world_position = 1; + + // S position on the reference line + optional double s_position = 2; + } +} + +// Like a LaneBoundary, but with a reference and ST positions. +// +// Notes on design decisions: +// - The LogicalLaneBoundary has ST coordinates, and is thus a separate type +// from LaneBoundary. +// Advantages of this decision: +// - Calculations like getting the lane width at a position are easy, since +// one can just get the boundary points of the left and right boundary at +// the desired S position (via linear interpolation), and calculate the +// width from the two points. Also getting something like the distance to +// the lane border is very easy. +// - No centerline of the lane is necessary, since this can very easily be +// generated from the boundaries. +// Disadvantages of this decision: +// - Lane boundaries cannot be shared with physical lanes. This results in +// more data needed. This can mostly be mitigated by only transmitting the +// lane boundaries during initialization (e.g. via the OSMP GroundTruthInit +// message). +// - The LogicalLaneBoundary contains all data directly which an agent model is +// likely to need. It does not include information normally only used by +// sensor models (e.g. the exact length of the color markings on the road). +// This information can be gotten from the physical lane referenced in the +// LogicalLane, if needed. +// +// TODO To Discuss: It would be entirely possible to add ST coordinates also to +// LaneBoundary. Then no separate type would be needed. However, it is unclear if +// the additional overhead is acceptable for sensor models. +// +message LogicalLaneBoundary +{ + // The ID of the lane boundary. + // + // \rules + // is_globally_unique + // \endrules + // + optional Identifier id = 1; + + // points making up the lane boundary. + // The boundary must be defined in the same direction as the reference + // line. So S positions should increase along the line. Note that S + // positions will not always increase strictly monotonically. + // Example: + // |---------\ + // | \ + // /---boundary--| \------------ + // / + // ---------- reference line -------------- + // At the place where the boundary suddenly increases, two points will have + // the same S coordinate. + // + repeated LogicalBoundaryPoint boundary_line = 2; + + // The reference line for this boundary. + // + // The reference line is used as a coordinate system for this boundary. + // All points of this LogicalLaneBoundary must have S coordinates in the + // range [sStart,sEnd]. + // + // The reference line should roughly have the same shape as the boundary, so + // that S coordinates continually increase along the lane. + // + optional Identifier reference_line_id = 3; + + // The classification of the lane boundary. + // + optional LaneBoundary.Classification classification = 4; + + // Optional external reference to the lane boundary source. + // + // \note For OpenDRIVE, there is no direct possibility to reference the + // RoadMark, as there is no unique identifier in this sub-object. + // + // \note For non-ASAM Standards, it is implementation-specific how + // source_reference is resolved. + // + // \note The value has to be repeated because one object may be derived + // from more than one origin source, for example, from a scenario file + // and from sensors. + // + repeated ExternalReference source_reference = 5; + + // A point on the boundary + // + message LogicalBoundaryPoint { + + // The position of the \c LaneBoundaryPoint. + // + optional Vector3d position = 1; + + // S position of the LaneBoundaryPoint, measured along the parent's + // reference_line_id. + // + optional double s_position = 2; + + // T position of the LaneBoundaryPoint, measured along the parent's + // reference_line_id. + // + optional double t_position = 3; + } +} + +// +// \brief A logical lane in the road network. +// +// A logical lane is part of a road. Compared to a physical lane (OSI type +// \c Lane), its existence doesn't hinge on the existence of road markings. So +// e.g. a narrow urban road with two driving directions but no road markings +// in-between would be presented as two LogicalLanes, but only one Lane. So one +// Lane can consist of multiple LogicalLanes. E.g. on intersections, each +// driving path is one LogicalLane, but the whole area is one \c Lane of type +// \c #TYPE_INTERSECTION. +// +// If OSI is generated from OpenDRIVE, then LogicalLanes map directly to +// OpenDRIVE lanes. However, it is allowed to merge multiple consecutive +// OpenDRIVE lanes with the same type into one OSI LogicalLane: if an OpenDRIVE +// lane has a single successor, which has the same lane type, and this +// successor has only one predecessor (so no lane merging or splitting) then +// the two lanes may be presented as one continuous LogicalLane. This may be +// done recursively. +// +// The reference line pointed to by reference_line_id defines an ST coordinate +// system for the lane. This ST coordinate system is used to describe positions +// on the lane. +// +message LogicalLane +{ + // The ID of the logical lane. + // + // \note Note ID is global unique. + // + // \rules + // is_globally_unique + // \endrules + // + optional Identifier id = 1; + + // The type of the logical lane. + // + optional Lane.Classification.Subtype type = 2; + + // Optional external reference to the lane source. + // + // The external reference points to the source of the lane, if it is derived + // from one or more objects or external references. + // + // For example, to reference a lane defined in an OpenDRIVE map + // the items should be set as follows: + // * reference = URI to map, can remain empty if identical with definiton + // in \c GroundTruth::map_reference + // * type = "net.asam.opendrive" + // * identifier[0] = id of t_road + // * identifier[1] = s of t_road_lanes_laneSection + // * identifier[2] = id of t_road_lanes_laneSection_left_lane, + // t_road_lanes_laneSection_right_lane + // + // \note For non-ASAM Standards, it is implementation-specific how + // source_reference is resolved. + // + // \note The value has to be repeated, because one lane segment may be + // derived from more than one origin segment. Multiple sources + // may be added as reference as well, for example, a map and sensors. + // + repeated ExternalReference source_reference = 3; + + // Reference to the physical lane this logical lane belongs to. + // + // This makes it possible to get detailed information on the physical lane + // properties, e.g. the visual colors of the boundaries, the road + // condition, etc.. + // + // TODO Should this be a repeated field? Imagine the following scenario: + // --------------------------------- + // l1 l2 + // ---------- l3 --------- + // l4 l5 + // --------------------------------- + // + // In this case, we have five physical lanes: l1, l2, l4 and l5 where a + // lane marking is present. And l3 is one lane covering the whole road + // (because no road marking is present). + // + // Now there are two basic possibilities to define the logical lanes: + // - There could be two logical lanes: one encompassing l4, part of l3 and + // l5; another encompassing l2, part of l3 and l1. In this case, one + // logical lane can map to a number of physical lanes, and the mapping + // should include s positions, so it is clear which part of the logical + // lane maps to which physical lane. + // - There could be 6 logical lanes: l1, l2, l4, l5 and two lanes for each + // halve of l3. Then each logical lane would map to a single physical + // lane, but logical lanes would have to be split each time a lane + // marking appears or disappears. + // + optional Identifier physical_lane_id = 4; + + // The reference line for this logical lane + // + // The reference line is used as a coordinate system on this lane. + // + // The reference line should roughly have the same shape as the lane, so + // that S coordinates continually increase/decrease along the lane. It is + // not required that the reference line has the same direction as the + // driving direction of the lane. + // + // Neighbouring lanes are strongly encouraged to use the same + // reference_line, so that vehicles that are next to each other on + // neighbouring lanes have comparable S positions. + // + optional Identifier reference_line_id = 5; + + // Start S position of the lane. Must be in range [sStart,sEnd] of the + // reference line. + // + optional double start_s = 6; + + // End S position of the lane. Must be in range [sStart,sEnd] of the + // reference line. + // end_s > start_s + // + optional double end_s = 7; + + // Definition of the intended driving direction. + // + // \c true means driving direction is according to ascending S position. + // \c false means driving direction is according to descending S position. + // + optional bool reference_line_is_driving_direction = 8; + + // Lanes that are directly right of this lane, without gap or overlap. + // "Right" is in definition direction (not driving direction), so right lanes + // have smaller T coordinates. + // + repeated LaneRelation right_adjacent_lane = 9; + + // Lanes that are directly left of this lane, without gap or overlap. + // "Left" is in definition direction (not driving direction), so left lanes + // have larger T coordinates. + // + repeated LaneRelation left_adjacent_lane = 10; + + // Lanes that partially or completely overlap this lane. Only overlaps + // laterally larger than 5cm are considered overlaps for the purpose of + // this relation. + // + repeated LaneRelation overlapping_lane = 11; + + // Right boundary of this lane. + // References to LogicalLaneBoundary elements. + // All LogicalLaneBoundary elements referenced here must refer to the same + // ReferenceLine as this lane. + // The boundaries together must cover the whole length of the lane (the + // range [start_s,end_s]) without gap or overlap. + // + // TODO Is it allowed for the boundaries to be longer than the lane? + // Theoretically, this could be done. Then the user would have to limit the + // boundary itself to [start_s,end_s]. + // + repeated Identifier right_boundary_id = 12; + + // Left boundary of this lane. + // References to LogicalLaneBoundary elements. + // All LogicalLaneBoundary elements referenced here must refer to the same + // ReferenceLine as this lane. + // The boundaries together must cover the whole length of the lane (the + // range [start_s,end_s]) without gap or overlap. + // + // TODO Is it allowed for the boundaries to be longer than the lane? + // Theoretically, this could be done. Then the user would have to limit the + // boundary itself to [start_s,end_s]. + // + repeated Identifier left_boundary_id = 13; + + // Lanes that directly are connected to this lane at the beginning + // + repeated LaneConnection predecessor_lane = 14; + + // Lanes that directly are connected to this lane at the end + // + repeated LaneConnection successor_lane = 15; + + // Connection to another lane (predecessor or successor) + // + message LaneConnection { + + // Id of the other logical lane that is connected + // + optional Identifier other_lane_id = 1; + + // If true: LaneConnection is at the beginning of the other lane + // If false: LaneConnection is a the end of the other lane + // + optional bool at_begin_of_other_lane = 2; + + } + + // Relation of this lane to another logical lane + // + message LaneRelation { + + // Id of the other logical lane + // + optional Identifier other_lane_id = 1; + + // Start s position of the relation + // + optional double start_s = 2; + + // End s position of the relation + // + // Requirement: end_s > start_s + // + optional double end_s = 3; + + // Start s position of the relation on the other lane. + // + // This is the same place as start_s, but measured along the reference + // line of the other lane. + // + optional double start_s_other = 4; + + // End s position of the relation on the other lane. + // + // This is the same place as end_s, but measured along the reference + // line of the other lane. + // + // Note: end_s_other might be smaller than start_s_other + // + optional double end_s_other = 5; + } +} + +// TODO Traffic Agents also need the physical area of an intersection. This +// should be added to physical lanes of type TYPE_INTERSECTION. + From 4b317f11971e1bd142082cdbe62a1aa00d8db968 Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Tue, 23 Nov 2021 08:07:38 +0100 Subject: [PATCH 02/37] Fix a spelling error in osi_logicallane.proto Co-authored-by: clemenshabedank Signed-off-by: Thomas Bleher --- osi_logicallane.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osi_logicallane.proto b/osi_logicallane.proto index e8e90d2bd..ffe416687 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -56,7 +56,7 @@ message ReferenceLine // Together, these rules allow directly putting OpenDRIVE S coordinates // into an OSI ReferenceLine. // - // Between to ReferenceLinePoints, both the world coordinate and the S + // Between two ReferenceLinePoints, both the world coordinate and the S // coordinate is interpolated linearly. So each S value uniquely describes // a point on the polyline. // From 96b86185b5a890ab1bc18c4fa13ba910c99414c2 Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Tue, 23 Nov 2021 09:58:17 +0100 Subject: [PATCH 03/37] Adaptations from first round of review Signed-off-by: Thomas Bleher --- osi_common.proto | 7 ++++++- osi_logicallane.proto | 43 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/osi_common.proto b/osi_common.proto index de46801c2..446f96393 100644 --- a/osi_common.proto +++ b/osi_common.proto @@ -346,7 +346,12 @@ message Spherical3d // a part of the object overlaps. // // As an exception to this, \c TrafficSign and \c TrafficLight are assigned to -// a logical lane if they control traffic on that lane. +// a logical lane if they control traffic on that lane. For \c TrafficSign and +// \c TrafficLight , s_position refers to the position where the sign or light +// is valid (e.g. where vehicles should stop in case of a red traffic light), +// not the physical position (where the sign or light is in the world). +// Typically, t_position and angle_to_lane do not have any meaning in this +// case, and will be 0. // message LogicalLaneAssignment { diff --git a/osi_logicallane.proto b/osi_logicallane.proto index ffe416687..d1eda0256 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -56,6 +56,13 @@ message ReferenceLine // Together, these rules allow directly putting OpenDRIVE S coordinates // into an OSI ReferenceLine. // + // If the reference line approximates a curve (e.g. a clothoid in + // OpenDRIVE), the points must be chosen in a way that the lateral distance + // to the ideal line does not exceed 5cm. As shown in the following image: + // + // \image html line_approximation_error.svg "Approximation error" + // Approximation error green line. + // // Between two ReferenceLinePoints, both the world coordinate and the S // coordinate is interpolated linearly. So each S value uniquely describes // a point on the polyline. @@ -106,7 +113,8 @@ message ReferenceLine // coordinate is no longer calculated in the XY plane (as proposed for // OSI). It doesn't seem feasable to implement the same tilting for OSI, // so simulation tools will have to consider superElevation and convert - // the T coordinate accordingly. + // the T coordinate accordingly: t_OSI = t_OpenDRIVE * cos(alpha), where + // alpha is the superelevation angle. // - The angle will not be perfectly the same, due to the use of line // segments in OSI, and curves in OpenDRIVE. In the authors opinion, the // difference will be negligible if the poly_line is suitably sampled. @@ -120,9 +128,6 @@ message ReferenceLine // for lanes without superelevation, and to make it easier to convert // between OSI and OpenDRIVE in case superelevation is present. // - // TODO Describe needed precision. - // TODO Describe how large angles between line segments are allowed to be. - // repeated ReferenceLinePoint poly_line = 2; // A point on the reference line @@ -186,6 +191,21 @@ message LogicalLaneBoundary // At the place where the boundary suddenly increases, two points will have // the same S coordinate. // + // If the boundary approximates a curve (e.g. a cubic function in + // OpenDRIVE), the points must be chosen in a way that the lateral distance + // to the ideal line does not exceed 5cm. As shown in the following image: + // + // \image html line_approximation_error.svg "Approximation error" + // Approximation error green line. + // + // The Z error (difference in Z height between boundary_line and the "real" + // line) must also not exceed 5cm. + // + // Note: if two lanes have different Z heights (e.g. a driving lane is + // beside a sidewalk, where the sidewalk is 10cm higher than the road), + // then these lanes cannot share a boundary, since their boundaries have + // different Z heights. + // repeated LogicalBoundaryPoint boundary_line = 2; // The reference line for this boundary. @@ -366,18 +386,21 @@ message LogicalLane // Lanes that are directly right of this lane, without gap or overlap. // "Right" is in definition direction (not driving direction), so right lanes // have smaller T coordinates. + // Entries must be ordered: first by start_s, then by end_s. // repeated LaneRelation right_adjacent_lane = 9; // Lanes that are directly left of this lane, without gap or overlap. // "Left" is in definition direction (not driving direction), so left lanes // have larger T coordinates. + // Entries must be ordered: first by start_s, then by end_s. // repeated LaneRelation left_adjacent_lane = 10; // Lanes that partially or completely overlap this lane. Only overlaps // laterally larger than 5cm are considered overlaps for the purpose of // this relation. + // Entries must be ordered: first by start_s, then by end_s. // repeated LaneRelation overlapping_lane = 11; @@ -386,7 +409,11 @@ message LogicalLane // All LogicalLaneBoundary elements referenced here must refer to the same // ReferenceLine as this lane. // The boundaries together must cover the whole length of the lane (the - // range [start_s,end_s]) without gap or overlap. + // range [start_s,end_s]) without gap or overlap. The boundaries must be + // stored in ascending order, starting with the smallest S position. + // Consecutive boundaries must share a point: the last point of the + // previous boundary must be identical to the first point of the next + // boundary. // // TODO Is it allowed for the boundaries to be longer than the lane? // Theoretically, this could be done. Then the user would have to limit the @@ -399,7 +426,11 @@ message LogicalLane // All LogicalLaneBoundary elements referenced here must refer to the same // ReferenceLine as this lane. // The boundaries together must cover the whole length of the lane (the - // range [start_s,end_s]) without gap or overlap. + // range [start_s,end_s]) without gap or overlap. The boundaries must be + // stored in ascending order, starting with the smallest S position. + // Consecutive boundaries must share a point: the last point of the + // previous boundary must be identical to the first point of the next + // boundary. // // TODO Is it allowed for the boundaries to be longer than the lane? // Theoretically, this could be done. Then the user would have to limit the From 836b859afa6b010fd67ba55f5909e4d77199b174 Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Thu, 25 Nov 2021 16:15:30 +0100 Subject: [PATCH 04/37] Update osi_logicallane.proto: fix wrong mention of "road" instead of "reference line" Co-authored-by: clemenshabedank Signed-off-by: Thomas Bleher --- osi_logicallane.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osi_logicallane.proto b/osi_logicallane.proto index d1eda0256..ad2a7956d 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -50,7 +50,7 @@ message ReferenceLine // - The S distance between two points may be larger than the 2D euclidean // distance, but should be not much larger. It is allowed to be larger if // the underlying reference line (e.g. in an OpenDRIVE map) is a curve, - // and thus the sampled road has a smaller length than the original + // and thus the sampled reference line has a smaller length than the original // curve. // // Together, these rules allow directly putting OpenDRIVE S coordinates From f31bf822a1eeff32230571868fc0ada648c0b758 Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Fri, 7 Jan 2022 22:40:38 +0100 Subject: [PATCH 05/37] Logical Lanes: add a few refers_to rules Signed-off-by: Thomas Bleher --- osi_logicallane.proto | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/osi_logicallane.proto b/osi_logicallane.proto index ad2a7956d..25b8f63b7 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -217,6 +217,10 @@ message LogicalLaneBoundary // The reference line should roughly have the same shape as the boundary, so // that S coordinates continually increase along the lane. // + // \rules + // refers_to: ReferenceLine + // \endrules + // optional Identifier reference_line_id = 3; // The classification of the lane boundary. @@ -348,6 +352,10 @@ message LogicalLane // lane, but logical lanes would have to be split each time a lane // marking appears or disappears. // + // \rules + // refers_to: Lane + // \endrules + // optional Identifier physical_lane_id = 4; // The reference line for this logical lane @@ -363,6 +371,10 @@ message LogicalLane // reference_line, so that vehicles that are next to each other on // neighbouring lanes have comparable S positions. // + // \rules + // refers_to: ReferenceLine + // \endrules + // optional Identifier reference_line_id = 5; // Start S position of the lane. Must be in range [sStart,sEnd] of the @@ -419,6 +431,10 @@ message LogicalLane // Theoretically, this could be done. Then the user would have to limit the // boundary itself to [start_s,end_s]. // + // \rules + // refers_to: LogicalLaneBoundary + // \endrules + // repeated Identifier right_boundary_id = 12; // Left boundary of this lane. @@ -436,6 +452,10 @@ message LogicalLane // Theoretically, this could be done. Then the user would have to limit the // boundary itself to [start_s,end_s]. // + // \rules + // refers_to: LogicalLaneBoundary + // \endrules + // repeated Identifier left_boundary_id = 13; // Lanes that directly are connected to this lane at the beginning @@ -452,6 +472,10 @@ message LogicalLane // Id of the other logical lane that is connected // + // \rules + // refers_to: LogicalLane + // \endrules + // optional Identifier other_lane_id = 1; // If true: LaneConnection is at the beginning of the other lane @@ -467,6 +491,10 @@ message LogicalLane // Id of the other logical lane // + // \rules + // refers_to: LogicalLane + // \endrules + // optional Identifier other_lane_id = 1; // Start s position of the relation From 4ceb1a2fa0ec906eccebc7b1407e4fc6dd2c4c6e Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Fri, 7 Jan 2022 23:40:28 +0100 Subject: [PATCH 06/37] LogicalLaneBoundary: reference LaneBoundary, and add PassingRule The previous definition was incomplete, since it couldn't handle cases where two lanes were separated by multiple physical lane boundaries (e.g. a solid-broken marker). Solve this be referencing 0..N physical lane boundaries, and adding a PassingRule, so agent models don't have to look at the physical lane boundaries to determine the lane change rules. Also clarify some of the descriptions. Signed-off-by: Thomas Bleher --- osi_logicallane.proto | 124 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 114 insertions(+), 10 deletions(-) diff --git a/osi_logicallane.proto b/osi_logicallane.proto index 25b8f63b7..26146059f 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -140,7 +140,19 @@ message ReferenceLine } } -// Like a LaneBoundary, but with a reference and ST positions. +// Similar to a LaneBoundary, but with a reference and ST positions. +// +// A logical lane boundary describes the boundary between two logical lanes. As +// such, there will always be exactly one logical lane boundary between two +// lanes at a given S position. Contrary to that, there can be 0 to N physical +// lane boundaries (i.e. type LaneBoundary) between two logical lanes at a +// given S position. +// +// If there are multiple physical lane boundaries at one S position between two +// lanes (think of a solid-broken marking, which would be described by two +// LaneBoundary objects, one for the solid lane marking, one for the broken lane +// marking), then the single LogicalLaneBoundary describing the boundary between +// two logical lanes should be between the physical boundaries. // // Notes on design decisions: // - The LogicalLaneBoundary has ST coordinates, and is thus a separate type @@ -164,10 +176,6 @@ message ReferenceLine // This information can be gotten from the physical lane referenced in the // LogicalLane, if needed. // -// TODO To Discuss: It would be entirely possible to add ST coordinates also to -// LaneBoundary. Then no separate type would be needed. However, it is unclear if -// the additional overhead is acceptable for sensor models. -// message LogicalLaneBoundary { // The ID of the lane boundary. @@ -214,8 +222,9 @@ message LogicalLaneBoundary // All points of this LogicalLaneBoundary must have S coordinates in the // range [sStart,sEnd]. // - // The reference line should roughly have the same shape as the boundary, so - // that S coordinates continually increase along the lane. + // The reference line should roughly have the same shape as the boundary (so + // roughly parallel to the lane middle), so that S coordinates continually + // increase along the boundary. // // \rules // refers_to: ReferenceLine @@ -223,9 +232,48 @@ message LogicalLaneBoundary // optional Identifier reference_line_id = 3; - // The classification of the lane boundary. + // Reference to the physical lane boundary or boundaries that make up this + // logical boundary. + // + // Rules and notes: + // - This list is empty if there are no physical lane boundaries to delimit + // a lane. + // - In the common case, this will contain one physical boundary. + // - This list contains several lane boundaries if there are several physical + // lane boundaries at one S position (e.g. both a broken and a solid + // line). + // - If there are several lane boundaries, they must be listed in increasing + // T order (i.e. from right to left in reference line direction). + // Rationale: this makes it easier to determine e.g. rules on lane + // changes, which depend on the T order of the lanes. + // - Whenever physical lane boundaries begin or end, or switch their T + // position (if there are multiple physical lane boundaries), a new + // LogicalLaneBoundary must be created. + // - The referenced LaneBoundary objects may be longer than the + // LogicalLaneBoundary which references them, but must never be shorter. + // + // Example: + // Lane 1 + // --------a------------------ - - - -c- - - - + // - - - -b- - - - + // Lane 2 + // + // This shows the boundary between lane 1 and lane 2. First there is a + // solid-broken line (a and b), then there is only a solid line (a), then + // there is a broken line (c). There would be three LogicalLaneBoundary + // objects between Lane1 and Lane2: the first would reference a and b, the + // second would reference only a, and the third would reference c. + // + // \rules + // refers_to: LaneBoundary + // \endrules + // + repeated Identifier physical_boundary_id = 4; + + // The passing rules, insomuch as they can be determined just from road + // markings. // - optional LaneBoundary.Classification classification = 4; + optional PassingRule passing_rule = 5; // Optional external reference to the lane boundary source. // @@ -239,7 +287,7 @@ message LogicalLaneBoundary // from more than one origin source, for example, from a scenario file // and from sensors. // - repeated ExternalReference source_reference = 5; + repeated ExternalReference source_reference = 6; // A point on the boundary // @@ -259,6 +307,39 @@ message LogicalLaneBoundary // optional double t_position = 3; } + + // Passing rule of the LogicalLaneBoundary. + // + // This describes how vehicles may move across the LogicalLaneBoundary. The + // PassingRule is determined solely based on the road, not on any signs + // (i.e. it may be overridden by signs). + // + enum PassingRule { + // Passing rule cannot be determined, e.g. because it depends on the + // agent type. + // + CANNOT_BE_DETERMINED = 0; + + // No passing is allowed (neither from left to right nor from right to + // left). + // + NONE_ALLOWED = 1; + + // Only passing from left to right (in definition direction, so in + // decreasing T direction) is allowed. + // + LEFT_TO_RIGHT = 2; + + // Only passing from right to left (in definition direction, so in + // increasing T direction) is allowed. + // + RIGHT_TO_LEFT = 3; + + // Passing is allowed in both directions (left to right and right to + // left). + // + BOTH_ALLOWD = 4; + } } // @@ -272,6 +353,11 @@ message LogicalLaneBoundary // driving path is one LogicalLane, but the whole area is one \c Lane of type // \c #TYPE_INTERSECTION. // +// Outside of junctions, logical lanes are constructed such that each point on +// the road belongs to at least one (typically: exactly one) logical lane. So +// there are no gaps between logical lanes, and no areas that don't belong to a +// logical lane. +// // If OSI is generated from OpenDRIVE, then LogicalLanes map directly to // OpenDRIVE lanes. However, it is allowed to merge multiple consecutive // OpenDRIVE lanes with the same type into one OSI LogicalLane: if an OpenDRIVE @@ -400,6 +486,15 @@ message LogicalLane // have smaller T coordinates. // Entries must be ordered: first by start_s, then by end_s. // + // The XY positions of the polyline generated by the LogicalLaneBoundaries + // of adjacent lanes must match up to a small error (5cm). + // Typically adjacent lanes will share a LogicalLaneBoundary, but this will + // not always be true. Examples: on intersections, it might be hard to generate + // data such that lanes that are adjacent for a short length share a + // LogicalLaneBoundary for this length; also different LogicalLaneBoundaries + // are needed if the lanes have different heights at their boundaries (e.g. + // road adjacent to a sidewalk). + // repeated LaneRelation right_adjacent_lane = 9; // Lanes that are directly left of this lane, without gap or overlap. @@ -407,6 +502,15 @@ message LogicalLane // have larger T coordinates. // Entries must be ordered: first by start_s, then by end_s. // + // The XY positions of the polyline generated by the LogicalLaneBoundaries + // of adjacent lanes must match up to a small error (5cm). + // Typically adjacent lanes will share a LogicalLaneBoundary, but this will + // not always be true. Examples: on intersections, it might be hard to generate + // data such that lanes that are adjacent for a short length share a + // LogicalLaneBoundary for this length; also different LogicalLaneBoundaries + // are needed if the lanes have different heights at their boundaries (e.g. + // road adjacent to a sidewalk). + // repeated LaneRelation left_adjacent_lane = 10; // Lanes that partially or completely overlap this lane. Only overlaps From 731b29557487e9990225bc82aac474da6f6c229c Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Mon, 10 Jan 2022 11:29:18 +0100 Subject: [PATCH 07/37] Move ReferenceLine to separate file This makes it easier to use the ReferenceLine for other purposes. Signed-off-by: Thomas Bleher --- CMakeLists.txt | 1 + osi_groundtruth.proto | 1 + osi_logicallane.proto | 133 ------------------------------------- osi_referenceline.proto | 141 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 143 insertions(+), 133 deletions(-) create mode 100644 osi_referenceline.proto diff --git a/CMakeLists.txt b/CMakeLists.txt index 634f22cdb..3df80bcb6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,6 +74,7 @@ set(OSI_PROTO_FILES osi_trafficlight.proto osi_trafficupdate.proto osi_trafficcommand.proto + osi_referenceline.proto osi_roadmarking.proto osi_lane.proto osi_logicallane.proto diff --git a/osi_groundtruth.proto b/osi_groundtruth.proto index fc6920e3f..8b7d8ceb6 100644 --- a/osi_groundtruth.proto +++ b/osi_groundtruth.proto @@ -10,6 +10,7 @@ import "osi_trafficlight.proto"; import "osi_roadmarking.proto"; import "osi_lane.proto"; import "osi_logicallane.proto"; +import "osi_referenceline.proto"; import "osi_object.proto"; import "osi_occupant.proto"; diff --git a/osi_logicallane.proto b/osi_logicallane.proto index 26146059f..610d828f2 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -7,139 +7,6 @@ import "osi_lane.proto"; package osi3; -// -// \brief A reference line for defining a non-euclidean ST coordinate system -// -// A reference line is a 3D polyline, used for generating a non-euclidean -// ST coordinate system. -// -// Notes on design decisions: -// - This is a polyline, and not some more complex curve. The advantage of a -// polyline is that it is very simple to generate from various map formats, -// and it is also easy to handle. The downside is that a polyline has no -// direct curvature, and even the angle is not continuous (only C0 smooth). -// In the author's experience, the benefits of a polyline outweigh the costs. -// -// TODO Test whether the current definition is good enough for wide roads with -// strong curvature (e.g. roundabouts with several lanes). -// -message ReferenceLine -{ - // The ID of the logical lane. - // - // \note Note ID is global unique. - // - // \rules - // is_globally_unique - // \endrules - // - optional Identifier id = 1; - - // Points comprising the polyline. - // - // At least 2 points must be given. - // The polyline is defined as the lines between consecutive points. - // Each point has an S coordinate. There are a few requirements on the S - // position: - // - Later points in the list must have strictly larger S coordinates than - // earlier points. - // - For consecutive points, the S difference between them must be at - // least as large as the 2D euclidean distance between the points (2D - // distance == euclidean distance between the points taking only X and Y - // into account). - // - The S distance between two points may be larger than the 2D euclidean - // distance, but should be not much larger. It is allowed to be larger if - // the underlying reference line (e.g. in an OpenDRIVE map) is a curve, - // and thus the sampled reference line has a smaller length than the original - // curve. - // - // Together, these rules allow directly putting OpenDRIVE S coordinates - // into an OSI ReferenceLine. - // - // If the reference line approximates a curve (e.g. a clothoid in - // OpenDRIVE), the points must be chosen in a way that the lateral distance - // to the ideal line does not exceed 5cm. As shown in the following image: - // - // \image html line_approximation_error.svg "Approximation error" - // Approximation error green line. - // - // Between two ReferenceLinePoints, both the world coordinate and the S - // coordinate is interpolated linearly. So each S value uniquely describes - // a point on the polyline. - // - // For the purpose of this discussion, let's call the S position of the - // first point sStart, and the S position of the last point sEnd. - // - // For some purposes, S positions outside the normally defined range (i.e. - // outside [sStart,sEnd]) need to be defined. For this purpose, the first - // line of the polyline is infinitely extended in negative S direction. - // Similarly, the last line of the polyline is infinitely extended beyond - // the last point. The S value of points outside [sStart,sEnd] is defined - // by the euclidean 2D distance from the start or end point, respectively. - // So if sStart = 15, and a point is on the line extended from the start - // position, with a 2D euclidean distance of 10 from the first point, then - // it has an S position of 5. - // - // A point is "before" the reference line, if its s coordinate is < sStart. - // A point is "after" the reference line, if its s coordinate is > sEnd. - // - // To describe points that are not directly on the polyline, a T - // coordinate is added. T is the signed 2D distance (i.e. hypot(A.X-B.X, - // A.Y-B.Y), if A and B are the two points) between the point to describe - // and the nearest point on the polyline (this point might either be on a - // line segment or at an edge between two line segments). The distance is - // positive if the point is left of the polyline (in definition direction), - // negative if it is right of it. Note that the "nearest point on the - // polyline" is calculated in 3D, in order to choose the correct point for - // 3D curves (think reference lines for roads in parking decks). If there - // are several "nearest points", the one with the smallest S coordinate on - // the polyline is chosen. - // - // Sometimes an angle to a reference line is needed. This shall be defined - // as follows: - // First the nearest point on the polyline is determined, as described - // above. If this point is on a line segment, then the angle is calculated - // relative to the line segment on which the reference point lays. - // If the nearest point is at the edge between line segments, then the - // angle of the following line shall be chosen. - // - // Notes on OpenDRIVE compatibility: - // Ideally, one would want the polyline to be fully compatible with - // OpenDRIVE, so that calculations done for OpenDRIVE directly match those - // in OSI. There are a few difficulties with this: - // - The T coordinate is nearly the same as for OpenDRIVE, but - // unfortunately not perfectly. In OpenDRIVE, if the road is tilted using - // superElevation, then the t coordinate system is tilted along, so the T - // coordinate is no longer calculated in the XY plane (as proposed for - // OSI). It doesn't seem feasable to implement the same tilting for OSI, - // so simulation tools will have to consider superElevation and convert - // the T coordinate accordingly: t_OSI = t_OpenDRIVE * cos(alpha), where - // alpha is the superelevation angle. - // - The angle will not be perfectly the same, due to the use of line - // segments in OSI, and curves in OpenDRIVE. In the authors opinion, the - // difference will be negligible if the poly_line is suitably sampled. - // - // Notes on design decisions: - // - The S coordinate is included directly, both for OpenDRIVE - // compatibility, and to speed up calculations. - // - The rules on S coordinates (e.g. the calculation in 2D space) are - // there to ensure OpenDRIVE compatibility. - // - The rules on T coordinates are there to ensure OpenDRIVE compatibility - // for lanes without superelevation, and to make it easier to convert - // between OSI and OpenDRIVE in case superelevation is present. - // - repeated ReferenceLinePoint poly_line = 2; - - // A point on the reference line - message ReferenceLinePoint { - // A world position - optional Vector3d world_position = 1; - - // S position on the reference line - optional double s_position = 2; - } -} - // Similar to a LaneBoundary, but with a reference and ST positions. // // A logical lane boundary describes the boundary between two logical lanes. As diff --git a/osi_referenceline.proto b/osi_referenceline.proto new file mode 100644 index 000000000..301de17ae --- /dev/null +++ b/osi_referenceline.proto @@ -0,0 +1,141 @@ +syntax = "proto2"; + +option optimize_for = SPEED; + +import "osi_common.proto"; + +package osi3; + +// +// \brief A reference line for defining a non-euclidean ST coordinate system +// +// A reference line is a 3D polyline, used for generating a non-euclidean +// ST coordinate system. +// +// Notes on design decisions: +// - This is a polyline, and not some more complex curve. The advantage of a +// polyline is that it is very simple to generate from various map formats, +// and it is also easy to handle. The downside is that a polyline has no +// direct curvature, and even the angle is not continuous (only C0 smooth). +// In the author's experience, the benefits of a polyline outweigh the costs. +// +// TODO Test whether the current definition is good enough for wide roads with +// strong curvature (e.g. roundabouts with several lanes). +// +message ReferenceLine +{ + // The ID of the logical lane. + // + // \note Note ID is global unique. + // + // \rules + // is_globally_unique + // \endrules + // + optional Identifier id = 1; + + // Points comprising the polyline. + // + // At least 2 points must be given. + // The polyline is defined as the lines between consecutive points. + // Each point has an S coordinate. There are a few requirements on the S + // position: + // - Later points in the list must have strictly larger S coordinates than + // earlier points. + // - For consecutive points, the S difference between them must be at + // least as large as the 2D euclidean distance between the points (2D + // distance == euclidean distance between the points taking only X and Y + // into account). + // - The S distance between two points may be larger than the 2D euclidean + // distance, but should be not much larger. It is allowed to be larger if + // the underlying reference line (e.g. in an OpenDRIVE map) is a curve, + // and thus the sampled reference line has a smaller length than the original + // curve. + // + // Together, these rules allow directly putting OpenDRIVE S coordinates + // into an OSI ReferenceLine. + // + // If the reference line approximates a curve (e.g. a clothoid in + // OpenDRIVE), the points must be chosen in a way that the lateral distance + // to the ideal line does not exceed 5cm. As shown in the following image: + // + // \image html line_approximation_error.svg "Approximation error" + // Approximation error green line. + // + // Between two ReferenceLinePoints, both the world coordinate and the S + // coordinate is interpolated linearly. So each S value uniquely describes + // a point on the polyline. + // + // For the purpose of this discussion, let's call the S position of the + // first point sStart, and the S position of the last point sEnd. + // + // For some purposes, S positions outside the normally defined range (i.e. + // outside [sStart,sEnd]) need to be defined. For this purpose, the first + // line of the polyline is infinitely extended in negative S direction. + // Similarly, the last line of the polyline is infinitely extended beyond + // the last point. The S value of points outside [sStart,sEnd] is defined + // by the euclidean 2D distance from the start or end point, respectively. + // So if sStart = 15, and a point is on the line extended from the start + // position, with a 2D euclidean distance of 10 from the first point, then + // it has an S position of 5. + // + // A point is "before" the reference line, if its s coordinate is < sStart. + // A point is "after" the reference line, if its s coordinate is > sEnd. + // + // To describe points that are not directly on the polyline, a T + // coordinate is added. T is the signed 2D distance (i.e. hypot(A.X-B.X, + // A.Y-B.Y), if A and B are the two points) between the point to describe + // and the nearest point on the polyline (this point might either be on a + // line segment or at an edge between two line segments). The distance is + // positive if the point is left of the polyline (in definition direction), + // negative if it is right of it. Note that the "nearest point on the + // polyline" is calculated in 3D, in order to choose the correct point for + // 3D curves (think reference lines for roads in parking decks). If there + // are several "nearest points", the one with the smallest S coordinate on + // the polyline is chosen. + // + // Sometimes an angle to a reference line is needed. This shall be defined + // as follows: + // First the nearest point on the polyline is determined, as described + // above. If this point is on a line segment, then the angle is calculated + // relative to the line segment on which the reference point lays. + // If the nearest point is at the edge between line segments, then the + // angle of the following line shall be chosen. + // + // Notes on OpenDRIVE compatibility: + // Ideally, one would want the polyline to be fully compatible with + // OpenDRIVE, so that calculations done for OpenDRIVE directly match those + // in OSI. There are a few difficulties with this: + // - The T coordinate is nearly the same as for OpenDRIVE, but + // unfortunately not perfectly. In OpenDRIVE, if the road is tilted using + // superElevation, then the t coordinate system is tilted along, so the T + // coordinate is no longer calculated in the XY plane (as proposed for + // OSI). It doesn't seem feasable to implement the same tilting for OSI, + // so simulation tools will have to consider superElevation and convert + // the T coordinate accordingly: t_OSI = t_OpenDRIVE * cos(alpha), where + // alpha is the superelevation angle. + // - The angle will not be perfectly the same, due to the use of line + // segments in OSI, and curves in OpenDRIVE. In the authors opinion, the + // difference will be negligible if the poly_line is suitably sampled. + // + // Notes on design decisions: + // - The S coordinate is included directly, both for OpenDRIVE + // compatibility, and to speed up calculations. + // - The rules on S coordinates (e.g. the calculation in 2D space) are + // there to ensure OpenDRIVE compatibility. + // - The rules on T coordinates are there to ensure OpenDRIVE compatibility + // for lanes without superelevation, and to make it easier to convert + // between OSI and OpenDRIVE in case superelevation is present. + // + repeated ReferenceLinePoint poly_line = 2; + + // A point on the reference line + message ReferenceLinePoint { + // A world position + optional Vector3d world_position = 1; + + // S position on the reference line + optional double s_position = 2; + } +} + From e1998cd7f7561205b0a10d49510eccf2cbbda7dd Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Mon, 10 Jan 2022 11:45:58 +0100 Subject: [PATCH 08/37] Rework PassingRule enum, based on review in working group - Add common prefix as used in other enums in OSI3 - Split CANNOT_BE_DETERMINED into UNKNOWN and OTHER, similar to other enums - Rename LEFT_TO_RIGHT and RIGHT_TO_LEFT, to avoid confusion - Fix a spelling error in BOTH_ALLOWED Signed-off-by: Thomas Bleher --- osi_logicallane.proto | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/osi_logicallane.proto b/osi_logicallane.proto index 610d828f2..bf4fdf47a 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -182,30 +182,44 @@ message LogicalLaneBoundary // (i.e. it may be overridden by signs). // enum PassingRule { - // Passing rule cannot be determined, e.g. because it depends on the - // agent type. + // Passing rule is unknown (must not be used in ground truth). // - CANNOT_BE_DETERMINED = 0; + PASSING_RULE_UNKNOWN = 0; // No passing is allowed (neither from left to right nor from right to // left). // - NONE_ALLOWED = 1; - - // Only passing from left to right (in definition direction, so in - // decreasing T direction) is allowed. + PASSING_RULE_NONE_ALLOWED = 1; + + // Only passing in increasing T direction allowed. Passing is allowed + // from one lane to the other if the points on the target lane have + // larger T values than points on the source lane (at the same S + // position). In reference line direction (but not necessarily in + // driving direction), this means changing from right to left is + // allowed. // - LEFT_TO_RIGHT = 2; - - // Only passing from right to left (in definition direction, so in - // increasing T direction) is allowed. + PASSING_RULE_INCREASING_T = 2; + + // Only passing in decreasing T direction allowed. Passing is allowed + // from one lane to the other if the points on the target lane have + // smaller T values than points on the source lane (at the same S + // position). In reference line direction (but not necessarily in + // driving direction), this means changing from left to right is + // allowed. // - RIGHT_TO_LEFT = 3; + PASSING_RULE_DECREASING_T = 3; // Passing is allowed in both directions (left to right and right to // left). // - BOTH_ALLOWD = 4; + PASSING_RULE_BOTH_ALLOWED = 4; + + // Passing rule fits neither of the above categories. + // + // Example: this type needs to be used if passing depends on the agent + // type, e.g. if cars may change lane, but trucks may not. + // + PASSING_RULE_OTHER = 5; } } From 7291e91b6e1e6c6984e8f22a6e19d86bc1d28330 Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Mon, 10 Jan 2022 11:50:59 +0100 Subject: [PATCH 09/37] Clarify physical_boundary_id example a bit Signed-off-by: Thomas Bleher --- osi_logicallane.proto | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/osi_logicallane.proto b/osi_logicallane.proto index bf4fdf47a..b41de901a 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -12,7 +12,7 @@ package osi3; // A logical lane boundary describes the boundary between two logical lanes. As // such, there will always be exactly one logical lane boundary between two // lanes at a given S position. Contrary to that, there can be 0 to N physical -// lane boundaries (i.e. type LaneBoundary) between two logical lanes at a +// lane boundaries (i.e. type LaneBoundary) between two logical lanes at a // given S position. // // If there are multiple physical lane boundaries at one S position between two @@ -121,15 +121,16 @@ message LogicalLaneBoundary // // Example: // Lane 1 - // --------a------------------ - - - -c- - - - + // --------a------------------ - - - -c- - - - ----> // - - - -b- - - - - // Lane 2 - // - // This shows the boundary between lane 1 and lane 2. First there is a - // solid-broken line (a and b), then there is only a solid line (a), then - // there is a broken line (c). There would be three LogicalLaneBoundary - // objects between Lane1 and Lane2: the first would reference a and b, the - // second would reference only a, and the third would reference c. + // Lane -1 + // + // This shows the boundary between lane 1 and lane -1, with the reference + // line going from left to right. First there is a solid-broken line (a and + // b), then there is only a solid line (a), then there is a broken line + // (c). There would be three LogicalLaneBoundary objects between Lane1 and + // Lane2: the first would reference first b and then a, the second would + // reference only a, and the third would reference c. // // \rules // refers_to: LaneBoundary From 3b8198d3e78e25d1f3e2faea54d625de235ff9fe Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Wed, 19 Jan 2022 09:44:06 +0100 Subject: [PATCH 10/37] Update Doxygen documentation Signed-off-by: Thomas Bleher --- osi_common.proto | 4 ++++ osi_logicallane.proto | 45 +++++++++++++++++++++++++++-------------- osi_referenceline.proto | 31 ++++++++++++++++------------ 3 files changed, 52 insertions(+), 28 deletions(-) diff --git a/osi_common.proto b/osi_common.proto index 446f96393..465cc5105 100644 --- a/osi_common.proto +++ b/osi_common.proto @@ -357,6 +357,10 @@ message LogicalLaneAssignment { // ID of the LogicalLane the object is assigned to. // + // \rules + // refers_to: LogicalLane + // \endrules + // optional Identifier assigned_lane_id = 1; // S position of the object reference point on the lane, in the ST diff --git a/osi_logicallane.proto b/osi_logicallane.proto index b41de901a..c398e1be4 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -7,6 +7,9 @@ import "osi_lane.proto"; package osi3; +// +// \brief Boundary line of a LogicalLane +// // Similar to a LaneBoundary, but with a reference and ST positions. // // A logical lane boundary describes the boundary between two logical lanes. As @@ -58,11 +61,13 @@ message LogicalLaneBoundary // line. So S positions should increase along the line. Note that S // positions will not always increase strictly monotonically. // Example: + //
     //                |---------\
     //                |          \
-    //  /---boundary--|           \------------
+    //  /---boundary--|           \\------------
     // /
     // ---------- reference line --------------
+    // 
// At the place where the boundary suddenly increases, two points will have // the same S coordinate. // @@ -120,10 +125,12 @@ message LogicalLaneBoundary // LogicalLaneBoundary which references them, but must never be shorter. // // Example: - // Lane 1 - // --------a------------------ - - - -c- - - - ----> - // - - - -b- - - - - // Lane -1 + //
+    //       Lane 1
+    //  --------a------------------ - - - -c- - - -           ---->
+    //  \- - - -b- - - -
+    //       Lane -1
+    // 
// // This shows the boundary between lane 1 and lane -1, with the reference // line going from left to right. First there is a solid-broken line (a and @@ -157,9 +164,11 @@ message LogicalLaneBoundary // repeated ExternalReference source_reference = 6; - // A point on the boundary // - message LogicalBoundaryPoint { + // \brief A point on the boundary + // + message LogicalBoundaryPoint + { // The position of the \c LaneBoundaryPoint. // @@ -176,13 +185,15 @@ message LogicalLaneBoundary optional double t_position = 3; } - // Passing rule of the LogicalLaneBoundary. + // + // \brief Passing rule of the LogicalLaneBoundary. // // This describes how vehicles may move across the LogicalLaneBoundary. The // PassingRule is determined solely based on the road, not on any signs // (i.e. it may be overridden by signs). // - enum PassingRule { + enum PassingRule + { // Passing rule is unknown (must not be used in ground truth). // PASSING_RULE_UNKNOWN = 0; @@ -299,11 +310,13 @@ message LogicalLane // condition, etc.. // // TODO Should this be a repeated field? Imagine the following scenario: + //
     // ---------------------------------
     //  l1                       l2
     // ----------    l3        ---------
     //  l4                       l5
     // ---------------------------------
+    // 
// // In this case, we have five physical lanes: l1, l2, l4 and l5 where a // lane marking is present. And l3 is one lane covering the whole road @@ -452,10 +465,11 @@ message LogicalLane // repeated LaneConnection successor_lane = 15; - // Connection to another lane (predecessor or successor) // - message LaneConnection { - + // \brief Connection to another lane (predecessor or successor) + // + message LaneConnection + { // Id of the other logical lane that is connected // // \rules @@ -471,10 +485,11 @@ message LogicalLane } - // Relation of this lane to another logical lane // - message LaneRelation { - + // \brief Relation of this lane to another logical lane + // + message LaneRelation + { // Id of the other logical lane // // \rules diff --git a/osi_referenceline.proto b/osi_referenceline.proto index 301de17ae..00d464c20 100644 --- a/osi_referenceline.proto +++ b/osi_referenceline.proto @@ -82,17 +82,17 @@ message ReferenceLine // A point is "before" the reference line, if its s coordinate is < sStart. // A point is "after" the reference line, if its s coordinate is > sEnd. // - // To describe points that are not directly on the polyline, a T - // coordinate is added. T is the signed 2D distance (i.e. hypot(A.X-B.X, - // A.Y-B.Y), if A and B are the two points) between the point to describe - // and the nearest point on the polyline (this point might either be on a - // line segment or at an edge between two line segments). The distance is - // positive if the point is left of the polyline (in definition direction), - // negative if it is right of it. Note that the "nearest point on the - // polyline" is calculated in 3D, in order to choose the correct point for - // 3D curves (think reference lines for roads in parking decks). If there - // are several "nearest points", the one with the smallest S coordinate on - // the polyline is chosen. + // To describe points that are not directly on the polyline, a T coordinate + // is added. T is the signed 2D distance (i.e. hypot(A.X-B.X, + // A.Y-B.Y), if A and B are the two points) between the point to + // describe and the nearest point on the polyline (this point might either + // be on a line segment or at an edge between two line segments). The + // distance is positive if the point is left of the polyline (in definition + // direction), negative if it is right of it. Note that the "nearest point + // on the polyline" is calculated in 3D, in order to choose the correct + // point for 3D curves (think reference lines for roads in parking decks). + // If there are several "nearest points", the one with the smallest S + // coordinate on the polyline is chosen. // // Sometimes an angle to a reference line is needed. This shall be defined // as follows: @@ -129,12 +129,17 @@ message ReferenceLine // repeated ReferenceLinePoint poly_line = 2; - // A point on the reference line - message ReferenceLinePoint { + // + // \brief A point on the reference line + // + message ReferenceLinePoint + { // A world position + // optional Vector3d world_position = 1; // S position on the reference line + // optional double s_position = 2; } } From 03bd76d791e121658b4ca2a44c4435367a05e28e Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Wed, 19 Jan 2022 09:56:43 +0100 Subject: [PATCH 11/37] Clarify when objects should be assigned to lanes. Signed-off-by: Thomas Bleher --- osi_common.proto | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osi_common.proto b/osi_common.proto index 465cc5105..7073f96d7 100644 --- a/osi_common.proto +++ b/osi_common.proto @@ -343,7 +343,8 @@ message Spherical3d // // An object is assigned to a logical lane if it overlaps the logical lane. // Assignment happens even if the reference point is outside the lane, and only -// a part of the object overlaps. +// a part of the object overlaps (any object overlapping the lane more than 5cm +// has to be assigned to the lane). // // As an exception to this, \c TrafficSign and \c TrafficLight are assigned to // a logical lane if they control traffic on that lane. For \c TrafficSign and From 7d3f6317d8eec8753306f5fdd6ac5980bec553a6 Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Fri, 21 Jan 2022 21:45:34 +0100 Subject: [PATCH 12/37] Add own type for logical lanes Compared to Lane.Classification.Subtype, Curb and Median are added as additional types. Signed-off-by: Thomas Bleher --- osi_logicallane.proto | 93 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 2 deletions(-) diff --git a/osi_logicallane.proto b/osi_logicallane.proto index c398e1be4..f7c122267 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -3,7 +3,6 @@ syntax = "proto2"; option optimize_for = SPEED; import "osi_common.proto"; -import "osi_lane.proto"; package osi3; @@ -277,7 +276,7 @@ message LogicalLane // The type of the logical lane. // - optional Lane.Classification.Subtype type = 2; + optional Type type = 2; // Optional external reference to the lane source. // @@ -465,6 +464,96 @@ message LogicalLane // repeated LaneConnection successor_lane = 15; + // + // \brief Definition of available lane types. + // + // This is mostly aligned with OpenDRIVE, except that lane types modelling + // access restrictions (e.g. "taxi") are not made available here. These are + // already deprecated in OpenDRIVE. To support this, access restrictions + // should be added later, in alignment with OpenDRIVE. + // + enum Type + { + // %Lane of unknown type. Do not use in ground truth. + // + TYPE_UNKNOWN = 0; + + // Any other type of lane. + // + TYPE_OTHER = 1; + + // A normal driving lane. + // Example: Lanes with IDs l1, l2, l3 and l4 in image \ref + // HighwayExit. + // This matches the OpenDRIVE type "driving". + // + TYPE_NORMAL = 2; + + // A lane that is designated for bicylists. + // + TYPE_BIKING = 3; + + // A lane that is designated for pedestrians (sidewalk). + // + TYPE_SIDEWALK = 4; + + // A lane with parking spaces. + // + TYPE_PARKING = 5; + + // A hard shoulder on motorways for emergency stops. + // Example: Lane l5 in image \ref + // HighwayExit. + // + TYPE_STOP = 6; + + // A lane on which cars should not drive. + // + TYPE_RESTRICTED = 7; + + // A hard border on the edge of a road. + // + TYPE_BORDER = 8; + + // A soft border on the edge of a road. + // + TYPE_SHOULDER = 9; + + // A deceleration lane in parallel to the main road. + // Example: Lane l6 in image \ref + // HighwayExit. + // + TYPE_EXIT = 10; + + // An acceleration lane in parallel to the main road. + // + TYPE_ENTRY = 11; + + // A ramp from rural or urban roads joining a motorway. + // + TYPE_ONRAMP = 12; + + // A ramp leading off a motorway onto rural or urban roads. + // + TYPE_OFFRAMP = 13; + + // A ramp that connect two motorways. + // + TYPE_CONNECTINGRAMP = 14; + + // A lane that sits between driving lanes + // that lead in opposite directions. It is + // typically used to separate traffic in + // towns on large roads. + // + TYPE_MEDIAN = 15; + + // Curb stones. Curb stones have a different + // height than the adjacent drivable lanes. + // + TYPE_CURB = 16; + } + // // \brief Connection to another lane (predecessor or successor) // From df07a0175ea605139b7e4cd28da3f0fb33528283 Mon Sep 17 00:00:00 2001 From: Thomas Bleher Date: Fri, 21 Jan 2022 22:17:41 +0100 Subject: [PATCH 13/37] Allow a logical lane to reference several physical lanes Signed-off-by: Thomas Bleher --- osi_logicallane.proto | 58 +++++++++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 13 deletions(-) diff --git a/osi_logicallane.proto b/osi_logicallane.proto index f7c122267..2ea0afc93 100644 --- a/osi_logicallane.proto +++ b/osi_logicallane.proto @@ -302,13 +302,22 @@ message LogicalLane // repeated ExternalReference source_reference = 3; - // Reference to the physical lane this logical lane belongs to. + // Reference to the physical lanes this logical lane belongs to. // // This makes it possible to get detailed information on the physical lane // properties, e.g. the visual colors of the boundaries, the road // condition, etc.. // - // TODO Should this be a repeated field? Imagine the following scenario: + // Note: a logical lane may consist of several physical lanes (in a row). + // At any one S position, a logical lane should only reference one physical + // lane. Several logical lanes may reference the same physical lane (see + // drawing below). + // + // Logical lanes should not extend beyond intersections. All logical lanes + // on intersections should end at the latest at the border of the + // intersection. + // + // Example: //
     // ---------------------------------
     //  l1                       l2
@@ -321,22 +330,21 @@ message LogicalLane
     // lane marking is present. And l3 is one lane covering the whole road
     // (because no road marking is present).
     //
-    // Now there are two basic possibilities to define the logical lanes:
-    // - There could be two logical lanes: one encompassing l4, part of l3 and
-    //   l5; another encompassing l2, part of l3 and l1. In this case, one
-    //   logical lane can map to a number of physical lanes, and the mapping
-    //   should include s positions, so it is clear which part of the logical
-    //   lane maps to which physical lane.
-    // - There could be 6 logical lanes: l1, l2, l4, l5 and two lanes for each
-    //   halve of l3. Then each logical lane would map to a single physical
-    //   lane, but logical lanes would have to be split each time a lane
-    //   marking appears or disappears.
+    // This would typically be presented as two logical lanes:
+    // - One encompassing l1, part of l3, and l2
+    // - The other encompassing l4, part of l3 and l5
+    //
+    // In this example, both logical lanes would reference l3. Their shared
+    // LogicalLaneBoundary would cut through the middle of l3.
+    //
+    // physical_lane_reference does not give any information how much of the
+    // area of a physical lane is covered by a logical lane.
     //
     // \rules
     // refers_to: Lane
     // \endrules
     //
-    optional Identifier physical_lane_id = 4;
+    repeated PhysicalLaneReference physical_lane_reference = 4;
 
     // The reference line for this logical lane
     //
@@ -554,6 +562,30 @@ message LogicalLane
         TYPE_CURB = 16;
     }
 
+    //
+    // \brief Reference to a physical lane.
+    //
+    message PhysicalLaneReference
+    {
+        // Id of the physical lane referenced.
+        //
+        // \rules
+        // refers_to: Lane
+        // \endrules
+        //
+        optional Identifier physical_lane_id = 1;
+
+        // S position on the logical lane where the physical lane starts
+        //
+        optional double start_s = 2;
+
+        // S position on the logical lane where the physical lane ends
+        //
+        // Requirement: end_s > start_s
+        //
+        optional double end_s = 3;
+    }
+
     //
     // \brief Connection to another lane (predecessor or successor)
     //

From e2f186383237c9d234b5d12e2e4a161321e56cf3 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Fri, 21 Jan 2022 22:24:58 +0100
Subject: [PATCH 14/37] Allow logical boundaries to extend beyond the logical
 lane

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 14 ++++++--------
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 2ea0afc93..02835c078 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -427,15 +427,14 @@ message LogicalLane
     // All LogicalLaneBoundary elements referenced here must refer to the same
     // ReferenceLine as this lane.
     // The boundaries together must cover the whole length of the lane (the
-    // range [start_s,end_s]) without gap or overlap. The boundaries must be
+    // range \[#start_s,#end_s\]) without gap or overlap. The boundaries must be
     // stored in ascending order, starting with the smallest S position.
     // Consecutive boundaries must share a point: the last point of the
     // previous boundary must be identical to the first point of the next
     // boundary.
     //
-    // TODO Is it allowed for the boundaries to be longer than the lane?
-    // Theoretically, this could be done. Then the user would have to limit the
-    // boundary itself to [start_s,end_s].
+    // Note: the referenced boundaries may have points outside of
+    // \[#start_s,#end_s\] (e.g. a boundary may extend beyond the end of a lane).
     //
     // \rules
     // refers_to: LogicalLaneBoundary
@@ -448,15 +447,14 @@ message LogicalLane
     // All LogicalLaneBoundary elements referenced here must refer to the same
     // ReferenceLine as this lane.
     // The boundaries together must cover the whole length of the lane (the
-    // range [start_s,end_s]) without gap or overlap. The boundaries must be
+    // range \[#start_s,#end_s\]) without gap or overlap. The boundaries must be
     // stored in ascending order, starting with the smallest S position.
     // Consecutive boundaries must share a point: the last point of the
     // previous boundary must be identical to the first point of the next
     // boundary.
     //
-    // TODO Is it allowed for the boundaries to be longer than the lane?
-    // Theoretically, this could be done. Then the user would have to limit the
-    // boundary itself to [start_s,end_s].
+    // Note: the referenced boundaries may have points outside of
+    // \[#start_s,#end_s\] (e.g. a boundary may extend beyond the end of a lane).
     //
     // \rules
     // refers_to: LogicalLaneBoundary

From 987eceedfb314dde75a2a4b838ebdbe999a9a881 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Fri, 21 Jan 2022 22:32:14 +0100
Subject: [PATCH 15/37] Small doc update

Signed-off-by: Thomas Bleher 
---
 osi_common.proto      |  4 ++--
 osi_logicallane.proto | 29 ++++++++++++++++-------------
 2 files changed, 18 insertions(+), 15 deletions(-)

diff --git a/osi_common.proto b/osi_common.proto
index 7073f96d7..f9d0b3acd 100644
--- a/osi_common.proto
+++ b/osi_common.proto
@@ -348,7 +348,7 @@ message Spherical3d
 //
 // As an exception to this, \c TrafficSign and \c TrafficLight are assigned to
 // a logical lane if they control traffic on that lane. For \c TrafficSign and
-// \c TrafficLight , s_position refers to the position where the sign or light
+// \c TrafficLight , #s_position refers to the position where the sign or light
 // is valid (e.g. where vehicles should stop in case of a red traffic light),
 // not the physical position (where the sign or light is in the world).
 // Typically, t_position and angle_to_lane do not have any meaning in this
@@ -367,7 +367,7 @@ message LogicalLaneAssignment
     // S position of the object reference point on the lane, in the ST
     // coordinate system of the lane.
     //
-    // s_position might be outside [s_start,s_end] of the lane (and even
+    // #s_position might be outside [s_start,s_end] of the lane (and even
     // outside [startS,endS] of the reference line) if the reference point is
     // outside the lane, but the object overlaps the lane or a TrafficSign or
     // TrafficLight is assigned to a lane.
diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 02835c078..e58c8bd0a 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -35,7 +35,7 @@ package osi3;
 //   - No centerline of the lane is necessary, since this can very easily be
 //     generated from the boundaries.
 //   Disadvantages of this decision:
-//   - Lane boundaries cannot be shared with physical lanes. This results in
+//   - %Lane boundaries cannot be shared with physical lanes. This results in
 //     more data needed. This can mostly be mitigated by only transmitting the
 //     lane boundaries during initialization (e.g. via the OSMP GroundTruthInit
 //     message).
@@ -359,6 +359,11 @@ message LogicalLane
     // reference_line, so that vehicles that are next to each other on
     // neighbouring lanes have comparable S positions.
     //
+    // The S coordinate of the reference line makes it easy to find e.g. which
+    // object is next on a lane, using the LogicalLaneAssignment of the
+    // objects.
+    //
+    //
     // \rules
     // refers_to: ReferenceLine
     // \endrules
@@ -372,7 +377,8 @@ message LogicalLane
 
     // End S position of the lane. Must be in range [sStart,sEnd] of the
     // reference line.
-    // end_s > start_s
+    //
+    // Requirement: #end_s > #start_s
     //
     optional double end_s = 7;
 
@@ -386,7 +392,7 @@ message LogicalLane
     // Lanes that are directly right of this lane, without gap or overlap.
     // "Right" is in definition direction (not driving direction), so right lanes
     // have smaller T coordinates.
-    // Entries must be ordered: first by start_s, then by end_s.
+    // Entries must be ordered: first by #start_s, then by #end_s.
     //
     // The XY positions of the polyline generated by the LogicalLaneBoundaries
     // of adjacent lanes must match up to a small error (5cm).
@@ -402,7 +408,7 @@ message LogicalLane
     // Lanes that are directly left of this lane, without gap or overlap.
     // "Left" is in definition direction (not driving direction), so left lanes
     // have larger T coordinates.
-    // Entries must be ordered: first by start_s, then by end_s.
+    // Entries must be ordered: first by #start_s, then by #end_s.
     //
     // The XY positions of the polyline generated by the LogicalLaneBoundaries
     // of adjacent lanes must match up to a small error (5cm).
@@ -418,7 +424,7 @@ message LogicalLane
     // Lanes that partially or completely overlap this lane. Only overlaps
     // laterally larger than 5cm are considered overlaps for the purpose of
     // this relation.
-    // Entries must be ordered: first by start_s, then by end_s.
+    // Entries must be ordered: first by #start_s, then by #end_s.
     //
     repeated LaneRelation overlapping_lane = 11;
 
@@ -579,7 +585,7 @@ message LogicalLane
 
         // S position on the logical lane where the physical lane ends
         //
-        // Requirement: end_s > start_s
+        // Requirement: #end_s > #start_s
         //
         optional double end_s = 3;
     }
@@ -623,28 +629,25 @@ message LogicalLane
 
         // End s position of the relation
         //
-        // Requirement: end_s > start_s
+        // Requirement: #end_s > #start_s
         //
         optional double end_s = 3;
 
         // Start s position of the relation on the other lane.
         //
-        // This is the same place as start_s, but measured along the reference
+        // This is the same place as #start_s, but measured along the reference
         // line of the other lane.
         //
         optional double start_s_other = 4;
 
         // End s position of the relation on the other lane.
         //
-        // This is the same place as end_s, but measured along the reference
+        // This is the same place as #end_s, but measured along the reference
         // line of the other lane.
         //
-        // Note: end_s_other might be smaller than start_s_other
+        // Note: #end_s_other might be smaller than #start_s_other
         //
         optional double end_s_other = 5;
     }
 }
 
-// TODO Traffic Agents also need the physical area of an intersection. This
-// should be added to physical lanes of type TYPE_INTERSECTION.
-

From eb0dff771f4743f4dbb6927db5099f4c9bdb48d9 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 24 Jan 2022 16:27:19 +0100
Subject: [PATCH 16/37] Improve LogicalLane documentation, add two example
 images.

Signed-off-by: Thomas Bleher 
---
 doc/images/OSI_LogicalLane1.png | Bin 0 -> 17494 bytes
 doc/images/OSI_LogicalLane2.png | Bin 0 -> 9425 bytes
 osi_logicallane.proto           |  70 +++++++++++++++++++++++++-------
 3 files changed, 56 insertions(+), 14 deletions(-)
 create mode 100644 doc/images/OSI_LogicalLane1.png
 create mode 100644 doc/images/OSI_LogicalLane2.png

diff --git a/doc/images/OSI_LogicalLane1.png b/doc/images/OSI_LogicalLane1.png
new file mode 100644
index 0000000000000000000000000000000000000000..ad13f12d9e74e6582b7bea647e27831523332740
GIT binary patch
literal 17494
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
B<&ppZ

literal 0
HcmV?d00001

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index e58c8bd0a..33326139c 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -240,27 +240,69 @@ message LogicalLaneBoundary
 // A logical lane is part of a road. Compared to a physical lane (OSI type
 // \c Lane), its existence doesn't hinge on the existence of road markings. So
 // e.g. a narrow urban road with two driving directions but no road markings
-// in-between would be presented as two LogicalLanes, but only one Lane. So one
-// Lane can consist of multiple LogicalLanes. E.g. on intersections, each
-// driving path is one LogicalLane, but the whole area is one \c Lane of type
-// \c #TYPE_INTERSECTION.
+// in-between would be presented as two \link LogicalLane LogicalLanes\endlink,
+// but only one Lane. So one Lane can consist of multiple \link LogicalLane
+// LogicalLanes\endlink. E.g. on intersections, each driving path is one
+// LogicalLane, but the whole area is one \c Lane of type \link
+// osi3::Lane::Classification::TYPE_INTERSECTION \c TYPE_INTERSECTION \endlink.
 //
 // Outside of junctions, logical lanes are constructed such that each point on
 // the road belongs to at least one (typically: exactly one) logical lane. So
 // there are no gaps between logical lanes, and no areas that don't belong to a
 // logical lane.
 //
-// If OSI is generated from OpenDRIVE, then LogicalLanes map directly to
-// OpenDRIVE lanes. However, it is allowed to merge multiple consecutive
-// OpenDRIVE lanes with the same type into one OSI LogicalLane: if an OpenDRIVE
-// lane has a single successor, which has the same lane type, and this
-// successor has only one predecessor (so no lane merging or splitting) then
-// the two lanes may be presented as one continuous LogicalLane. This may be
-// done recursively.
+// If OSI is generated from OpenDRIVE, then \link LogicalLane
+// LogicalLanes\endlink map directly to OpenDRIVE lanes. However, it is allowed
+// to merge multiple consecutive OpenDRIVE lanes with the same type into one
+// OSI LogicalLane: if an OpenDRIVE lane has a single successor, which has the
+// same lane type, and this successor has only one predecessor (so no lane
+// merging or splitting) then the two lanes may be presented as one continuous
+// LogicalLane. This may be done recursively.
 //
-// The reference line pointed to by reference_line_id defines an ST coordinate
-// system for the lane. This ST coordinate system is used to describe positions
-// on the lane.
+// The \link ReferenceLine reference line\endlink pointed to by
+// #reference_line_id defines an ST coordinate system for the lane. This ST
+// coordinate system is used to describe positions on the lane.
+//
+// ## Example
+//
+// The example below shows two logical lanes on an intersection, with a focus
+// on the left-turn lane (\c l1):
+// \image html OSI_LogicalLane1.png "Two logical lanes on an intersection"
+//
+// Assumptions not shown in the image:
+// - This is right-hand traffic (and thus vehicles on \c l1 drive from the bottom
+//   to the left, vehicles on \c l2 drive from right to left).
+// - The yellow line is a ReferenceLine, defined starting at the bottom, and
+//   going to the left.
+//
+// Some features shown in the image relative to \c l1:
+// - The yellow line is the ReferenceLine of \c l1 . The ReferenceLine can be
+//   shared with other lanes.  Because the ReferenceLine has the same direction
+//   as the driving direction of \c l1 in this example,
+//   #reference_line_is_driving_direction == true.
+// - The red line marks the area where \c l2 is left of
+//   \c l1 - this info is recorded in #left_adjacent_lane of \c l1.
+// - The red area is the area where \c l2 overlaps \c l1. This is recorded in
+//   #overlapping_lane of \c l1.
+//
+// The image below shows the same two lanes, but from the perspective of \c l2:
+// \image html OSI_LogicalLane2.png "Two logical lanes on an intersection"
+//
+// Assumptions not shown in the image:
+// - The yellow line is a ReferenceLine, defined starting at the right, going
+//   to the left.
+//
+// Some features shown in the image relative to \c l2:
+// - The yellow line is the ReferenceLine of \c l2 . The ReferenceLine can be
+//   shared with other lanes.  Because the ReferenceLine has the same direction
+//   as the driving direction of \c l2 in this example,
+//   #reference_line_is_driving_direction == true.
+// - The green line marks the area where \c l1 is right of
+//   \c l2 - this info is recorded in #right_adjacent_lane of \c l2.
+// - The red area is the area where \c l1 overlaps \c l2. This is recorded in
+//   #overlapping_lane of \c l1.
+//
+// Note: all these relations are also defined outside of intersections.
 //
 message LogicalLane
 {

From cbdc34a1fd57a5084366d8d92f75722992a25eed Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Thu, 27 Jan 2022 14:05:22 +0100
Subject: [PATCH 17/37] Extend documentation on reference line

Also some Doxygen cleanup for LogicalLane.

Signed-off-by: Thomas Bleher 
---
 doc/images/OSI_ReferenceLine1.svg | 256 ++++++++++++++++++++++++++++++
 osi_logicallane.proto             |  85 +++++-----
 osi_referenceline.proto           | 102 ++++++++----
 3 files changed, 377 insertions(+), 66 deletions(-)
 create mode 100644 doc/images/OSI_ReferenceLine1.svg

diff --git a/doc/images/OSI_ReferenceLine1.svg b/doc/images/OSI_ReferenceLine1.svg
new file mode 100644
index 000000000..dcd7bc7ea
--- /dev/null
+++ b/doc/images/OSI_ReferenceLine1.svg
@@ -0,0 +1,256 @@
+
+
+
+
+  
+    
+      
+    
+    
+      
+    
+    
+      
+    
+  
+  
+  
+    
+      
+        image/svg+xml
+        
+        
+      
+    
+  
+  
+    
+    
+    
+    
+    
+    
+    
+    
+    P2
+    P3
+    P1
+    
+    
+    P4
+    
+    P5
+    
+    
+        
+    
+  
+
diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 33326139c..f2d027c9e 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -47,7 +47,7 @@ package osi3;
 //
 message LogicalLaneBoundary
 {
-    // The ID of the lane boundary.
+    // \brief The ID of the lane boundary.
     //
     // \rules
     // is_globally_unique
@@ -55,7 +55,8 @@ message LogicalLaneBoundary
     //
     optional Identifier id = 1;
 
-    // points making up the lane boundary.
+    // \brief Points making up the lane boundary.
+    //
     // The boundary must be defined in the same direction as the reference
     // line. So S positions should increase along the line. Note that S
     // positions will not always increase strictly monotonically.
@@ -87,11 +88,11 @@ message LogicalLaneBoundary
     //
     repeated LogicalBoundaryPoint boundary_line = 2;
 
-    // The reference line for this boundary.
+    // \brief The reference line for this boundary.
     //
     // The reference line is used as a coordinate system for this boundary.
     // All points of this LogicalLaneBoundary must have S coordinates in the
-    // range [sStart,sEnd].
+    // range [\c sStart,\c sEnd].
     //
     // The reference line should roughly have the same shape as the boundary (so
     // roughly parallel to the lane middle), so that S coordinates continually
@@ -103,8 +104,8 @@ message LogicalLaneBoundary
     //
     optional Identifier reference_line_id = 3;
 
-    // Reference to the physical lane boundary or boundaries that make up this
-    // logical boundary.
+    // \brief Reference to the physical lane boundary or boundaries that make
+    // up this logical boundary.
     //
     // Rules and notes:
     // - This list is empty if there are no physical lane boundaries to delimit
@@ -144,12 +145,12 @@ message LogicalLaneBoundary
     //
     repeated Identifier physical_boundary_id = 4;
 
-    // The passing rules, insomuch as they can be determined just from road
-    // markings.
+    // \brief The passing rules, insomuch as they can be determined just from
+    // road markings.
     //
     optional PassingRule passing_rule = 5;
 
-    // Optional external reference to the lane boundary source.
+    // \brief Optional external reference to the lane boundary source.
     //
     // \note For OpenDRIVE, there is no direct possibility to reference the
     //       RoadMark, as there is no unique identifier in this sub-object.
@@ -306,7 +307,7 @@ message LogicalLaneBoundary
 //
 message LogicalLane
 {
-    // The ID of the logical lane.
+    // \brief The ID of the logical lane.
     //
     // \note Note ID is global unique.
     //
@@ -316,11 +317,11 @@ message LogicalLane
     //
     optional Identifier id = 1;
 
-    // The type of the logical lane.
+    // \brief The type of the logical lane.
     //
     optional Type type = 2;
 
-    // Optional external reference to the lane source.
+    // \brief Optional external reference to the lane source.
     //
     // The external reference points to the source of the lane, if it is derived
     // from one or more objects or external references.
@@ -344,7 +345,7 @@ message LogicalLane
     //
     repeated ExternalReference source_reference = 3;
 
-    // Reference to the physical lanes this logical lane belongs to.
+    // \brief Reference to the physical lanes this logical lane belongs to.
     //
     // This makes it possible to get detailed information on the physical lane
     // properties, e.g. the visual colors of the boundaries, the road
@@ -388,7 +389,7 @@ message LogicalLane
     //
     repeated PhysicalLaneReference physical_lane_reference = 4;
 
-    // The reference line for this logical lane
+    // \brief The \link ReferenceLine reference line\endlink for this logical lane
     //
     // The reference line is used as a coordinate system on this lane.
     //
@@ -405,6 +406,8 @@ message LogicalLane
     // object is next on a lane, using the LogicalLaneAssignment of the
     // objects.
     //
+    // The reference trajectory must be sampled such that there are no two
+    // positions on the lane more than 5cm apart with the same ST coordinate.
     //
     // \rules
     // refers_to: ReferenceLine
@@ -412,26 +415,29 @@ message LogicalLane
     //
     optional Identifier reference_line_id = 5;
 
-    // Start S position of the lane. Must be in range [sStart,sEnd] of the
-    // reference line.
+    // \brief Start S position of the lane.
+    //
+    // Must be in range [\c sStart,\c sEnd] of the reference line.
     //
     optional double start_s = 6;
 
-    // End S position of the lane. Must be in range [sStart,sEnd] of the
-    // reference line.
+    // \brief End S position of the lane.
+    //
+    // Must be in range [\c sStart,\c sEnd] of the reference line.
     //
     // Requirement: #end_s > #start_s
     //
     optional double end_s = 7;
 
-    // Definition of the intended driving direction.
+    // \brief Definition of the intended driving direction.
     //
     // \c true means driving direction is according to ascending S position.
     // \c false means driving direction is according to descending S position.
     //
     optional bool reference_line_is_driving_direction = 8;
 
-    // Lanes that are directly right of this lane, without gap or overlap.
+    // \brief Lanes that are directly right of this lane, without gap or overlap.
+    //
     // "Right" is in definition direction (not driving direction), so right lanes
     // have smaller T coordinates.
     // Entries must be ordered: first by #start_s, then by #end_s.
@@ -447,7 +453,8 @@ message LogicalLane
     //
     repeated LaneRelation right_adjacent_lane = 9;
 
-    // Lanes that are directly left of this lane, without gap or overlap.
+    // \brief Lanes that are directly left of this lane, without gap or overlap.
+    //
     // "Left" is in definition direction (not driving direction), so left lanes
     // have larger T coordinates.
     // Entries must be ordered: first by #start_s, then by #end_s.
@@ -463,14 +470,17 @@ message LogicalLane
     //
     repeated LaneRelation left_adjacent_lane = 10;
 
-    // Lanes that partially or completely overlap this lane. Only overlaps
-    // laterally larger than 5cm are considered overlaps for the purpose of
-    // this relation.
+    // \brief Lanes that partially or completely overlap this lane.
+    //
+    // Only overlaps laterally larger than 5cm are considered overlaps for the
+    // purpose of this relation.
+    //
     // Entries must be ordered: first by #start_s, then by #end_s.
     //
     repeated LaneRelation overlapping_lane = 11;
 
-    // Right boundary of this lane.
+    // \brief Right boundary of this lane.
+    //
     // References to LogicalLaneBoundary elements.
     // All LogicalLaneBoundary elements referenced here must refer to the same
     // ReferenceLine as this lane.
@@ -490,7 +500,8 @@ message LogicalLane
     //
     repeated Identifier right_boundary_id = 12;
 
-    // Left boundary of this lane.
+    // \brief Left boundary of this lane.
+    //
     // References to LogicalLaneBoundary elements.
     // All LogicalLaneBoundary elements referenced here must refer to the same
     // ReferenceLine as this lane.
@@ -510,11 +521,11 @@ message LogicalLane
     //
     repeated Identifier left_boundary_id = 13;
 
-    // Lanes that directly are connected to this lane at the beginning
+    // \brief Lanes that directly are connected to this lane at the beginning.
     //
     repeated LaneConnection predecessor_lane = 14;
 
-    // Lanes that directly are connected to this lane at the end
+    // \brief Lanes that directly are connected to this lane at the end.
     //
     repeated LaneConnection successor_lane = 15;
 
@@ -613,7 +624,7 @@ message LogicalLane
     //
     message PhysicalLaneReference
     {
-        // Id of the physical lane referenced.
+        // \brief Id of the physical lane referenced.
         //
         // \rules
         // refers_to: Lane
@@ -621,11 +632,11 @@ message LogicalLane
         //
         optional Identifier physical_lane_id = 1;
 
-        // S position on the logical lane where the physical lane starts
+        // \brief S position on the logical lane where the physical lane starts.
         //
         optional double start_s = 2;
 
-        // S position on the logical lane where the physical lane ends
+        // \brief S position on the logical lane where the physical lane ends.
         //
         // Requirement: #end_s > #start_s
         //
@@ -637,7 +648,7 @@ message LogicalLane
     //
     message LaneConnection
     {
-        // Id of the other logical lane that is connected
+        // \brief Id of the other logical lane that is connected.
         //
         // \rules
         // refers_to: LogicalLane
@@ -657,7 +668,7 @@ message LogicalLane
     //
     message LaneRelation
     {
-        // Id of the other logical lane
+        // \brief Id of the other logical lane.
         //
         // \rules
         // refers_to: LogicalLane
@@ -665,24 +676,24 @@ message LogicalLane
         //
         optional Identifier other_lane_id = 1;
 
-        // Start s position of the relation
+        // \brief Start s position of the relation.
         //
         optional double start_s = 2;
 
-        // End s position of the relation
+        // \brief End s position of the relation.
         //
         // Requirement: #end_s > #start_s
         //
         optional double end_s = 3;
 
-        // Start s position of the relation on the other lane.
+        // \brief Start s position of the relation on the other lane.
         //
         // This is the same place as #start_s, but measured along the reference
         // line of the other lane.
         //
         optional double start_s_other = 4;
 
-        // End s position of the relation on the other lane.
+        // \brief End s position of the relation on the other lane.
         //
         // This is the same place as #end_s, but measured along the reference
         // line of the other lane.
diff --git a/osi_referenceline.proto b/osi_referenceline.proto
index 00d464c20..c77aef49b 100644
--- a/osi_referenceline.proto
+++ b/osi_referenceline.proto
@@ -19,12 +19,9 @@ package osi3;
 //   direct curvature, and even the angle is not continuous (only C0 smooth).
 //   In the author's experience, the benefits of a polyline outweigh the costs.
 //
-// TODO Test whether the current definition is good enough for wide roads with
-// strong curvature (e.g. roundabouts with several lanes).
-//
 message ReferenceLine
 {
-    // The ID of the logical lane.
+    // \brief The ID of the logical lane.
     //
     // \note Note ID is global unique.
     //
@@ -34,12 +31,15 @@ message ReferenceLine
     //
     optional Identifier id = 1;
 
-    // Points comprising the polyline.
+    // \brief Points comprising the polyline.
     //
     // At least 2 points must be given.
     // The polyline is defined as the lines between consecutive points.
-    // Each point has an S coordinate. There are a few requirements on the S
-    // position:
+    // Each point has an S coordinate.
+    //
+    // ## Rules on the S position
+    //
+    // There are a few requirements on the S position:
     // - Later points in the list must have strictly larger S coordinates than
     //   earlier points.
     // - For consecutive points, the S difference between them  must be at
@@ -66,21 +66,25 @@ message ReferenceLine
     // coordinate is interpolated linearly. So each S value uniquely describes
     // a point on the polyline.
     //
+    // ## Extending the coordinate system infinitely
+    //
     // For the purpose of this discussion, let's call the S position of the
-    // first point sStart, and the S position of the last point sEnd.
+    // first point \c sStart, and the S position of the last point \c sEnd.
     //
     // For some purposes, S positions outside the normally defined range (i.e.
-    // outside [sStart,sEnd]) need to be defined. For this purpose, the first
-    // line of the polyline is infinitely extended in negative S direction.
-    // Similarly, the last line of the polyline is infinitely extended beyond
-    // the last point. The S value of points outside [sStart,sEnd] is defined
-    // by the euclidean 2D distance from the start or end point, respectively.
-    // So if sStart = 15, and a point is on the line extended from the start
-    // position, with a 2D euclidean distance of 10 from the first point, then
-    // it has an S position of 5.
-    //
-    // A point is "before" the reference line, if its s coordinate is < sStart.
-    // A point is "after" the reference line, if its s coordinate is > sEnd.
+    // outside [\c sStart,\c sEnd]) need to be defined. For this purpose, the
+    // first line of the polyline is infinitely extended in negative S
+    // direction.  Similarly, the last line of the polyline is infinitely
+    // extended beyond the last point. The S value of points outside [\c
+    // sStart,\c sEnd] is defined by the euclidean 2D distance from the start
+    // or end point, respectively.  So if sStart = 15, and a point
+    // is on the line extended from the start position, with a 2D euclidean
+    // distance of 10 from the first point, then it has an S position of 5.
+    //
+    // A point is "before" the reference line, if its s coordinate is < \c sStart.
+    // A point is "after" the reference line, if its s coordinate is > \c sEnd.
+    //
+    // ## Adding T coordinates
     //
     // To describe points that are not directly on the polyline, a T coordinate
     // is added. T is the signed 2D distance (i.e. hypot(A.X-B.X,
@@ -88,11 +92,19 @@ message ReferenceLine
     // describe and the nearest point on the polyline (this point might either
     // be on a line segment or at an edge between two line segments). The
     // distance is positive if the point is left of the polyline (in definition
-    // direction), negative if it is right of it. Note that the "nearest point
-    // on the polyline" is calculated in 3D, in order to choose the correct
-    // point for 3D curves (think reference lines for roads in parking decks).
-    // If there are several "nearest points", the one with the smallest S
-    // coordinate on the polyline is chosen.
+    // direction), negative if it is right of it.
+    // The S position of such a point outside the reference line is the same as
+    // the S value of the nearest point on the polyline.
+    //
+    // Notes:
+    // - The "nearest point on the polyline" is determined in 3D (even if the
+    //   resulting T value is only the 2D distance), in order to choose the
+    //   correct point for 3D curves (think reference lines for roads in parking
+    //   decks).
+    // - If there are several "nearest points", the one with the smallest S
+    //   coordinate on the polyline is chosen.
+    //
+    // ## Defining angles
     //
     // Sometimes an angle to a reference line is needed. This shall be defined
     // as follows:
@@ -102,6 +114,38 @@ message ReferenceLine
     // If the nearest point is at the edge between line segments, then the
     // angle of the following line shall be chosen.
     //
+    // ## Converting between world coordinates and ST coordinates
+    //
+    // The above rules define an ST coordinate system across the whole XY plane.
+    // Every XY position has a ST coordinate, but not necessarily a unique ST
+    // coordinate.
+    //
+    // Example:
+    // \image html OSI_ReferenceLine1.svg
+    //
+    // This shows a reference line (consisting of three points), and five points
+    // not on the reference line.
+    //
+    // - For \c P1, the situation is clear, since there is exactly one nearest
+    //   point on the polyline. The resulting ST coordinate uniquely maps back
+    //   to \c P1.
+    // - \c P2 has multiple points "nearest points" on the polyline.
+    //   As can be seen here, two  ST coordinates map to \c P2 (red and grey
+    //   dotted line).  Following the rules above, the one with the smallest S
+    //   value is chosen (the red dotted line).
+    // - \c P3 has a unique "nearest point" on the polyline. However, multiple
+    //   points map to the same ST coordinate as that of \c P3, e.g. \C P4
+    //   (drawn in grey).
+    // - Finally, \c P5 shows how the reference line is extended infinitely for
+    //   points that are "outside" the reference line.
+    //
+    // The sampling of the polyline must be chosen such that the error
+    // when converting coordinates is "small enough". The exact needed
+    // precision is defined for each user, where the reference line is
+    // referenced.
+    //
+    // ## Various notes
+    //
     // Notes on OpenDRIVE compatibility:
     // Ideally, one would want the polyline to be fully compatible with
     // OpenDRIVE, so that calculations done for OpenDRIVE directly match those
@@ -112,11 +156,11 @@ message ReferenceLine
     //   coordinate is no longer calculated in the XY plane (as proposed for
     //   OSI). It doesn't seem feasable to implement the same tilting for OSI,
     //   so simulation tools will have to consider superElevation and convert
-    //   the T coordinate accordingly: t_OSI = t_OpenDRIVE * cos(alpha), where
-    //   alpha is the superelevation angle.
+    //   the T coordinate accordingly: t_OSI = t_OpenDRIVE *
+    //   cos(alpha), where alpha is the superelevation angle.
     // - The angle will not be perfectly the same, due to the use of line
     //   segments in OSI, and curves in OpenDRIVE. In the authors opinion, the
-    //   difference will be negligible if the poly_line is suitably sampled.
+    //   difference will be negligible if the #poly_line is suitably sampled.
     //
     // Notes on design decisions:
     // - The S coordinate is included directly, both for OpenDRIVE
@@ -134,11 +178,11 @@ message ReferenceLine
     //
     message ReferenceLinePoint
     {
-        // A world position
+        // \brief A world position
 	//
         optional Vector3d world_position = 1;
 
-        // S position on the reference line
+        // \brief S position on the reference line
 	//
         optional double s_position = 2;
     }

From 35b87b5225ee3680e53fae9eee1e307569eba563 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Thu, 27 Jan 2022 15:23:54 +0100
Subject: [PATCH 18/37] Clarify when lanes should share a reference line

Also fix a Doxygen error.

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto   | 11 ++++++++---
 osi_referenceline.proto |  2 +-
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index f2d027c9e..8de73e7b7 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -303,7 +303,11 @@ message LogicalLaneBoundary
 // - The red area is the area where \c l1 overlaps \c l2. This is recorded in
 //   #overlapping_lane of \c l1.
 //
-// Note: all these relations are also defined outside of intersections.
+// As can be seen in the images, the two highlighted lanes are neighbours for
+// part of their length, but it makes no sense for them to have the same
+// reference line, since they diverge significantly.
+//
+// Note: all the relations shown above are also defined outside of intersections.
 //
 message LogicalLane
 {
@@ -398,8 +402,9 @@ message LogicalLane
     // not required that the reference line has the same direction as the
     // driving direction of the lane.
     //
-    // Neighbouring lanes are strongly encouraged to use the same
-    // reference_line, so that vehicles that are next to each other on
+    // Neighbouring lanes (i.e. lanes that are neighbours and whose directions
+    // do not diverge significantly) are strongly encouraged to reference the
+    // same ReferenceLine, so that vehicles that are next to each other on
     // neighbouring lanes have comparable S positions.
     //
     // The S coordinate of the reference line makes it easy to find e.g. which
diff --git a/osi_referenceline.proto b/osi_referenceline.proto
index c77aef49b..541ac6d85 100644
--- a/osi_referenceline.proto
+++ b/osi_referenceline.proto
@@ -134,7 +134,7 @@ message ReferenceLine
     //   dotted line).  Following the rules above, the one with the smallest S
     //   value is chosen (the red dotted line).
     // - \c P3 has a unique "nearest point" on the polyline. However, multiple
-    //   points map to the same ST coordinate as that of \c P3, e.g. \C P4
+    //   points map to the same ST coordinate as that of \c P3, e.g. \c P4
     //   (drawn in grey).
     // - Finally, \c P5 shows how the reference line is extended infinitely for
     //   points that are "outside" the reference line.

From 674315c62f18c4db646bfc5ea0dfcffb9916a280 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 11:26:39 +0100
Subject: [PATCH 19/37] Make example regarding difference between Lane and
 LogicalLane more general

The example is not limited to narrow roads.

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 8de73e7b7..4219bb9d4 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -240,9 +240,9 @@ message LogicalLaneBoundary
 //
 // A logical lane is part of a road. Compared to a physical lane (OSI type
 // \c Lane), its existence doesn't hinge on the existence of road markings. So
-// e.g. a narrow urban road with two driving directions but no road markings
-// in-between would be presented as two \link LogicalLane LogicalLanes\endlink,
-// but only one Lane. So one Lane can consist of multiple \link LogicalLane
+// e.g. a road with two driving directions but no road markings in-between
+// would be presented as two \link LogicalLane LogicalLanes\endlink, but only
+// one Lane. So one Lane can consist of multiple \link LogicalLane
 // LogicalLanes\endlink. E.g. on intersections, each driving path is one
 // LogicalLane, but the whole area is one \c Lane of type \link
 // osi3::Lane::Classification::TYPE_INTERSECTION \c TYPE_INTERSECTION \endlink.

From b29338fc009c6b0fed93ff5577c590dbf59d6ddb Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 11:30:04 +0100
Subject: [PATCH 20/37] Limit allowed Z error to 2cm

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 4219bb9d4..8bc22ce2c 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -78,8 +78,10 @@ message LogicalLaneBoundary
     // \image html line_approximation_error.svg "Approximation error"
     // Approximation error green line.
     //
-    // The Z error (difference in Z height between boundary_line and the "real"
-    // line) must also not exceed 5cm.
+    // The Z error (difference in Z height between #boundary_line and the
+    // "real" line) must not exceed 2cm. This is a stricter requirements than
+    // for errors in the XY plane, because Z differences between lanes
+    // influence driving very much.
     //
     // Note: if two lanes have different Z heights (e.g. a driving lane is
     // beside a sidewalk, where the sidewalk is 10cm higher than the road),

From 365e515ddc72a508adbf1eeced056ddcf12dd4ab Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 11:34:53 +0100
Subject: [PATCH 21/37] Move PASSING_RULE_OTHER to the top, according to OSI
 convention.

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 21 +++++++++++----------
 1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 8bc22ce2c..ad5db2546 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -200,10 +200,17 @@ message LogicalLaneBoundary
         //
         PASSING_RULE_UNKNOWN = 0;
 
+        // Passing rule fits neither of the other categories.
+        //
+        // Example: this type needs to be used if passing depends on the agent
+        // type, e.g. if cars may change lane, but trucks may not.
+        //
+        PASSING_RULE_OTHER = 1;
+
         // No passing is allowed (neither from left to right nor from right to
         // left).
         //
-        PASSING_RULE_NONE_ALLOWED = 1;
+        PASSING_RULE_NONE_ALLOWED = 2;
 
         // Only passing in increasing T direction allowed. Passing is allowed
         // from one lane to the other if the points on the target lane have
@@ -212,7 +219,7 @@ message LogicalLaneBoundary
         // driving direction), this means changing from right to left is
         // allowed.
         //
-        PASSING_RULE_INCREASING_T = 2;
+        PASSING_RULE_INCREASING_T = 3;
 
         // Only passing in decreasing T direction allowed. Passing is allowed
         // from one lane to the other if the points on the target lane have
@@ -221,19 +228,13 @@ message LogicalLaneBoundary
         // driving direction), this means changing from left to right is
         // allowed.
         //
-        PASSING_RULE_DECREASING_T = 3;
+        PASSING_RULE_DECREASING_T = 4;
 
         // Passing is allowed in both directions (left to right and right to
         // left).
         //
-        PASSING_RULE_BOTH_ALLOWED = 4;
+        PASSING_RULE_BOTH_ALLOWED = 5;
 
-        // Passing rule fits neither of the above categories.
-        //
-        // Example: this type needs to be used if passing depends on the agent
-        // type, e.g. if cars may change lane, but trucks may not.
-        //
-        PASSING_RULE_OTHER = 5;
     }
 }
 

From ba2fbe9395bf11410b2a4e1f8622d3962cf9c60b Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 11:42:10 +0100
Subject: [PATCH 22/37] Explain a bit where overlapping_lane should be filled

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index ad5db2546..d81e0db1f 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -483,6 +483,10 @@ message LogicalLane
     // Only overlaps laterally larger than 5cm are considered overlaps for the
     // purpose of this relation.
     //
+    // This will typically contain a lot of entries on intersections, but might
+    // also be used outside of intersections (e.g. if a #TYPE_BIKING lane
+    // overlaps a #TYPE_NORMAL lane).
+    //
     // Entries must be ordered: first by #start_s, then by #end_s.
     //
     repeated LaneRelation overlapping_lane = 11;

From c7634c8e5ad995a898f3079d78cabbc5b82074ee Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 11:48:34 +0100
Subject: [PATCH 23/37] Consistently use "intersection" instead of "junction"

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index d81e0db1f..b3b5eef31 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -250,7 +250,7 @@ message LogicalLaneBoundary
 // LogicalLane, but the whole area is one \c Lane of type \link
 // osi3::Lane::Classification::TYPE_INTERSECTION \c TYPE_INTERSECTION \endlink.
 //
-// Outside of junctions, logical lanes are constructed such that each point on
+// Outside of intersections, logical lanes are constructed such that each point on
 // the road belongs to at least one (typically: exactly one) logical lane. So
 // there are no gaps between logical lanes, and no areas that don't belong to a
 // logical lane.

From 7ffc417b0b6ffd9ae99bd265cc37efc783ddb734 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 11:51:36 +0100
Subject: [PATCH 24/37] Better explain where TYPE_BIKING and TYPE_SIDEWALK
 should be used

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index b3b5eef31..bddb3cb69 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -567,10 +567,14 @@ message LogicalLane
         TYPE_NORMAL = 2;
 
         // A lane that is designated for bicylists.
+        // Note that biking lanes that cross the road (e.g. on an intersection)
+        // are also labeled with this type.
         //
         TYPE_BIKING = 3;
 
         // A lane that is designated for pedestrians (sidewalk).
+        // Note that pedestrian lanes that cross the road (e.g. on an
+        // intersection) are also labeled with this type.
         //
         TYPE_SIDEWALK = 4;
 

From 28375fb7460ed4af4e47d640f70662e2e482b76d Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 12:03:21 +0100
Subject: [PATCH 25/37] Add TYPE_RAIL and TYPE_TRAM

This makes it possible to describe train crossings and similar

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index bddb3cb69..3bfc63dd4 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -633,6 +633,18 @@ message LogicalLane
         // height than the adjacent drivable lanes.
         //
         TYPE_CURB = 16;
+
+        // A rail lane. This lane covers the area a train needs to drive along
+        // its rails.
+        // #overlapping_lane then describes where a train crosses other lanes.
+        //
+        TYPE_RAIL = 17;
+
+        // A tram lane. This lane covers the area a tram needs to drive along
+        // its rails.
+        // #overlapping_lane then describes where a tram crosses other lanes.
+        //
+        TYPE_TRAM = 18;
     }
 
     //

From 1d84acb1357e90b97e7fa345f0e0baffa69ababd Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 13:30:09 +0100
Subject: [PATCH 26/37] Add note that PASSING_RULE_OTHER should be used between
 non-drivable lanes

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 3bfc63dd4..47fa9b205 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -205,6 +205,10 @@ message LogicalLaneBoundary
         // Example: this type needs to be used if passing depends on the agent
         // type, e.g. if cars may change lane, but trucks may not.
         //
+        // This value is also used between non-drivable lanes where the traffic
+        // regulations do not say anything about passing rules (e.g. for a lane
+        // boundary between lanes of TYPE_BORDER and TYPE_SHOULDER).
+        //
         PASSING_RULE_OTHER = 1;
 
         // No passing is allowed (neither from left to right nor from right to

From 83ac8e15f21c301abeffd247fc8d88ae2d7fac51 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 14:13:11 +0100
Subject: [PATCH 27/37] Clarify merging of lanes

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 47fa9b205..13edc2abe 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -238,7 +238,6 @@ message LogicalLaneBoundary
         // left).
         //
         PASSING_RULE_BOTH_ALLOWED = 5;
-
     }
 }
 
@@ -261,11 +260,11 @@ message LogicalLaneBoundary
 //
 // If OSI is generated from OpenDRIVE, then \link LogicalLane
 // LogicalLanes\endlink map directly to OpenDRIVE lanes. However, it is allowed
-// to merge multiple consecutive OpenDRIVE lanes with the same type into one
-// OSI LogicalLane: if an OpenDRIVE lane has a single successor, which has the
-// same lane type, and this successor has only one predecessor (so no lane
-// merging or splitting) then the two lanes may be presented as one continuous
-// LogicalLane. This may be done recursively.
+// to merge multiple consecutive (in S direction) OpenDRIVE lanes with the same
+// type into one OSI LogicalLane: if an OpenDRIVE lane has a single successor,
+// which has the same lane type, and this successor has only one predecessor
+// (so no lane merging or splitting) then the two lanes may be presented as one
+// continuous LogicalLane. This may be done recursively.
 //
 // The \link ReferenceLine reference line\endlink pointed to by
 // #reference_line_id defines an ST coordinate system for the lane. This ST

From 37bcd27e57c4a45cec7c15aa935930b840b298b0 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 14:26:37 +0100
Subject: [PATCH 28/37] Expand explanation on predecessor and successor

Use the definition from OpenDRIVE 1.7.

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 13edc2abe..d39bd7ed7 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -538,10 +538,30 @@ message LogicalLane
 
     // \brief Lanes that directly are connected to this lane at the beginning.
     //
+    // "Beginning" is relative to the reference line, so connections at #start_s.
+    //
+    // Lane predecessors and successors shall only be used to connect lanes if
+    // a physical connection at the beginning or end of both lanes exist. Both
+    // lanes have a non-zero width at the connection point and they are
+    // semantically connected.
+    //
+    // A lane may have several predecessors e.g. on intersections, or if a wide
+    // lane splits into two, or two merge into one.
+    //
     repeated LaneConnection predecessor_lane = 14;
 
     // \brief Lanes that directly are connected to this lane at the end.
     //
+    // "End" is relative to the reference line, so connections at #end_s.
+    //
+    // Lane predecessors and successors shall only be used to connect lanes if
+    // a physical connection at the beginning or end of both lanes exist. Both
+    // lanes have a non-zero width at the connection point and they are
+    // semantically connected.
+    //
+    // A lane may have several successors e.g. on intersections, or if a wide
+    // lane splits into two, or two merge into one.
+    //
     repeated LaneConnection successor_lane = 15;
 
     //

From d54a599036a35b95dc665b423497f139a58bc1ca Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 15:51:12 +0100
Subject: [PATCH 29/37] Support bidirectional lanes

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 55 ++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 6 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index d39bd7ed7..6c30c4789 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -286,7 +286,7 @@ message LogicalLaneBoundary
 // - The yellow line is the ReferenceLine of \c l1 . The ReferenceLine can be
 //   shared with other lanes.  Because the ReferenceLine has the same direction
 //   as the driving direction of \c l1 in this example,
-//   #reference_line_is_driving_direction == true.
+//   #move_direction == #MOVE_DIRECTION_INCREASING_S.
 // - The red line marks the area where \c l2 is left of
 //   \c l1 - this info is recorded in #left_adjacent_lane of \c l1.
 // - The red area is the area where \c l2 overlaps \c l1. This is recorded in
@@ -303,7 +303,7 @@ message LogicalLaneBoundary
 // - The yellow line is the ReferenceLine of \c l2 . The ReferenceLine can be
 //   shared with other lanes.  Because the ReferenceLine has the same direction
 //   as the driving direction of \c l2 in this example,
-//   #reference_line_is_driving_direction == true.
+//   #move_direction == #MOVE_DIRECTION_INCREASING_S.
 // - The green line marks the area where \c l1 is right of
 //   \c l2 - this info is recorded in #right_adjacent_lane of \c l2.
 // - The red area is the area where \c l1 overlaps \c l2. This is recorded in
@@ -442,10 +442,7 @@ message LogicalLane
 
     // \brief Definition of the intended driving direction.
     //
-    // \c true means driving direction is according to ascending S position.
-    // \c false means driving direction is according to descending S position.
-    //
-    optional bool reference_line_is_driving_direction = 8;
+    optional MoveDirection move_direction = 8;
 
     // \brief Lanes that are directly right of this lane, without gap or overlap.
     //
@@ -587,6 +584,10 @@ message LogicalLane
         // HighwayExit.
         // This matches the OpenDRIVE type "driving".
         //
+        // Note: a lane with OpenDRIVE type "bidirectional" will have an OSI
+        // type of TYPE_NORMAL, with #move_direction ==
+        // #MOVE_DIRECTION_BOTH_ALLOWED.
+        //
         TYPE_NORMAL = 2;
 
         // A lane that is designated for bicylists.
@@ -694,6 +695,48 @@ message LogicalLane
         optional double end_s = 3;
     }
 
+    //
+    // \brief Describes in which direction moving objects may typically move
+    // along a lane.
+    //
+    // This describes the allowed typical driving direction on a lane, or (in
+    // the case of pedestrian) the allowed walking direction.
+    //
+    // Note: Allowed overtaking (e.g. on country roads) does not automatically
+    // make a lane bidirectional, since vehicles may normally only drive in the
+    // other direction during the overtake maneuver, not for longer periods of
+    // time.
+    //
+    enum MoveDirection
+    {
+        // Move direction is unknown. Do not use in ground truth.
+        //
+        MOVE_DIRECTION_UNKNOWN = 0;
+
+        // Move direction fits neither of the other categories.
+        //
+        // Example: a lane where cars may only drive in one direction, but
+        // bikes may drive in both.
+        //
+        MOVE_DIRECTION_OTHER = 1;
+
+        // Objects may move in increasing S direction.
+        //
+        // This means they move in the same direction as the reference line.
+        //
+        MOVE_DIRECTION_INCREASING_S = 2;
+
+        // Objects may move in decreasing S direction.
+        //
+        // This means they move in the opposite direction as the reference line.
+        //
+        MOVE_DIRECTION_DECREASING_S = 3;
+
+        // Objects may move in both directions.
+        //
+        MOVE_DIRECTION_BOTH_ALLOWED = 4;
+    }
+
     //
     // \brief Connection to another lane (predecessor or successor)
     //

From 62df8991f0221433c498514e4c7abcb635b9de13 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 15:59:09 +0100
Subject: [PATCH 30/37] Remove LogicalLaneAssignment from non-Groundtruth
 objects

Signed-off-by: Thomas Bleher 
---
 osi_common.proto       | 8 --------
 osi_object.proto       | 8 ++++++++
 osi_roadmarking.proto  | 4 ++++
 osi_trafficlight.proto | 4 ++++
 osi_trafficsign.proto  | 8 ++++++++
 5 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/osi_common.proto b/osi_common.proto
index f9d0b3acd..3243a37a7 100644
--- a/osi_common.proto
+++ b/osi_common.proto
@@ -447,10 +447,6 @@ message BaseStationary
     // The polygon is defined counter-clockwise.
     //
     repeated Vector2d base_polygon = 4;
-
-    // Assignment of this object to logical lanes
-    //
-    repeated LogicalLaneAssignment logical_lane_assignment = 5;
 }
 
 //
@@ -573,10 +569,6 @@ message BaseMoving
     // The polygon is defined counter-clockwise.
     //
     repeated Vector2d base_polygon = 7;
-
-    // Assignment of this object to logical lanes
-    //
-    repeated LogicalLaneAssignment logical_lane_assignment = 9;
 }
 
 //
diff --git a/osi_object.proto b/osi_object.proto
index 215062706..dd70630d8 100644
--- a/osi_object.proto
+++ b/osi_object.proto
@@ -79,6 +79,10 @@ message StationaryObject
     //
     optional ColorDescription color_description = 6;
 
+    // Assignment of this object to logical lanes
+    //
+    repeated LogicalLaneAssignment logical_lane_assignment = 7;
+
     //
     // \brief Classification data for a stationary object.
     //
@@ -483,6 +487,10 @@ message MovingObject
     //
     optional ColorDescription color_description = 11;
 
+    // Assignment of this object to logical lanes
+    //
+    repeated LogicalLaneAssignment logical_lane_assignment = 12;
+
     // Definition of object types.
     //
     enum Type
diff --git a/osi_roadmarking.proto b/osi_roadmarking.proto
index 0b9ce9a95..ef49ba034 100644
--- a/osi_roadmarking.proto
+++ b/osi_roadmarking.proto
@@ -90,6 +90,10 @@ message RoadMarking
     //
     optional ColorDescription color_description = 5;
 
+    // Assignment of this object to logical lanes
+    //
+    repeated LogicalLaneAssignment logical_lane_assignment = 6;
+
     //
     // \brief \c Classification data for a road surface marking.
     //
diff --git a/osi_trafficlight.proto b/osi_trafficlight.proto
index ace90bccd..d27aee343 100644
--- a/osi_trafficlight.proto
+++ b/osi_trafficlight.proto
@@ -71,6 +71,10 @@ message TrafficLight
     //
     optional ColorDescription color_description = 6;
 
+    // Assignment of this object to logical lanes
+    //
+    repeated LogicalLaneAssignment logical_lane_assignment = 7;
+
     //
     // \brief \c Classification data for a traffic light.
     //
diff --git a/osi_trafficsign.proto b/osi_trafficsign.proto
index 7436e81c0..03730f85f 100644
--- a/osi_trafficsign.proto
+++ b/osi_trafficsign.proto
@@ -214,6 +214,10 @@ message TrafficSign
         //
         optional string model_reference = 3;
 
+        // Assignment of this object to logical lanes
+        //
+        repeated LogicalLaneAssignment logical_lane_assignment = 4;
+
         //
         // \brief \c Classification data for a traffic sign.
         //
@@ -5569,6 +5573,10 @@ message TrafficSign
         //
         optional string model_reference = 3;
 
+        // Assignment of this object to logical lanes
+        //
+        repeated LogicalLaneAssignment logical_lane_assignment = 4;
+
         //
         // \brief \c Classification data for a supplementary traffic sign.
         //

From 065aaa500b9b409f25d63b7e35b0f2668d2d250c Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Mon, 31 Jan 2022 22:01:27 +0100
Subject: [PATCH 31/37] Add new files to setup.py

This makes the python build work

Signed-off-by: Thomas Bleher 
---
 setup.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/setup.py b/setup.py
index 70423591e..dcc8ba688 100644
--- a/setup.py
+++ b/setup.py
@@ -67,6 +67,8 @@ def find_protoc():
         'osi_object.proto',
         'osi_occupant.proto',
         'osi_lane.proto',
+        'osi_logicallane.proto',
+        'osi_referenceline.proto',
         'osi_sensordata.proto',
         'osi_sensorviewconfiguration.proto',
         'osi_sensorspecific.proto',

From a91199244aae61f6cee2a15548fa6ce5d864e0fd Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Tue, 1 Feb 2022 10:38:22 +0100
Subject: [PATCH 32/37] Remove tabs

Signed-off-by: Thomas Bleher 
---
 osi_referenceline.proto | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/osi_referenceline.proto b/osi_referenceline.proto
index 541ac6d85..cd8963add 100644
--- a/osi_referenceline.proto
+++ b/osi_referenceline.proto
@@ -179,11 +179,11 @@ message ReferenceLine
     message ReferenceLinePoint
     {
         // \brief A world position
-	//
+        //
         optional Vector3d world_position = 1;
 
         // \brief S position on the reference line
-	//
+        //
         optional double s_position = 2;
     }
 }

From d2048d80179e07f5dee6d2b9bbdc9ce16762ac42 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Wed, 2 Feb 2022 14:20:56 +0100
Subject: [PATCH 33/37] Move LogicalLaneAssignment to Classification

Signed-off-by: Thomas Bleher 
---
 osi_object.proto       | 23 +++++++++++++----------
 osi_roadmarking.proto  | 10 ++++++----
 osi_trafficlight.proto | 10 ++++++----
 osi_trafficsign.proto  | 22 ++++++++++++++--------
 4 files changed, 39 insertions(+), 26 deletions(-)

diff --git a/osi_object.proto b/osi_object.proto
index dd70630d8..fc2aa9bde 100644
--- a/osi_object.proto
+++ b/osi_object.proto
@@ -79,10 +79,6 @@ message StationaryObject
     //
     optional ColorDescription color_description = 6;
 
-    // Assignment of this object to logical lanes
-    //
-    repeated LogicalLaneAssignment logical_lane_assignment = 7;
-
     //
     // \brief Classification data for a stationary object.
     //
@@ -128,6 +124,12 @@ message StationaryObject
         //
         repeated double assigned_lane_percentage = 7;
 
+        // Assignment of this object to logical lanes.
+        //
+        // \note OSI uses singular instead of plural for repeated field names.
+        //
+        repeated LogicalLaneAssignment logical_lane_assignment = 8;
+
         // Definition of object types.
         //
         enum Type
@@ -487,10 +489,6 @@ message MovingObject
     //
     optional ColorDescription color_description = 11;
 
-    // Assignment of this object to logical lanes
-    //
-    repeated LogicalLaneAssignment logical_lane_assignment = 12;
-
     // Definition of object types.
     //
     enum Type
@@ -704,8 +702,13 @@ message MovingObject
         //
         // \note OSI uses singular instead of plural for repeated field names.
         //
-        repeated double assigned_lane_percentage = 2;        
-        
+        repeated double assigned_lane_percentage = 2;
+
+        // Assignment of this object to logical lanes.
+        //
+        // \note OSI uses singular instead of plural for repeated field names.
+        //
+        repeated LogicalLaneAssignment logical_lane_assignment = 3;
     }
 
     //
diff --git a/osi_roadmarking.proto b/osi_roadmarking.proto
index ef49ba034..d8ed5a2e0 100644
--- a/osi_roadmarking.proto
+++ b/osi_roadmarking.proto
@@ -90,10 +90,6 @@ message RoadMarking
     //
     optional ColorDescription color_description = 5;
 
-    // Assignment of this object to logical lanes
-    //
-    repeated LogicalLaneAssignment logical_lane_assignment = 6;
-
     //
     // \brief \c Classification data for a road surface marking.
     //
@@ -260,6 +256,12 @@ message RoadMarking
         //
         optional string sub_code = 11;
 
+        // Assignment of this object to logical lanes.
+        //
+        // \note OSI uses singular instead of plural for repeated field names.
+        //
+        repeated LogicalLaneAssignment logical_lane_assignment = 12;
+
         // Definition of road marking types.
         //
         enum Type
diff --git a/osi_trafficlight.proto b/osi_trafficlight.proto
index d27aee343..887a99fd4 100644
--- a/osi_trafficlight.proto
+++ b/osi_trafficlight.proto
@@ -71,10 +71,6 @@ message TrafficLight
     //
     optional ColorDescription color_description = 6;
 
-    // Assignment of this object to logical lanes
-    //
-    repeated LogicalLaneAssignment logical_lane_assignment = 7;
-
     //
     // \brief \c Classification data for a traffic light.
     //
@@ -131,6 +127,12 @@ message TrafficLight
         //
         optional bool is_out_of_service = 6;
 
+        // Assignment of this object to logical lanes.
+        //
+        // \note OSI uses singular instead of plural for repeated field names.
+        //
+        repeated LogicalLaneAssignment logical_lane_assignment = 7;
+
         // Definition of semantic colors for traffic lights.
         //
         // \note The color types represent the semantic classification of a traffic light
diff --git a/osi_trafficsign.proto b/osi_trafficsign.proto
index 03730f85f..5be493ebc 100644
--- a/osi_trafficsign.proto
+++ b/osi_trafficsign.proto
@@ -214,10 +214,6 @@ message TrafficSign
         //
         optional string model_reference = 3;
 
-        // Assignment of this object to logical lanes
-        //
-        repeated LogicalLaneAssignment logical_lane_assignment = 4;
-
         //
         // \brief \c Classification data for a traffic sign.
         //
@@ -381,6 +377,13 @@ message TrafficSign
             //
             optional string sub_code = 11;
 
+            // Assignment of this object to logical lanes.
+            //
+            // \note OSI uses singular instead of plural for repeated field
+            // names.
+            //
+            repeated LogicalLaneAssignment logical_lane_assignment = 12;
+
             // Definition of traffic sign types.
             // Numbers are given according to German StVO.
             //
@@ -5573,10 +5576,6 @@ message TrafficSign
         //
         optional string model_reference = 3;
 
-        // Assignment of this object to logical lanes
-        //
-        repeated LogicalLaneAssignment logical_lane_assignment = 4;
-
         //
         // \brief \c Classification data for a supplementary traffic sign.
         //
@@ -5706,6 +5705,13 @@ message TrafficSign
             //
             optional string sub_code = 11;
 
+            // Assignment of this object to logical lanes.
+            //
+            // \note OSI uses singular instead of plural for repeated field
+            // names.
+            //
+            repeated LogicalLaneAssignment logical_lane_assignment = 12;
+
             // Definition of supplementary sign types.
             //
             // For general supplementary signs use \c #TYPE_TEXT.

From e73cd474031e926acb374345e0b964a30a2dd49c Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Wed, 2 Feb 2022 14:40:35 +0100
Subject: [PATCH 34/37] Fix test_brief_necessity errors

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto   | 72 ++++++++++++++++++++---------------------
 osi_referenceline.proto |  8 ++---
 2 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 6c30c4789..32454569c 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -47,7 +47,7 @@ package osi3;
 //
 message LogicalLaneBoundary
 {
-    // \brief The ID of the lane boundary.
+    // The ID of the lane boundary.
     //
     // \rules
     // is_globally_unique
@@ -55,7 +55,7 @@ message LogicalLaneBoundary
     //
     optional Identifier id = 1;
 
-    // \brief Points making up the lane boundary.
+    // Points making up the lane boundary.
     //
     // The boundary must be defined in the same direction as the reference
     // line. So S positions should increase along the line. Note that S
@@ -90,7 +90,7 @@ message LogicalLaneBoundary
     //
     repeated LogicalBoundaryPoint boundary_line = 2;
 
-    // \brief The reference line for this boundary.
+    // The reference line for this boundary.
     //
     // The reference line is used as a coordinate system for this boundary.
     // All points of this LogicalLaneBoundary must have S coordinates in the
@@ -106,8 +106,8 @@ message LogicalLaneBoundary
     //
     optional Identifier reference_line_id = 3;
 
-    // \brief Reference to the physical lane boundary or boundaries that make
-    // up this logical boundary.
+    // Reference to the physical lane boundary or boundaries that make up this
+    // logical boundary.
     //
     // Rules and notes:
     // - This list is empty if there are no physical lane boundaries to delimit
@@ -147,12 +147,12 @@ message LogicalLaneBoundary
     //
     repeated Identifier physical_boundary_id = 4;
 
-    // \brief The passing rules, insomuch as they can be determined just from
-    // road markings.
+    // The passing rules, insomuch as they can be determined just from road
+    // markings.
     //
     optional PassingRule passing_rule = 5;
 
-    // \brief Optional external reference to the lane boundary source.
+    // Optional external reference to the lane boundary source.
     //
     // \note For OpenDRIVE, there is no direct possibility to reference the
     //       RoadMark, as there is no unique identifier in this sub-object.
@@ -188,7 +188,7 @@ message LogicalLaneBoundary
     }
 
     //
-    // \brief Passing rule of the LogicalLaneBoundary.
+    // Passing rule of the LogicalLaneBoundary.
     //
     // This describes how vehicles may move across the LogicalLaneBoundary. The
     // PassingRule is determined solely based on the road, not on any signs
@@ -317,7 +317,7 @@ message LogicalLaneBoundary
 //
 message LogicalLane
 {
-    // \brief The ID of the logical lane.
+    // The ID of the logical lane.
     //
     // \note Note ID is global unique.
     //
@@ -327,11 +327,11 @@ message LogicalLane
     //
     optional Identifier id = 1;
 
-    // \brief The type of the logical lane.
+    // The type of the logical lane.
     //
     optional Type type = 2;
 
-    // \brief Optional external reference to the lane source.
+    // Optional external reference to the lane source.
     //
     // The external reference points to the source of the lane, if it is derived
     // from one or more objects or external references.
@@ -355,7 +355,7 @@ message LogicalLane
     //
     repeated ExternalReference source_reference = 3;
 
-    // \brief Reference to the physical lanes this logical lane belongs to.
+    // Reference to the physical lanes this logical lane belongs to.
     //
     // This makes it possible to get detailed information on the physical lane
     // properties, e.g. the visual colors of the boundaries, the road
@@ -399,7 +399,7 @@ message LogicalLane
     //
     repeated PhysicalLaneReference physical_lane_reference = 4;
 
-    // \brief The \link ReferenceLine reference line\endlink for this logical lane
+    // The \link ReferenceLine reference line\endlink for this logical lane
     //
     // The reference line is used as a coordinate system on this lane.
     //
@@ -426,13 +426,13 @@ message LogicalLane
     //
     optional Identifier reference_line_id = 5;
 
-    // \brief Start S position of the lane.
+    // Start S position of the lane.
     //
     // Must be in range [\c sStart,\c sEnd] of the reference line.
     //
     optional double start_s = 6;
 
-    // \brief End S position of the lane.
+    // End S position of the lane.
     //
     // Must be in range [\c sStart,\c sEnd] of the reference line.
     //
@@ -440,11 +440,11 @@ message LogicalLane
     //
     optional double end_s = 7;
 
-    // \brief Definition of the intended driving direction.
+    // Definition of the intended driving direction.
     //
     optional MoveDirection move_direction = 8;
 
-    // \brief Lanes that are directly right of this lane, without gap or overlap.
+    // Lanes that are directly right of this lane, without gap or overlap.
     //
     // "Right" is in definition direction (not driving direction), so right lanes
     // have smaller T coordinates.
@@ -461,7 +461,7 @@ message LogicalLane
     //
     repeated LaneRelation right_adjacent_lane = 9;
 
-    // \brief Lanes that are directly left of this lane, without gap or overlap.
+    // Lanes that are directly left of this lane, without gap or overlap.
     //
     // "Left" is in definition direction (not driving direction), so left lanes
     // have larger T coordinates.
@@ -478,7 +478,7 @@ message LogicalLane
     //
     repeated LaneRelation left_adjacent_lane = 10;
 
-    // \brief Lanes that partially or completely overlap this lane.
+    // Lanes that partially or completely overlap this lane.
     //
     // Only overlaps laterally larger than 5cm are considered overlaps for the
     // purpose of this relation.
@@ -491,7 +491,7 @@ message LogicalLane
     //
     repeated LaneRelation overlapping_lane = 11;
 
-    // \brief Right boundary of this lane.
+    // Right boundary of this lane.
     //
     // References to LogicalLaneBoundary elements.
     // All LogicalLaneBoundary elements referenced here must refer to the same
@@ -512,7 +512,7 @@ message LogicalLane
     //
     repeated Identifier right_boundary_id = 12;
 
-    // \brief Left boundary of this lane.
+    // Left boundary of this lane.
     //
     // References to LogicalLaneBoundary elements.
     // All LogicalLaneBoundary elements referenced here must refer to the same
@@ -533,7 +533,7 @@ message LogicalLane
     //
     repeated Identifier left_boundary_id = 13;
 
-    // \brief Lanes that directly are connected to this lane at the beginning.
+    // Lanes that directly are connected to this lane at the beginning.
     //
     // "Beginning" is relative to the reference line, so connections at #start_s.
     //
@@ -547,7 +547,7 @@ message LogicalLane
     //
     repeated LaneConnection predecessor_lane = 14;
 
-    // \brief Lanes that directly are connected to this lane at the end.
+    // Lanes that directly are connected to this lane at the end.
     //
     // "End" is relative to the reference line, so connections at #end_s.
     //
@@ -562,7 +562,7 @@ message LogicalLane
     repeated LaneConnection successor_lane = 15;
 
     //
-    // \brief Definition of available lane types.
+    // Definition of available lane types.
     //
     // This is mostly aligned with OpenDRIVE, except that lane types modelling
     // access restrictions (e.g. "taxi") are not made available here. These are
@@ -676,7 +676,7 @@ message LogicalLane
     //
     message PhysicalLaneReference
     {
-        // \brief Id of the physical lane referenced.
+        // Id of the physical lane referenced.
         //
         // \rules
         // refers_to: Lane
@@ -684,11 +684,11 @@ message LogicalLane
         //
         optional Identifier physical_lane_id = 1;
 
-        // \brief S position on the logical lane where the physical lane starts.
+        // S position on the logical lane where the physical lane starts.
         //
         optional double start_s = 2;
 
-        // \brief S position on the logical lane where the physical lane ends.
+        // S position on the logical lane where the physical lane ends.
         //
         // Requirement: #end_s > #start_s
         //
@@ -696,8 +696,8 @@ message LogicalLane
     }
 
     //
-    // \brief Describes in which direction moving objects may typically move
-    // along a lane.
+    // Describes in which direction moving objects may typically move along a
+    // lane.
     //
     // This describes the allowed typical driving direction on a lane, or (in
     // the case of pedestrian) the allowed walking direction.
@@ -742,7 +742,7 @@ message LogicalLane
     //
     message LaneConnection
     {
-        // \brief Id of the other logical lane that is connected.
+        // Id of the other logical lane that is connected.
         //
         // \rules
         // refers_to: LogicalLane
@@ -762,7 +762,7 @@ message LogicalLane
     //
     message LaneRelation
     {
-        // \brief Id of the other logical lane.
+        // Id of the other logical lane.
         //
         // \rules
         // refers_to: LogicalLane
@@ -770,24 +770,24 @@ message LogicalLane
         //
         optional Identifier other_lane_id = 1;
 
-        // \brief Start s position of the relation.
+        // Start s position of the relation.
         //
         optional double start_s = 2;
 
-        // \brief End s position of the relation.
+        // End s position of the relation.
         //
         // Requirement: #end_s > #start_s
         //
         optional double end_s = 3;
 
-        // \brief Start s position of the relation on the other lane.
+        // Start s position of the relation on the other lane.
         //
         // This is the same place as #start_s, but measured along the reference
         // line of the other lane.
         //
         optional double start_s_other = 4;
 
-        // \brief End s position of the relation on the other lane.
+        // End s position of the relation on the other lane.
         //
         // This is the same place as #end_s, but measured along the reference
         // line of the other lane.
diff --git a/osi_referenceline.proto b/osi_referenceline.proto
index cd8963add..1a1c39e20 100644
--- a/osi_referenceline.proto
+++ b/osi_referenceline.proto
@@ -21,7 +21,7 @@ package osi3;
 //
 message ReferenceLine
 {
-    // \brief The ID of the logical lane.
+    // The ID of the logical lane.
     //
     // \note Note ID is global unique.
     //
@@ -31,7 +31,7 @@ message ReferenceLine
     //
     optional Identifier id = 1;
 
-    // \brief Points comprising the polyline.
+    // Points comprising the polyline.
     //
     // At least 2 points must be given.
     // The polyline is defined as the lines between consecutive points.
@@ -178,11 +178,11 @@ message ReferenceLine
     //
     message ReferenceLinePoint
     {
-        // \brief A world position
+        // A world position
         //
         optional Vector3d world_position = 1;
 
-        // \brief S position on the reference line
+        // S position on the reference line
         //
         optional double s_position = 2;
     }

From 34484f41b60848148e3e19a80e06840cbe1500e6 Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Thu, 24 Mar 2022 11:20:05 +0100
Subject: [PATCH 35/37] Add a small note on the heights of the boundary.

Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 32454569c..554eba17e 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -9,7 +9,7 @@ package osi3;
 //
 // \brief Boundary line of a LogicalLane
 //
-// Similar to a LaneBoundary, but with a reference and ST positions.
+// Similar to a LaneBoundary, but with a reference line and ST positions.
 //
 // A logical lane boundary describes the boundary between two logical lanes. As
 // such, there will always be exactly one logical lane boundary between two
@@ -23,6 +23,11 @@ package osi3;
 // marking), then the single LogicalLaneBoundary describing the boundary between
 // two logical lanes should be between the physical boundaries.
 //
+// A logical lane boundary consists of a list of \link LogicalBoundaryPoint
+// LogicalBoundaryPoints\endlink. Each point has a XYZ and an ST coordinate.
+// The XYZ coordinates describe the position and height of the boundary in the
+// world.
+//
 // Notes on design decisions:
 // - The LogicalLaneBoundary has ST coordinates, and is thus a separate type
 //   from LaneBoundary.
@@ -79,7 +84,7 @@ message LogicalLaneBoundary
     // Approximation error green line.
     //
     // The Z error (difference in Z height between #boundary_line and the
-    // "real" line) must not exceed 2cm. This is a stricter requirements than
+    // "real" line) must not exceed 2cm. This is a stricter requirement than
     // for errors in the XY plane, because Z differences between lanes
     // influence driving very much.
     //

From c3c0244f392938d4cbee073eeecb539d5261de6d Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Thu, 24 Mar 2022 11:53:19 +0100
Subject: [PATCH 36/37] Add a note on how to create reference lines for map
 formats without reference lines

Signed-off-by: Thomas Bleher 
---
 osi_referenceline.proto | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/osi_referenceline.proto b/osi_referenceline.proto
index 1a1c39e20..d8622eeaa 100644
--- a/osi_referenceline.proto
+++ b/osi_referenceline.proto
@@ -144,6 +144,23 @@ message ReferenceLine
     // precision is defined for each user, where the reference line is
     // referenced.
     //
+    // ## Creating reference lines
+    //
+    // When OSI is generated from OpenDRIVE, typically the reference lines will
+    // be taken directly from the road reference lines in OpenDRIVE, and
+    // sampled according to the accuracy requirements outlined above.
+    //
+    // Other map formats may not have reference lines, so they will have to be
+    // synthesized by the tool generating OSI data. A few guidelines on this
+    // process:
+    //
+    // - The reference line should follow the road
+    // - It is preferable to have the reference line in the center of the road
+    //   (e.g. on a highway, it should be in the middle between the two driving
+    //   directions). Rationale: this makes S differences better approximate
+    //   euclidean distances, compared to having the reference line at one side
+    //   of a curvy road.
+    //
     // ## Various notes
     //
     // Notes on OpenDRIVE compatibility:

From c7dc6eabe81db20ad9f18900ff484c78ec48d52a Mon Sep 17 00:00:00 2001
From: Thomas Bleher 
Date: Tue, 29 Mar 2022 22:34:28 +0200
Subject: [PATCH 37/37] Explain how curbs are handled

Apply suggestions from code review

Co-authored-by: clemenshabedank 
Signed-off-by: Thomas Bleher 
---
 osi_logicallane.proto | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)

diff --git a/osi_logicallane.proto b/osi_logicallane.proto
index 554eba17e..a0c28f602 100644
--- a/osi_logicallane.proto
+++ b/osi_logicallane.proto
@@ -195,8 +195,9 @@ message LogicalLaneBoundary
     //
     // Passing rule of the LogicalLaneBoundary.
     //
-    // This describes how vehicles may move across the LogicalLaneBoundary. The
-    // PassingRule is determined solely based on the road, not on any signs
+    // This describes how vehicles are legally allowed to move across the 
+    // LogicalLaneBoundary. The PassingRule is determined solely based 
+    // on the semantics of (physical) lane boundaries, not on any signs
     // (i.e. it may be overridden by signs).
     //
     enum PassingRule
@@ -210,9 +211,11 @@ message LogicalLaneBoundary
         // Example: this type needs to be used if passing depends on the agent
         // type, e.g. if cars may change lane, but trucks may not.
         //
-        // This value is also used between non-drivable lanes where the traffic
-        // regulations do not say anything about passing rules (e.g. for a lane
-        // boundary between lanes of TYPE_BORDER and TYPE_SHOULDER).
+        // This value is also used between LogicalLanes where the traffic
+        // regulations do not say anything about passing rules (e.g. for a 
+        // LogicalLaneBoundary between LogicalLanes of TYPE_NORMAL 
+        // and TYPE_CURB or between LogicalLanes of TYPE_BORDER and 
+        // TYPE_SHOULDER) .
         //
         PASSING_RULE_OTHER = 1;
 
@@ -398,6 +401,9 @@ message LogicalLane
     // physical_lane_reference does not give any information how much of the
     // area of a physical lane is covered by a logical lane.
     //
+    // For LogicalLanes without a correspondence to a Lane.Classification.Subtype 
+    // (i.e. TYPE_MEDIAN, TYPE_CURB, TYPE_TRAM, TYPE_RAIL) this field has no value.
+    //
     // \rules
     // refers_to: Lane
     // \endrules
@@ -511,6 +517,11 @@ message LogicalLane
     // Note: the referenced boundaries may have points outside of
     // \[#start_s,#end_s\] (e.g. a boundary may extend beyond the end of a lane).
     //
+    // Note: A curb is a type of LogicalLane and of LaneBoundary. 
+    // If LogicalLane.Type == TYPE_CURB, by convention this
+    // field references the respective LaneBoundary of TYPE_CURB
+    // identically to the left_boundary_id of this LogicalLane.
+    //
     // \rules
     // refers_to: LogicalLaneBoundary
     // \endrules
@@ -532,6 +543,11 @@ message LogicalLane
     // Note: the referenced boundaries may have points outside of
     // \[#start_s,#end_s\] (e.g. a boundary may extend beyond the end of a lane).
     //
+    // Note: A curb is a type of LogicalLane and of LaneBoundary. 
+    // If LogicalLane.Type == TYPE_CURB, by convention this
+    // field references the respective LaneBoundary of TYPE_CURB.
+    // identically to the right_boundary_id of this LogicalLane.    
+    //
     // \rules
     // refers_to: LogicalLaneBoundary
     // \endrules