Commit 070eade0 authored by Sergi Hernandez's avatar Sergi Hernandez
Browse files

Updated the road documentation.

parent 6b4d881d
...@@ -5,37 +5,61 @@ COpendriveRoad ...@@ -5,37 +5,61 @@ COpendriveRoad
This class describes the whole road as a set of [COpendriveRoadSegment](opendrive_road_segment.md) objects. This class handles the creation and destruction of all road elements (road segments, lanes and road node) when the opendrive file is loaded. Once loaded, it is possible to access all the elements and information of the road, but its impossible to modify it. This class describes the whole road as a set of [COpendriveRoadSegment](opendrive_road_segment.md) objects. This class handles the creation and destruction of all road elements (road segments, lanes and road node) when the opendrive file is loaded. Once loaded, it is possible to access all the elements and information of the road, but its impossible to modify it.
## Example road
The road shown in the next figure will be used to complete the description of all classes with an example. The opendrive road descrption can be downloaded [here]().
<img src="images/original_road.png" alt="Opendrive road description used as an example" width="814" height="594">
The dotted lines represent the limits of adjacent road segments. Each road segment include its name and the opendrive segment identifier (in parenthesis). The name of the two road junctions are also displayed but the name of each junction road is omitted for clarity. The names of the road junctions follows the next format:
```
<junction_name>_<origin_road_id>_<origin_lane_id>_<target_road_id>_<target_lane_id>
```
## Main features ## Main features
The main features of this class are: The main features of this class are:
* Load the Opendrive description from a file. At the moment the only supported Opendrive version is the 1.4. * Load the Opendrive description from a file. At the moment the only supported Opendrive version is the 1.4.
* Provides access to all the road segments of the road defined as [COpendriveRoadSegment](opendrive_road_segment.md) objects. The road segments can be accessed by several different ways: * Provides access to all the road segments of the road defined as [COpendriveRoadSegment](opendrive_road_segment.md) objects. The road segments can be accessed by several different ways:
* **by index**: which is an arbitray number assigned when the road is loaded and coincides with the order in which the road segments are described in the Opendrive file. This approach may be usefull to cycle through all the segment to gather global information. * **by index**: which is a unique arbitrary number assigned when the road is loaded and coincides with the order in which the road segments are described in the Opendrive file. This approach may be useful to cycle through all the segment to gather global information.
* **by id**: which is the numerical identifier assigned in the Opendrive file. * **by id**: which is the numerical identifier assigned in the Opendrive file.
* **by name**: which is the string identifier assigned in the Opendrive file. * **by name**: which is the string identifier assigned in the Opendrive file.
* **by the closest position**: in this case when the position of interest is known (i.e. the position of the car, an obstacle, etc...), it is possible to get the road segment which is closest to this position. It is possible to get the index of the road segment of interest or a reference to it. * **by the closest pose**: in this case when the position of interest is known (i.e. the position of the car, an obstacle, etc...), it is possible to get the road segment which is closest to this position. It is possible to get the index of the road segment of interest or a reference to it.
* Provides access to all the road lanes of the road defined as [COpendriveLane](opendrive_lane.md) objects. The road lanes can be accessed by two different ways: * Provides access to all the road lanes of the road defined as [COpendriveLane](opendrive_lane.md) objects. The road lanes can be accessed by two different ways:
* **by index**: which is an arbitray number assigned when the road is loaded. This approach may be usefull to cycle through all the lanes to gather global information. * **by index**: which is a unique arbitrary number assigned when the road is loaded. This approach may be useful to cycle through all the lanes to gather global information.
* **by the closest position**: in this case when the position of interest is known (i.e. the position of the car, an obstacle, etc...), it is possible to get the road lane which is closest to this position. It is possible to get the index of the road lane of interest or a reference to it. * **by the closest pose**: in this case when the position of interest is known (i.e. the position of the car, an obstacle, etc...), it is possible to get the road lane which is closest to this position. It is possible to get the index of the road lane of interest or a reference to it.
* Provides access to all the road nodes of the road defined as [COpendriveRoadNode](opendrive_road_node.md) objects. The road nodes can be accessed by two different ways: * Provides access to all the road nodes of the road defined as [COpendriveRoadNode](opendrive_road_node.md) objects. The road nodes can be accessed by two different ways:
* **by index**: which is an arbitray number assigned when the road is loaded. This approach may be usefull to cycle through all the lanes to gather global information. * **by index**: which is a unique arbitrary number assigned when the road is loaded. This approach may be useful to cycle through all the lanes to gather global information.
* **by the closest position**: in this case when the position of interest is known (i.e. the position of the car, an obstacle, etc...), it is possible to get the road node which is closest to this position. It is possible to get the index of the road node of interest or a reference to it. * **by the closest pose**: in this case when the position of interest is known (i.e. the position of the car, an obstacle, etc...), it is possible to get the road node which is closest to this position. It is possible to get the index of the road node of interest or a reference to it.
* It is also possible to find the closest position (or positions) to the road independently of the road element where it belongs. In this case, a maximum distance parameter can be set to collect more than one candidate. * It is possible to find the closest position to the road independently of the road element where it belongs.
* It is possible to generate a new road object as a subset of the original road, which are completelly independenat from each other (that is ....). There exist three possible ways to generate a subroad: * It is possible to get a set of poses that are closer to a given pose than a given distance threshold, independently of the road element where they belong.
* **by copy**: in this case the new road is just a copy of the original one. candidate.
* **by path**: in this case the new road only has the road elements that include a set of road nodes (a path). This method generates a road with a single track. * It is possible to generate a new road object as a subset of the original road, which are completely independent from each other. See the [sub-roads](#sub_roads) section for further details.
* **by distance**: in this case the new road only has the road elements that are inside a range from a given position, following the direction of the traffic (that is ....). This method only works with road with a single track. * In case of unexpected errors, this class throws an instance of CException. All other errors are reported to the user.
For further details on the implementation of these features check the doxygen API documentation. For further details on the implementation of these features check the doxygen API documentation.
## Unsupported Opendrive features ## Unsupported Opendrive features
Not all features of the Opendrive standrad are supported by the current implementation. The limitations are listed next: Not all features of the Opendrive standard are supported by the current implementation. The limitations are listed here:
* Each road segment can have only one lane section, which implies that the number of left and right lanes is the same for all the segment. * Each road segment can have only one lane section, which implies that the number of left and right lanes is the same for all the segment.
* Each lane must have the same width for each segment. * Each lane must have the same width for each segment.
## Sub-roads
One important feature of this class is the possibility to create new roads with a sub-set of the original road elements. The original road elements are created when the Opendrive file is loaded and can not be modified afterwards. When a sub-road is generated, new elements are created while keeping the required original information and connectivity, resulting in two completely independent objects. The only information that changes in the new sub-road is:
* the remaining road segments, lanes and road nodes are re-indexed, so that their unique index is coherent with the new data structure.
* for any open road segment (that is, a road segment that is not connected), new road nodes are placed at the end of the open road segment to keep its lane and link geometric information.
Three different ways to create a new sub-road are supported:
* copy: in this case the new road is just a copy of the original one.
* path: in this case the new road only has the road elements that include a set of road nodes (a path).
* distance: in this case the new road only has the road elements that within a distance to a given pose, following the direction of the traffic.
The next images shows an example of sub-road generation for the last two cases.
* They all have a parameter to indicate the desired heading tolerance when searching for the closest element.
...@@ -23,7 +23,6 @@ class COpendriveRoad ...@@ -23,7 +23,6 @@ class COpendriveRoad
double scale_factor; double scale_factor;
double min_road_length; double min_road_length;
protected: protected:
COpendriveRoadSegment *get_segment_by_id(std::string &id);
void free(void); void free(void);
void link_segments(OpenDRIVE &open_drive); void link_segments(OpenDRIVE &open_drive);
unsigned int add_node(COpendriveRoadNode *node); unsigned int add_node(COpendriveRoadNode *node);
...@@ -66,7 +65,7 @@ class COpendriveRoad ...@@ -66,7 +65,7 @@ class COpendriveRoad
* \brief Sets the resolution * \brief Sets the resolution
* *
* This functions sets the default resolution used to generate all the internal * This functions sets the default resolution used to generate all the internal
* geomtry. This functions automatically changes the resolution of all underlying * geometry. This functions automatically changes the resolution of all underlying
* objects. * objects.
* *
* \param res desired value of the resolution in meters. The default resolution * \param res desired value of the resolution in meters. The default resolution
...@@ -77,7 +76,7 @@ class COpendriveRoad ...@@ -77,7 +76,7 @@ class COpendriveRoad
* \brief Sets the scale factor * \brief Sets the scale factor
* *
* This function sets the scale factor to be applied to all the internal geometry. * This function sets the scale factor to be applied to all the internal geometry.
* The scale factor makes it possible to change the size of the road withou actually * The scale factor makes it possible to change the size of the road without actually
* modifying the internal geometry data. This functions automatically changes * modifying the internal geometry data. This functions automatically changes
* the scale factor of all underlying objects. * the scale factor of all underlying objects.
* *
...@@ -134,6 +133,30 @@ class COpendriveRoad ...@@ -134,6 +133,30 @@ class COpendriveRoad
* \return constant reference to the desired road segment object. * \return constant reference to the desired road segment object.
*/ */
const COpendriveRoadSegment& get_segment(unsigned int index) const; const COpendriveRoadSegment& get_segment(unsigned int index) const;
/**
* \brief Returns a road segment by id
*
* This function returns a constant reference to the desired road segment
* object, which can not be modified by the user. If the id is not valid,
* this function will throw an exception.
*
* \param id is the Opendrive numeric id of the road segment.
*
* \return constant reference to the desired road segment object.
*/
const COpendriveRoadSegment &get_segment_by_id(unsigned int id) const;
/**
* \brief Returns a road segment by name
*
* This function returns a constant reference to the desired road segment
* object, which can not be modified by the user. If the name is not valid,
* this function will throw an exception.
*
* \param name is the Opendrive name of the road segment.
*
* \return constant reference to the desired road segment object.
*/
const COpendriveRoadSegment &get_segment_by_name(std::string &name) const;
/** /**
* \brief Returns the number of lane objects in the whole road * \brief Returns the number of lane objects in the whole road
* *
...@@ -187,24 +210,220 @@ class COpendriveRoad ...@@ -187,24 +210,220 @@ class COpendriveRoad
* \return constant reference to the desired road segment object. * \return constant reference to the desired road segment object.
*/ */
const COpendriveRoadSegment &operator[](std::size_t index); const COpendriveRoadSegment &operator[](std::size_t index);
/** /**
* \brief gets the closest node to a given point * \brief returns the closest node to a given pose
*
* This functions finds the closest road node belonging to the whole road to a
* given pose, and returns it.
* *
* This functions searches all the road nodes for the one which is closest to * \param world given pose to find the closest road node.
* a given position and returns it. The distance from the closest node to the * \param distance the node distance between the projection of the given pose to
* the lane link geometry of the closest road node, and the start
* position of the node, following the corresponding lane link geometry.
* \param angle_tol maximum heading difference between the given pose and the closest pose
* on the lane link geometry of the closest road node.
*
* \return a constant reference to the closest node which can not be modified by the
* user.
*/ */
const COpendriveRoadNode &get_closest_node(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const; const COpendriveRoadNode &get_closest_node(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const;
/**
* \brief returns the index of the closest node to a given pose
*
* This functions finds the closest road node belonging to the whole road to a given
* pose, and returns its index.
*
* \param world given pose to find the closest road node.
* \param distance the node distance between the projection of the given pose to
* the lane link geometry of the closest road node, and the start
* position of the node, following the corresponding lane link geometry.
* \param angle_tol maximum heading difference between the given pose and the closest pose
* on the lane link geometry of the closest road node.
*
* \return the index of the closest road node.
*/
unsigned int get_closest_node_index(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const; unsigned int get_closest_node_index(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const;
/**
* \brief returns the closest lane to a given pose
*
* This functions finds the closest lane belonging to the whole road to a
* given pose, and returns it.
*
* \param world given pose to find the closest lane.
* \param distance the lane distance between the projection of the given pose to
* the lane geometry, and the start position of the lane, following
* its geometry.
* \param angle_tol maximum heading difference between the given pose and the closest pose
* on the lane geometry.
*
* \return a constant reference to the closest lane which can not be modified by the
* user.
*/
const COpendriveLane &get_closest_lane(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const; const COpendriveLane &get_closest_lane(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const;
/**
* \brief returns the index of the closest lane to a given pose
*
* This functions finds the closest lane belonging to the whole road to a given
* pose, and returns its index.
*
* \param world given pose to find the closest lane.
* \param distance the lane distance between the projection of the given pose to
* the lane geometry, and the start position of the lane, following
* its geometry.
* \param angle_tol maximum heading difference between the given pose and the closest pose
* on the lane geometry.
*
* \return the index of the closest lane.
*/
unsigned int get_closest_lane_index(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const; unsigned int get_closest_lane_index(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const;
/**
* \brief returns the closest road segment to a given pose
*
* This functions finds the closest road segment belonging to the whole road to a
* given pose, and returns it. The geometry used to find the closest road segment is the
* one that describes the center lane of the segment, not the lane/link geometries.
*
* \param world given pose to find the closest road segment.
* \param distance the segment distance between the projection of the given pose to
* the road segment geometry, and the start position of the segment, following
* its geometry.
* \param angle_tol maximum heading difference between the given pose and the closest pose
* on the road segment geometry.
*
* \return a constant reference to the closest road segment which can not be modified by the
* user.
*/
const COpendriveRoadSegment &get_closest_segment(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const; const COpendriveRoadSegment &get_closest_segment(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const;
/**
* \brief returns the index of the closest road segment to a given pose
*
* This functions finds the closest road segment belonging to the whole road to a given
* pose, and returns its index. The geometry used to find the closest road segment is the
* one that describes the center lane of the segment, not the lane/link geometries.
*
* \param world given pose to find the closest road segment.
* \param distance the segment distance between the projection of the given pose to
* the road segment geometry, and the start position of the segment, following
* its geometry.
* \param angle_tol maximum heading difference between the given pose and the closest pose
* on the road segment geometry.
*
* \return the index of the closest road segment.
*/
unsigned int get_closest_segment_index(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const; unsigned int get_closest_segment_index(TOpendriveWorldPose &pose,double &distance,double angle_tol=0.1) const;
/**
* \brief returns the closest pose
*
* This functions finds the closest pose (minimum distance) to the whole road
* to a given pose.
*
* \param world given pose to find the closest pose.
* \param closest_pose the closest pose to the closest to any road geometry.
* \param angle_tol maximum heading difference between the given pose and the closest pose
* on any road geometry.
*
* \return the link distance between the projection of the given pose to the
* closest road geometry, following its geometry.
*/
double get_closest_pose(TOpendriveWorldPose &pose,TOpendriveWorldPose &closest_pose,double angle_tol=0.1) const; double get_closest_pose(TOpendriveWorldPose &pose,TOpendriveWorldPose &closest_pose,double angle_tol=0.1) const;
void get_closest_poses(TOpendriveWorldPose &pose,std::vector<TOpendriveWorldPose> &closest_poses,std::vector<double> &closest_lengths,double dist_tol,double angle_tol=0.1) const; /**
std::vector<unsigned int> get_sub_road(std::vector<unsigned int> &path_nodes,TOpendriveWorldPose &start_pose,TOpendriveWorldPose &end_pose,COpendriveRoad &new_road); * \brief Returns a set of poses on the whole road close to a given pose
*
* This function is similar to the get_closest_pose(), but in this case, the closest
* pose of any road geometry which is closer to the given pose that a given distance will be
* returned.
*
* \param world given pose to find the closest poses.
* \param closest_poses the closest poses on any road geometry.
* \param distances the link distance between the projection of the given pose to each
* of the closest road geometries, following the corresponding geometry.
* \param dist_tol maximum allowed distance from the given position to any road geometry.
* \param angle_tol maximum heading difference between the given pose and the closest pose
* on any road geometry.
*/
void get_closest_poses(TOpendriveWorldPose &pose,std::vector<TOpendriveWorldPose> &closest_poses,std::vector<double> &distances,double dist_tol,double angle_tol=0.1) const;
/**
* \brief creates a sub-road with only the road elements of a given path
*
* This functions creates a new sub road with only the whole road segments that
* include the road nodes of the given path. These new road segments will only have
* the lanes and the road nodes on the same side as the given path.
*
* The road elements of the new road keep the required original information and connectivity
* but are completely independent from the original ones. The only information that
* changes in the new sub-road is:
*
* * the remaining road segments, lanes and road nodes are re-indexed, so that their
* unique index is coherent with the new data structure.
* * for any open road segment (that is, a road segment that is not connected), new road
* nodes are placed at the end of the open road segment to keep its lane and link
* geometric information.
*
* If the given path has non-consecutive road nodes, this function will fail throwing an
* exception.
*
* \param path_nodes sequence of road nodes describing the path. The road nodes are
* identified by their unique index.
* \param end_pose end pose of the path. When final road node has multiple road segment
* parents, the end pose indicates which one of them must be included
* in the new road.
* \param new_road The new sub-road object.
*
* \return the sequence of road nodes describing the path in the new sub-road.
*/
std::vector<unsigned int> get_sub_road(std::vector<unsigned int> &path_nodes,TOpendriveWorldPose &end_pose,COpendriveRoad &new_road);
/**
* \brief creates a sub-road with only the road elements within a distance to a given pose
*
* This functions creates a new sub road stating a given distance (margin) from the start
* pose and reaching up to a given distance following the traffic direction of the start
* pose. The new road segments will keep all the original lanes and road nodes.
*
* The distance is measured following the road segment geometries, not the euclidean
* distance. The new road may be shorter than expected if the original road is not long
* enough.
*
* The road elements of the new road keep the required original information and connectivity
* but are completely independent from the original ones. The only information that
* changes in the new sub-road is:
*
* * the remaining road segments, lanes and road nodes are re-indexed, so that their
* unique index is coherent with the new data structure.
* * for any open road segment (that is, a road segment that is not connected), new road
* nodes are placed at the end of the open road segment to keep its lane and link
* geometric information.
*
* If the part of the road of interest has multiple paths, this function will fail throwing an
* exception.
*
* \param start_pose start pose of the new road. This pose implicitly defines the side
* of the road taken to generate the sub-road.
* \param length this is the desired length of the new road in meters. On success, this
* parameter will be updated with the actual length of the new road.
* \param margin a distance to be added at the beginning and the end of the new road, if
* possible. This makes the actual length of the new road equal to length+
* 2.0*margin.
* \param new_road The new sub-road object.
*
*/
void get_sub_road(TOpendriveWorldPose &start_pose,double &length,double margin,COpendriveRoad &new_road); void get_sub_road(TOpendriveWorldPose &start_pose,double &length,double margin,COpendriveRoad &new_road);
/**
* \brief creates a full copy of the road
*/
void operator=(const COpendriveRoad& object); void operator=(const COpendriveRoad& object);
/**
* \brief overloaded stream operator
*
* This functions streams human readable information about the whole road. This information
* includes:
* * The resolution, scale_factor and minimum road length
* * The road segments information.
*
*/
friend std::ostream& operator<<(std::ostream& out, COpendriveRoad &road); friend std::ostream& operator<<(std::ostream& out, COpendriveRoad &road);
/**
* \brief Destructor
*/
~COpendriveRoad(); ~COpendriveRoad();
}; };
......
...@@ -49,20 +49,6 @@ COpendriveRoad::COpendriveRoad(const COpendriveRoad& object) ...@@ -49,20 +49,6 @@ COpendriveRoad::COpendriveRoad(const COpendriveRoad& object)
this->update_references(new_segment_ref,new_lane_ref,new_node_ref); this->update_references(new_segment_ref,new_lane_ref,new_node_ref);
} }
COpendriveRoadSegment *COpendriveRoad::get_segment_by_id(std::string &id)
{
std::stringstream error;
for(unsigned int i=0;i<this->segments.size();i++)
{
if(this->segments[i]->get_id()==(unsigned int)std::stoi(id))
return this->segments[i];
}
error << "No road segment with the " << id << " ID";
throw CException(_HERE_,error.str());
}
void COpendriveRoad::free(void) void COpendriveRoad::free(void)
{ {
for(unsigned int i=0;i<this->segments.size();i++) for(unsigned int i=0;i<this->segments.size();i++)
...@@ -95,7 +81,7 @@ void COpendriveRoad::link_segments(OpenDRIVE &open_drive) ...@@ -95,7 +81,7 @@ void COpendriveRoad::link_segments(OpenDRIVE &open_drive)
for(OpenDRIVE::road_iterator road_it(open_drive.road().begin());road_it!=open_drive.road().end();++road_it) for(OpenDRIVE::road_iterator road_it(open_drive.road().begin());road_it!=open_drive.road().end();++road_it)
{ {
// get current segment // get current segment
road=this->get_segment_by_id(road_it->id().get()); road=const_cast<COpendriveRoadSegment *>(&this->get_segment_by_id((unsigned int)std::stoi(road_it->id().get())));
// get predecessor and successor // get predecessor and successor
if(road_it->lane_link().present()) if(road_it->lane_link().present())
{ {
...@@ -120,13 +106,13 @@ void COpendriveRoad::link_segments(OpenDRIVE &open_drive) ...@@ -120,13 +106,13 @@ void COpendriveRoad::link_segments(OpenDRIVE &open_drive)
{ {
if(!predecessor_id.empty()) if(!predecessor_id.empty())
{ {
prev_road=this->get_segment_by_id(predecessor_id); prev_road=const_cast<COpendriveRoadSegment *>(&this->get_segment_by_id((unsigned int)std::stoi(predecessor_id)));
prev_road->link_segment(road); prev_road->link_segment(road);
predecessor_id.clear(); predecessor_id.clear();
} }
if(!successor_id.empty()) if(!successor_id.empty())
{ {
next_road=this->get_segment_by_id(successor_id); next_road=const_cast<COpendriveRoadSegment *>(&this->get_segment_by_id((unsigned int)std::stoi(successor_id)));
road->link_segment(next_road); road->link_segment(next_road);
successor_id.clear(); successor_id.clear();
} }
...@@ -155,8 +141,8 @@ void COpendriveRoad::link_segments(OpenDRIVE &open_drive) ...@@ -155,8 +141,8 @@ void COpendriveRoad::link_segments(OpenDRIVE &open_drive)
} }
if(predecessor_id.compare(incoming_road_id)==0 && successor_id.compare(connecting_road_id)==0)// this is the connection if(predecessor_id.compare(incoming_road_id)==0 && successor_id.compare(connecting_road_id)==0)// this is the connection
{ {
prev_road=this->get_segment_by_id(predecessor_id); prev_road=const_cast<COpendriveRoadSegment *>(&this->get_segment_by_id((unsigned int)std::stoi(predecessor_id)));
next_road=this->get_segment_by_id(successor_id); next_road=const_cast<COpendriveRoadSegment *>(&this->get_segment_by_id((unsigned int)std::stoi(successor_id)));
for(connection::laneLink_iterator lane_link_it(connection_it->laneLink().begin()); lane_link_it!=connection_it->laneLink().end();++lane_link_it) for(connection::laneLink_iterator lane_link_it(connection_it->laneLink().begin()); lane_link_it!=connection_it->laneLink().end();++lane_link_it)
{ {
int from_lane_id; int from_lane_id;
...@@ -620,6 +606,34 @@ const COpendriveRoadSegment& COpendriveRoad::get_segment(unsigned int index) con ...@@ -620,6 +606,34 @@ const COpendriveRoadSegment& COpendriveRoad::get_segment(unsigned int index) con
} }
} }
const COpendriveRoadSegment &COpendriveRoad::get_segment_by_id(unsigned int id) const
{
std::stringstream error;
for(unsigned int i=0;i<this->segments.size();i++)
{
if(this->segments[i]->get_id()==id)
return *this->segments[i];
}
error << "No road segment with the " << id << " ID";
throw CException(_HERE_,error.str());
}
const COpendriveRoadSegment &COpendriveRoad::get_segment_by_name(std::string &name) const
{
std::stringstream error;
for(unsigned int i=0;i<this->segments.size();i++)
{
if(this->segments[i]->get_name()==name)
return *this->segments[i];
}
error << "No road segment with the " << name << " name";
throw CException(_HERE_,error.str());
}
unsigned int COpendriveRoad::get_num_lanes(void) const unsigned int COpendriveRoad::get_num_lanes(void) const
{ {
return this->lanes.size(); return this->lanes.size();
...@@ -795,14 +809,14 @@ double COpendriveRoad::get_closest_pose(TOpendriveWorldPose &pose,TOpendriveWorl ...@@ -795,14 +809,14 @@ double COpendriveRoad::get_closest_pose(TOpendriveWorldPose &pose,TOpendriveWorl
return closest_length; return closest_length;
} }
void COpendriveRoad::get_closest_poses(TOpendriveWorldPose &pose,std::vector<TOpendriveWorldPose> &closest_poses,std::vector<double> &closest_lengths,double dist_tol,double angle_tol) const void COpendriveRoad::get_closest_poses(TOpendriveWorldPose &pose,std::vector<TOpendriveWorldPose> &closest_poses,std::vector<double> &distances,double dist_tol,double angle_tol) const
{ {
std::vector<TOpendriveWorldPose> poses; std::vector<TOpendriveWorldPose> poses;
std::vector<double> lengths; std::vector<double> lengths;
bool already_added; bool already_added;
closest_poses.clear(); closest_poses.clear();
closest_lengths.clear(); distances.clear();
for(unsigned int i=0;i<this->nodes.size();i++) for(unsigned int i=0;i<this->nodes.size();i++)
{ {
this->nodes[i]->get_closest_poses(pose,poses,lengths,dist_tol,false,angle_tol); this->nodes[i]->get_closest_poses(pose,poses,lengths,dist_tol,false,angle_tol);
...@@ -819,13 +833,13 @@ void COpendriveRoad::get_closest_poses(TOpendriveWorldPose &pose,std::vector<TOp ...@@ -819,13 +833,13 @@ void COpendriveRoad::get_closest_poses(TOpendriveWorldPose &pose,std::vector<TOp
if(!already_added) if(!already_added)
{ {
closest_poses.push_back(poses[j]); closest_poses.push_back(poses[j]);
closest_lengths.push_back(lengths[j]); distances.push_back(lengths[j]);
} }
} }
} }
} }
std::vector<unsigned int> COpendriveRoad::get_sub_road(std::vector<unsigned int> &path_nodes,TOpendriveWorldPose &start_pose,TOpendriveWorldPose &end_pose,COpendriveRoad &new_road) std::vector<unsigned int> COpendriveRoad::get_sub_road(std::vector<unsigned int> &path_nodes,TOpendriveWorldPose &end_pose,COpendriveRoad &new_road)
{ {
segment_up_ref_t new_segment_ref; segment_up_ref_t new_segment_ref;
lane_up_ref_t new_lane_ref; lane_up_ref_t new_lane_ref;
...@@ -914,13 +928,14 @@ void COpendriveRoad::get_sub_road(TOpendriveWorldPose &start_pose,double &length ...@@ -914,13 +928,14 @@ void COpendriveRoad::get_sub_road(TOpendriveWorldPose &start_pose,double &length
lane_up_ref_t new_lane_ref; lane_up_ref_t new_lane_ref;
node_up_ref_t new_node_ref; node_up_ref_t new_node_ref;
link_up_ref_t new_link_ref; link_up_ref_t new_link_ref;
std::vector<const COpendriveRoadSegment *> cand_segments;
std::vector<int> cand_sides;
unsigned int segment_index; unsigned int segment_index;
TOpendriveWorldPose end_pose,int_pose; TOpendriveWorldPose end_pose,int_pose;
const COpendriveRoadSegment *segment,*next_segment; const COpendriveRoadSegment *segment;
COpendriveRoadSegment *new_segment; COpendriveRoadSegment *new_segment;
double rem_length=length+2.0*margin,distance,start_length; double rem_length=length+2.0*margin,distance,start_length;
int node_side; int node_side;
bool valid;
new_road.free(); new_road.free();
new_road.set_resolution(this->resolution); new_road.set_resolution(this->resolution);
...@@ -939,10 +954,18 @@ void COpendriveRoad::get_sub_road(TOpendriveWorldPose &start_pose,double &length ...@@ -939,10 +954,18 @@ void COpendriveRoad::get_sub_road(TOpendriveWorldPose &start_pose,double &length
rem_length=distance-margin; rem_length=distance-margin;
if(rem_length<0.0)// get the previous segment if(rem_length<0.0)// get the previous segment
{ {
next_segment=&segment->get_prev_segment(node_side,valid); cand_segments=segment->get_prev_segments(node_side,cand_sides);
if(valid) if(cand_segments.size()>1)
throw CException(_HERE_,"Road has multiple path, impossible to generate new road");
if(cand_segments.size()==0)