diff --git a/include/opendrive_lane.h b/include/opendrive_lane.h index 1a615d4c9b8a03327a848223ed1e431138210287..988dc2338c62e28bbdd180480eb5f38f78396ca4 100644 --- a/include/opendrive_lane.h +++ b/include/opendrive_lane.h @@ -54,8 +54,8 @@ class COpendriveLane void update_references(segment_up_ref_t &segment_refs,lane_up_ref_t &lane_refs,node_up_ref_t &node_refs); void clean_references(segment_up_ref_t &segment_refs,lane_up_ref_t &lane_refs,node_up_ref_t &node_refs); void update_start_node(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,TOpendriveWorldPoint *start=NULL); - COpendriveRoadNode *update_end_node(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,TOpendriveWorldPoint *end=NULL); - COpendriveLane *get_sub_lane(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,COpendriveRoadNode **new_node,TOpendriveWorldPoint *start=NULL,TOpendriveWorldPoint *end=NULL); + void update_end_node(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,TOpendriveWorldPoint *end=NULL); + COpendriveLane *get_sub_lane(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,TOpendriveWorldPoint *start=NULL,TOpendriveWorldPoint *end=NULL); COpendriveLane *clone(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref); public: unsigned int get_num_nodes(void) const; diff --git a/include/opendrive_road.h b/include/opendrive_road.h index 43d76f2a817d9a9eb3215f4fbe319d1c384fba6e..a00e0a9398528984ca5de063302612355b9cba91 100644 --- a/include/opendrive_road.h +++ b/include/opendrive_road.h @@ -30,6 +30,7 @@ class COpendriveRoad void remove_node(COpendriveRoadNode *node); unsigned int add_lane(COpendriveLane *lane); void remove_lane(COpendriveLane *lane); + void complete_open_lanes(void); void add_segment(COpendriveRoadSegment *segment,std::vector<unsigned int> &old_path,std::vector<unsigned int> &new_path); void update_references(segment_up_ref_t &segment_refs,lane_up_ref_t &lane_refs,node_up_ref_t &node_refs); void clean_references(segment_up_ref_t &segment_refs,lane_up_ref_t &lane_refs,node_up_ref_t &node_refs); @@ -54,7 +55,7 @@ class COpendriveRoad unsigned int get_closest_node(TOpendriveWorldPoint &point,double angle_tol=0.1); double get_closest_point(TOpendriveWorldPoint &point,TOpendriveWorldPoint &closest_point,double angle_tol=0.1); void get_closest_points(TOpendriveWorldPoint &point,std::vector<TOpendriveWorldPoint> &closest_points,std::vector<double> &closest_lengths,double dist_tol,double angle_tol=0.1); - void get_sub_road(std::vector<unsigned int> &path_nodes,TOpendriveWorldPoint &start_point,TOpendriveWorldPoint &end_point,COpendriveRoad &new_road); + std::vector<unsigned int> get_sub_road(std::vector<unsigned int> &path_nodes,TOpendriveWorldPoint &start_point,TOpendriveWorldPoint &end_point,COpendriveRoad &new_road); void get_sub_road(TOpendriveWorldPoint &start_point,double length,COpendriveRoad &new_road); void operator=(const COpendriveRoad& object); friend std::ostream& operator<<(std::ostream& out, COpendriveRoad &road); diff --git a/include/opendrive_road_node.h b/include/opendrive_road_node.h index f660aeb58d4b02f58842c01a44dfec150cec1c45..6e919e2b163f7a8c93def8a4477bd3c5bc3c37e8 100644 --- a/include/opendrive_road_node.h +++ b/include/opendrive_road_node.h @@ -39,7 +39,7 @@ class COpendriveRoadNode void update_references(segment_up_ref_t &segment_refs,lane_up_ref_t &lane_refs,node_up_ref_t &node_refs); void clean_references(segment_up_ref_t &segment_refs,lane_up_ref_t &lane_refs,node_up_ref_t &node_refs); void update_start_pose(COpendriveLane *lane,TOpendriveWorldPoint *start=NULL); - COpendriveRoadNode *update_end_pose(COpendriveLane *lane,TOpendriveWorldPoint *end=NULL); + void update_end_pose(COpendriveLane *lane,TOpendriveWorldPoint *end=NULL); COpendriveLink *get_link_with(COpendriveRoadNode *end); public: double get_resolution(void) const; @@ -56,6 +56,7 @@ class COpendriveRoadNode unsigned int get_num_geometries(void) const; const COpendriveGeometry &get_geometry(unsigned int index) const; unsigned int get_closest_link(TOpendriveWorldPoint &point,double angle_tol=0.1) const; + double get_closest_distance(TOpendriveWorldPoint &point,double angle_tol=0.1) const; double get_closest_point(TOpendriveWorldPoint &point,TOpendriveWorldPoint &closest_point,double angle_tol=0.1) const; void get_closest_points(TOpendriveWorldPoint &point,std::vector<TOpendriveWorldPoint> &closest_points,std::vector<double> &closest_lengths,double dist_tol,double angle_tol=0.1) const; friend std::ostream& operator<<(std::ostream& out, COpendriveRoadNode &node); diff --git a/src/opendrive_lane.cpp b/src/opendrive_lane.cpp index a523f0b26176c523d690065be6f4d6bd13ac0243..802b9df51321eb10b0ba6874354c32a47fc97d87 100644 --- a/src/opendrive_lane.cpp +++ b/src/opendrive_lane.cpp @@ -129,7 +129,6 @@ void COpendriveLane::link_lane(COpendriveLane *lane,opendrive_mark_t mark,bool f } start->add_link(end,mark,this->segment,this); // link lane - // link laness this->add_next_lane(lane); lane->add_prev_lane(this); } @@ -374,7 +373,7 @@ void COpendriveLane::update_start_node(node_up_ref_t &new_node_ref,lane_up_ref_t this->nodes[0]->update_start_pose(this,start); } -COpendriveRoadNode *COpendriveLane::update_end_node(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,TOpendriveWorldPoint *end) +void COpendriveLane::update_end_node(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,TOpendriveWorldPoint *end) { std::vector<COpendriveRoadNode *>::iterator it; segment_up_ref_t new_segment_ref; @@ -384,7 +383,7 @@ COpendriveRoadNode *COpendriveLane::update_end_node(node_up_ref_t &new_node_ref, bool exists; if(end==NULL) - return NULL; + return; end_node_index=this->get_closest_node(*end,3.14159); // eliminate all the node before the start one for(it=this->nodes.begin(),i=0;it!=this->nodes.end();i++) @@ -411,18 +410,10 @@ COpendriveRoadNode *COpendriveLane::update_end_node(node_up_ref_t &new_node_ref, } this->next.clear();// it is no longer connected to any next lane this->update_references(new_segment_ref,new_lane_ref,new_node_ref); - new_node=this->nodes[this->nodes.size()-1]->update_end_pose(this,end); - if(new_node!=NULL) - { - this->add_node(new_node); - new_node_ref[new_node]=new_node; - this->update_references(new_segment_ref,new_lane_ref,new_node_ref); - } - - return new_node; + this->nodes[this->nodes.size()-1]->update_end_pose(this,end); } -COpendriveLane *COpendriveLane::get_sub_lane(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,COpendriveRoadNode **new_node,TOpendriveWorldPoint *start,TOpendriveWorldPoint *end) +COpendriveLane *COpendriveLane::get_sub_lane(node_up_ref_t &new_node_ref,lane_up_ref_t &new_lane_ref,TOpendriveWorldPoint *start,TOpendriveWorldPoint *end) { COpendriveLane *new_lane; @@ -433,12 +424,12 @@ COpendriveLane *COpendriveLane::get_sub_lane(node_up_ref_t &new_node_ref,lane_up if(this->id<0) { new_lane->update_start_node(new_node_ref,new_lane_ref,start); - (*new_node)=new_lane->update_end_node(new_node_ref,new_lane_ref,end); + new_lane->update_end_node(new_node_ref,new_lane_ref,end); } else { new_lane->update_start_node(new_node_ref,new_lane_ref,end); - (*new_node)=new_lane->update_end_node(new_node_ref,new_lane_ref,start); + new_lane->update_end_node(new_node_ref,new_lane_ref,start); } return new_lane; diff --git a/src/opendrive_road.cpp b/src/opendrive_road.cpp index 53ad80e6d35bf8435efe0b07e8e4ff3342fc32c8..7fcf98c6fa8aa893aedd37c884a1504423a8c0d8 100644 --- a/src/opendrive_road.cpp +++ b/src/opendrive_road.cpp @@ -240,6 +240,41 @@ void COpendriveRoad::remove_lane(COpendriveLane *lane) } } +void COpendriveRoad::complete_open_lanes(void) +{ + std::vector<COpendriveLane *>::iterator lane_it; + COpendriveRoadNode *new_node; + TOpendriveWorldPoint end_point; + unsigned int new_node_index; + + // remove all nodes and lanes not present in the path + for(lane_it=this->lanes.begin();lane_it!=this->lanes.end();) + { + if((*lane_it)->next.empty())// lane is not connected + { + if((*lane_it)->get_id()<0) + end_point=(*lane_it)->get_end_point(); + else + end_point=(*lane_it)->get_start_point(); + if(!this->node_exists_at(end_point))// there is no node at the end point + { + new_node=new COpendriveRoadNode(); + new_node->set_resolution(this->resolution); + new_node->set_scale_factor(this->scale_factor); + new_node->set_start_point(end_point); + new_node_index=this->add_node(new_node); + new_node->set_index(new_node_index); + (*lane_it)->add_node(new_node); + (*lane_it)->segment->add_node(new_node); + } + else + lane_it++; + } + else + lane_it++; + } +} + void COpendriveRoad::add_segment(COpendriveRoadSegment *segment,std::vector<unsigned int> &old_path,std::vector<unsigned int> &new_path) { for(unsigned int i=0;i<this->segments.size();i++) @@ -263,7 +298,7 @@ void COpendriveRoad::add_segment(COpendriveRoadSegment *segment,std::vector<unsi { for(unsigned int j=0;j<old_path.size();j++) if(old_path[j]==segment->nodes[i]->index) - new_path.push_back(this->nodes.size()); + new_path[j]=this->nodes.size(); segment->nodes[i]->set_index(this->nodes.size()); this->nodes.push_back(segment->nodes[i]); } @@ -405,6 +440,16 @@ void COpendriveRoad::prune(std::vector<unsigned int> &path_nodes) else lane_it++; } + // re-index all nodes and the path + for(unsigned int i=0;i<this->nodes.size();i++) + { + for(unsigned int j=0;j<path_nodes.size();j++) + { + if(this->nodes[i]->get_index()==path_nodes[j]) + path_nodes[j]=i; + } + this->nodes[i]->set_index(i); + } // remove links to non-consecutive nodes for(unsigned int i=0;i<this->nodes.size();i++) @@ -627,17 +672,19 @@ void COpendriveRoad::get_closest_points(TOpendriveWorldPoint &point,std::vector< } } -void COpendriveRoad::get_sub_road(std::vector<unsigned int> &path_nodes,TOpendriveWorldPoint &start_point,TOpendriveWorldPoint &end_point,COpendriveRoad &new_road) +std::vector<unsigned int> COpendriveRoad::get_sub_road(std::vector<unsigned int> &path_nodes,TOpendriveWorldPoint &start_point,TOpendriveWorldPoint &end_point,COpendriveRoad &new_road) { segment_up_ref_t new_segment_ref; lane_up_ref_t new_lane_ref; node_up_ref_t new_node_ref; - COpendriveRoadNode *node,*next_node; - COpendriveRoadSegment *segment,*new_segment; + COpendriveRoadNode *node,*next_node,*repeat_node,*repeat_next_node; + COpendriveRoadSegment *segment,*new_segment,*repeat_segment; std::vector<unsigned int> new_path_nodes; unsigned int link_index; + bool added,repeated; int node_side; - bool added; + + new_path_nodes.resize(path_nodes.size()); new_road.free(); new_road.set_resolution(this->resolution); @@ -668,7 +715,30 @@ void COpendriveRoad::get_sub_road(std::vector<unsigned int> &path_nodes,TOpendri if(i==0) { node_side=segment->get_node_side(node); - new_segment=segment->get_sub_segment(new_node_ref,new_lane_ref,node_side,&start_point,NULL); + repeated=false; + for(unsigned int j=1;j<path_nodes.size();j++) + { + repeat_node=this->nodes[path_nodes[j]]; + if(j==path_nodes.size()-1) + { + link_index=node->get_closest_link(end_point,3.14159); + repeat_segment=node->links[link_index]->segment; + } + else + { + repeat_next_node=this->nodes[path_nodes[j+1]]; + repeat_segment=repeat_node->get_link_with(repeat_next_node)->segment; + } + if(segment==repeat_segment) + { + repeated=true; + break; + } + } + if(repeated) + new_segment=segment->clone(new_node_ref,new_lane_ref); + else + new_segment=segment->get_sub_segment(new_node_ref,new_lane_ref,node_side,&start_point,NULL); } else new_segment=segment->clone(new_node_ref,new_lane_ref); @@ -680,10 +750,25 @@ void COpendriveRoad::get_sub_road(std::vector<unsigned int> &path_nodes,TOpendri node=this->nodes[path_nodes[path_nodes.size()-1]]; link_index=node->get_closest_link(end_point,3.14159); segment=node->links[link_index]->segment; - node_side=segment->get_node_side(node); - new_segment=segment->get_sub_segment(new_node_ref,new_lane_ref,node_side,NULL,&end_point); - new_road.add_segment(new_segment,path_nodes,new_path_nodes); - new_segment_ref[segment]=new_segment; + repeated=false; + for(unsigned int j=0;j<path_nodes.size()-1;j++) + { + repeat_node=this->nodes[path_nodes[j]]; + repeat_next_node=this->nodes[path_nodes[j+1]]; + repeat_segment=repeat_node->get_link_with(repeat_next_node)->segment; + if(segment==repeat_segment) + { + repeated=true; + break; + } + } + if(!repeated) + { + node_side=segment->get_node_side(node); + new_segment=segment->get_sub_segment(new_node_ref,new_lane_ref,node_side,NULL,&end_point); + new_road.add_segment(new_segment,path_nodes,new_path_nodes); + new_segment_ref[segment]=new_segment; + } } new_road.update_references(new_segment_ref,new_lane_ref,new_node_ref); // add additional nodes not explicitly in the path @@ -712,6 +797,9 @@ void COpendriveRoad::get_sub_road(std::vector<unsigned int> &path_nodes,TOpendri // remove unconnected elements new_road.prune(new_path_nodes); new_road.clean_references(new_segment_ref,new_lane_ref,new_node_ref); + new_road.complete_open_lanes(); + + return new_path_nodes; } void COpendriveRoad::get_sub_road(TOpendriveWorldPoint &start_point,double length,COpendriveRoad &road) diff --git a/src/opendrive_road_node.cpp b/src/opendrive_road_node.cpp index edbf921b0cf7d7ceae650e7aa2e84774bc4c6a94..f6a3e74db47bd57a85205dc05bde248c674b1e5c 100644 --- a/src/opendrive_road_node.cpp +++ b/src/opendrive_road_node.cpp @@ -354,17 +354,16 @@ void COpendriveRoadNode::update_start_pose(COpendriveLane *lane,TOpendriveWorldP } } -COpendriveRoadNode *COpendriveRoadNode::update_end_pose(COpendriveLane *lane,TOpendriveWorldPoint *end) +void COpendriveRoadNode::update_end_pose(COpendriveLane *lane,TOpendriveWorldPoint *end) { std::vector<COpendriveLane *>::iterator lane_it; std::vector<COpendriveLink *>::iterator link_it; - COpendriveRoadNode *new_node=NULL; TOpendriveWorldPoint end_point; unsigned int i; double length; if(end==NULL) - return NULL; + return; // remove the references to all lanes and segments except for lane for(i=0,lane_it=this->lanes.begin();lane_it!=this->lanes.end();i++) { @@ -382,34 +381,19 @@ COpendriveRoadNode *COpendriveRoadNode::update_end_pose(COpendriveLane *lane,TOp for(unsigned int i=0;i<this->geometries.size();i++) this->geometries[i]->max_s=length*this->scale_factor; // update the links - for(i=0,link_it=this->links.begin();link_it!=this->links.end();i++) + for(link_it=this->links.begin();link_it!=this->links.end();) { if((*link_it)->prev==this) { - if((*link_it)->lane==lane) - { - // create a dummy node - new_node=new COpendriveRoadNode(); - new_node->set_resolution(this->resolution); - new_node->set_scale_factor(this->scale_factor); - new_node->set_start_point(end_point); - (*link_it)->set_next(new_node); - new_node->add_link(*link_it); - // update the end position of the link - (*link_it)->update_end_pose(end); - link_it++; - } - else - { - delete *link_it; - link_it=this->links.erase(link_it); - } + delete *link_it; + link_it=this->links.erase(link_it); } else + { + (*link_it)->update_end_pose(end); link_it++; + } } - - return new_node; } COpendriveLink *COpendriveRoadNode::get_link_with(COpendriveRoadNode *end) @@ -534,6 +518,30 @@ unsigned int COpendriveRoadNode::get_closest_link(TOpendriveWorldPoint &point,do return closest_index; } +double COpendriveRoadNode::get_closest_distance(TOpendriveWorldPoint &point,double angle_tol)const +{ + double dist,min_dist=std::numeric_limits<double>::max(); + double angle; + TPoint spline_point; + + for(unsigned int i=0;i<this->links.size();i++) + { + if(&this->links[i]->get_prev()==this)// links starting at this node + { + this->links[i]->find_closest_world_point(point,spline_point); + angle=diff_angle(normalize_angle(point.heading),spline_point.heading); + if(fabs(angle)<angle_tol) + { + dist=sqrt(pow(spline_point.x-point.x,2.0)+pow(spline_point.y-point.y,2.0)); + if(dist<min_dist) + min_dist=dist; + } + } + } + + return min_dist; +} + double COpendriveRoadNode::get_closest_point(TOpendriveWorldPoint &point,TOpendriveWorldPoint &closest_point,double angle_tol) const { double dist,min_dist=std::numeric_limits<double>::max(); diff --git a/src/opendrive_road_segment.cpp b/src/opendrive_road_segment.cpp index 3d9e57297333924d16015f0910d6ed6211e7e920..b33f8bd2093658b1d75a32ba5c5095feb86ab49b 100644 --- a/src/opendrive_road_segment.cpp +++ b/src/opendrive_road_segment.cpp @@ -603,7 +603,6 @@ COpendriveRoadSegment *COpendriveRoadSegment::get_sub_segment(node_up_ref_t &new COpendriveRoadSegment *new_segment; std::vector<COpendriveRoadNode *>::iterator node_it; node_up_ref_t::iterator node_ref_it; - COpendriveRoadNode *new_node; if(start==NULL && end==NULL) return this->clone(new_node_ref,new_lane_ref); @@ -613,12 +612,10 @@ COpendriveRoadSegment *COpendriveRoadSegment::get_sub_segment(node_up_ref_t &new for(lane_it=new_segment->lanes.begin();lane_it!=new_segment->lanes.end();lane_it++) { if(node_side<0) - new_lane=lane_it->second->get_sub_lane(new_node_ref,new_lane_ref,&new_node,start,end); + new_lane=lane_it->second->get_sub_lane(new_node_ref,new_lane_ref,start,end); else - new_lane=lane_it->second->get_sub_lane(new_node_ref,new_lane_ref,&new_node,end,start); + new_lane=lane_it->second->get_sub_lane(new_node_ref,new_lane_ref,end,start); new_lane_ref[lane_it->second]=new_lane; - if(new_node!=NULL) - new_segment->add_node(new_node); } new_segment->update_references(new_segment_ref,new_lane_ref,new_node_ref); // update signals and objects