diff --git a/include/opendrive_road_node.h b/include/opendrive_road_node.h index 49fa7a6742a5a9b98fde459b146d9da3a817b1e7..c5625b06fb8c79f91eed62c1bb234183d622d70a 100644 --- a/include/opendrive_road_node.h +++ b/include/opendrive_road_node.h @@ -13,7 +13,6 @@ typedef struct COpendriveRoadSegment *segment; double start_curvature; double end_curvature; - double length; }TOpendriveRoadNodeParent; class COpendriveRoadNode @@ -31,7 +30,7 @@ class COpendriveRoadNode unsigned int index; protected: COpendriveRoadNode(); - COpendriveRoadNode(const COpendriveRoadNode &object); + COpendriveRoadNode *clone(link_up_ref_t &new_link_ref); void free(void); bool add_link(COpendriveRoadNode *node,opendrive_mark_t mark,COpendriveRoadSegment *segment,COpendriveLane *lane); void add_link(COpendriveLink *link); @@ -43,15 +42,15 @@ class COpendriveRoadNode void set_scale_factor(double scale); void set_index(unsigned int index); void set_pose(TOpendriveWorldPose &start); - void add_parent(COpendriveLane *lane,COpendriveRoadSegment *segment,double length,double start_curvature,double end_curvature); + void add_parent(COpendriveLane *lane,COpendriveRoadSegment *segment,double start_curvature,double end_curvature); TOpendriveRoadNodeParent *get_parent_with_lane(const COpendriveLane *lane); TOpendriveRoadNodeParent *get_parent_with_segment(const COpendriveRoadSegment *segment); bool updated(node_up_ref_t &refs); COpendriveRoadNode *get_original_node(node_up_ref_t &node_refs); 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,TOpendriveWorldPose *start=NULL); - void update_end_pose(COpendriveLane *lane,TOpendriveWorldPose *end=NULL); + void update_start_pose(COpendriveLane *lane,TOpendriveWorldPose &start,double distance); + void update_end_pose(COpendriveLane *lane,TOpendriveWorldPose &end,double distance); public: double get_resolution(void) const; double get_scale_factor(void) const; @@ -64,9 +63,9 @@ class COpendriveRoadNode const COpendriveLink &get_link(unsigned int index) const; const COpendriveLink &get_link_ending_at(unsigned int node_index) const; unsigned int get_closest_link(TOpendriveWorldPose &pose,double angle_tol=0.1) const; - double get_closest_distance(TOpendriveWorldPose &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; + double get_closest_distance(TOpendriveWorldPose &pose,bool only_lanes=false,double angle_tol=0.1) const; + double get_closest_pose(TOpendriveWorldPose &pose,TOpendriveWorldPose &closest_pose,bool only_lanes=false,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,bool only_lanes,double angle_tol=0.1) const; friend std::ostream& operator<<(std::ostream& out, COpendriveRoadNode &node); ~COpendriveRoadNode(); }; diff --git a/src/opendrive_road_node.cpp b/src/opendrive_road_node.cpp index f9a990f36d7198f643daae266a22adf02489bb81..ee7d6dfaa6384c43acdfe4a013feb2119fb08c75 100644 --- a/src/opendrive_road_node.cpp +++ b/src/opendrive_road_node.cpp @@ -15,29 +15,37 @@ COpendriveRoadNode::COpendriveRoadNode() this->index=-1; } -COpendriveRoadNode::COpendriveRoadNode(const COpendriveRoadNode &object) +COpendriveRoadNode *COpendriveRoadNode::clone(link_up_ref_t &new_link_ref) { - COpendriveLink *new_link; + COpendriveRoadNode *new_node; - this->resolution=object.resolution; - this->scale_factor=object.scale_factor; - this->pose=object.pose; - this->parents=object.parents; - this->links.clear(); - for(unsigned int i=0;i<object.links.size();i++) + new_node=new COpendriveRoadNode(); + new_node->resolution=this->resolution; + new_node->scale_factor=this->scale_factor; + new_node->pose=this->pose; + new_node->parents=this->parents; + new_node->links.resize(this->links.size()); + for(unsigned int i=0;i<this->links.size();i++) { - new_link=new COpendriveLink(*object.links[i]); - this->links.push_back(new_link); + if(new_link_ref.find(this->links[i])!=new_link_ref.end()) + new_node->links[i]=new_link_ref[this->links[i]]; + else + { + new_node->links[i]=new COpendriveLink(*this->links[i]); + new_link_ref[this->links[i]]=new_node->links[i]; + } } - this->index=object.index; + new_node->index=this->index; + + return new_node; } bool COpendriveRoadNode::add_link(COpendriveRoadNode *node,opendrive_mark_t mark,COpendriveRoadSegment *segment,COpendriveLane *lane) { + TOpendriveRoadNodeParent *parent; TOpendriveWorldPose node_pose; - double start_curvature,end_curvature,length; + double start_curvature,end_curvature; COpendriveLink *new_link; - bool lane_found=false; if(this->has_link_with(node) || node->has_link_with(this)) return false; @@ -51,24 +59,26 @@ bool COpendriveRoadNode::add_link(COpendriveRoadNode *node,opendrive_mark_t mark new_link->set_parent_lane(lane); // get the curvature node_pose=node->get_pose(); - for(unsigned int i=0;i<this->parents.size();i++) + parent=this->get_parent_with_lane(lane); + if(parent!=NULL) { - if(this->parents[i].lane==lane && this->parents[i].segment==segment) - { - start_curvature=this->parents[i].start_curvature; - end_curvature=this->parents[i].end_curvature; - length=this->parents[i].length; - lane_found=true; - break; - } + start_curvature=parent->start_curvature; + end_curvature=parent->end_curvature; } - if(!lane_found) + else { - start_curvature=0.0; - end_curvature=0.0; - length=sqrt(pow(this->pose.x-node_pose.x,2.0)+pow(this->pose.y-node_pose.y,2.0)); + if(this->get_num_parents()==1) + { + start_curvature=this->parents[0].start_curvature; + end_curvature=this->parents[0].end_curvature; + } + else + { + start_curvature=0.0; + end_curvature=0.0; + } } - new_link->generate(start_curvature,end_curvature,length,lane_found); + new_link->generate(start_curvature,end_curvature); this->add_link(new_link); node->add_link(new_link); @@ -89,7 +99,8 @@ void COpendriveRoadNode::remove_link(COpendriveLink *link) { if((*it)==link) { - delete (*it); + if((*it)->prev==this) + delete (*it); it=this->links.erase(it); break; } @@ -146,7 +157,6 @@ void COpendriveRoadNode::set_scale_factor(double scale) { this->parents[i].start_curvature*=scale/this->scale_factor; this->parents[i].end_curvature*=scale/this->scale_factor; - this->parents[i].length*=this->scale_factor/scale; } } @@ -160,7 +170,7 @@ void COpendriveRoadNode::set_pose(TOpendriveWorldPose &start) this->pose=start; } -void COpendriveRoadNode::add_parent(COpendriveLane *lane,COpendriveRoadSegment *segment,double length,double start_curvature,double end_curvature) +void COpendriveRoadNode::add_parent(COpendriveLane *lane,COpendriveRoadSegment *segment,double start_curvature,double end_curvature) { TOpendriveRoadNodeParent new_parent; @@ -171,7 +181,6 @@ void COpendriveRoadNode::add_parent(COpendriveLane *lane,COpendriveRoadSegment * new_parent.segment=segment; new_parent.start_curvature=start_curvature; new_parent.end_curvature=end_curvature; - new_parent.length=length; this->parents.push_back(new_parent); } @@ -272,15 +281,24 @@ void COpendriveRoadNode::clean_references(segment_up_ref_t &segment_refs,lane_up } } -void COpendriveRoadNode::update_start_pose(COpendriveLane *lane,TOpendriveWorldPose *start) +void COpendriveRoadNode::update_start_pose(COpendriveLane *lane,TOpendriveWorldPose &start,double distance) { std::vector<TOpendriveRoadNodeParent>::iterator parent_it; std::vector<COpendriveLink *>::iterator link_it; - double new_length; - TPoint new_pose; + TOpendriveRoadNodeParent *parent; - if(start==NULL) - return; + this->pose=start; + // remove the references to all lanes and segments except for lane + for(parent_it=this->parents.begin();parent_it!=this->parents.end();) + { + if(parent_it->lane!=lane) + parent_it=this->parents.erase(parent_it); + else + { + parent=&(*parent_it); + parent_it++; + } + } // update the links for(link_it=this->links.begin();link_it!=this->links.end();) { @@ -291,35 +309,35 @@ void COpendriveRoadNode::update_start_pose(COpendriveLane *lane,TOpendriveWorldP } else { - new_pose=(*link_it)->update_start_pose(start); - new_length=(*link_it)->get_length(); + if((*link_it)->lane==lane) + { + parent->start_curvature=(*link_it)->get_curvature_at(distance); + (*link_it)->update_start_pose(start,parent->start_curvature); + } + else + (*link_it)->update_start_pose(start,0.0); link_it++; } } +} + +void COpendriveRoadNode::update_end_pose(COpendriveLane *lane,TOpendriveWorldPose &end,double distance) +{ + std::vector<TOpendriveRoadNodeParent>::iterator parent_it; + std::vector<COpendriveLink *>::iterator link_it; + TOpendriveRoadNodeParent *parent; + // remove the references to all lanes and segments except for lane for(parent_it=this->parents.begin();parent_it!=this->parents.end();) - { + { if(parent_it->lane!=lane) parent_it=this->parents.erase(parent_it); else { + parent=&(*parent_it); parent_it++; - parent_it->length=new_length; - parent_it->start_curvature=new_pose.curvature; } } - -} - -void COpendriveRoadNode::update_end_pose(COpendriveLane *lane,TOpendriveWorldPose *end) -{ - std::vector<TOpendriveRoadNodeParent>::iterator parent_it; - std::vector<COpendriveLink *>::iterator link_it; - double new_length; - TPoint new_pose; - - if(end==NULL) - return; // update the links for(link_it=this->links.begin();link_it!=this->links.end();) { @@ -329,23 +347,7 @@ void COpendriveRoadNode::update_end_pose(COpendriveLane *lane,TOpendriveWorldPos link_it=this->links.erase(link_it); } else - { - new_pose=(*link_it)->update_end_pose(end); - new_length=(*link_it)->get_length(); link_it++; - } - } - // remove the references to all lanes and segments except for lane - for(parent_it=this->parents.begin();parent_it!=this->parents.end();) - { - if(parent_it->lane!=lane) - parent_it=this->parents.erase(parent_it); - else - { - parent_it++; - parent_it->length=new_length; - parent_it->end_curvature=new_pose.curvature; - } } } @@ -460,7 +462,7 @@ unsigned int COpendriveRoadNode::get_closest_link(TOpendriveWorldPose &pose,doub return closest_index; } -double COpendriveRoadNode::get_closest_distance(TOpendriveWorldPose &pose,double angle_tol)const +double COpendriveRoadNode::get_closest_distance(TOpendriveWorldPose &pose,bool only_lanes,double angle_tol)const { double dist,min_dist=std::numeric_limits<double>::max(); double angle; @@ -470,13 +472,16 @@ double COpendriveRoadNode::get_closest_distance(TOpendriveWorldPose &pose,double { if(&this->links[i]->get_prev()==this)// links starting at this node { - this->links[i]->find_closest_world_pose(pose,closest_pose); - angle=diff_angle(normalize_angle(pose.heading),closest_pose.heading); - if(fabs(angle)<angle_tol) + if(!only_lanes || (only_lanes && this->links[i]->lane!=NULL)) { - dist=sqrt(pow(closest_pose.x-pose.x,2.0)+pow(closest_pose.y-pose.y,2.0)); - if(dist<min_dist) - min_dist=dist; + this->links[i]->find_closest_world_pose(pose,closest_pose); + angle=diff_angle(normalize_angle(pose.heading),closest_pose.heading); + if(fabs(angle)<angle_tol) + { + dist=sqrt(pow(closest_pose.x-pose.x,2.0)+pow(closest_pose.y-pose.y,2.0)); + if(dist<min_dist) + min_dist=dist; + } } } } @@ -484,7 +489,7 @@ double COpendriveRoadNode::get_closest_distance(TOpendriveWorldPose &pose,double return min_dist; } -double COpendriveRoadNode::get_closest_pose(TOpendriveWorldPose &pose,TOpendriveWorldPose &closest_pose,double angle_tol) const +double COpendriveRoadNode::get_closest_pose(TOpendriveWorldPose &pose,TOpendriveWorldPose &closest_pose,bool only_lanes,double angle_tol) const { double dist,min_dist=std::numeric_limits<double>::max(); double angle; @@ -498,16 +503,19 @@ double COpendriveRoadNode::get_closest_pose(TOpendriveWorldPose &pose,TOpendrive { if(&this->links[i]->get_prev()==this)// links starting at this node { - length=this->links[i]->find_closest_world_pose(pose,tmp_pose); - angle=diff_angle(normalize_angle(pose.heading),tmp_pose.heading); - if(fabs(angle)<angle_tol) + if(!only_lanes || (only_lanes && this->links[i]->lane!=NULL)) { - dist=sqrt(pow(tmp_pose.x-pose.x,2.0)+pow(tmp_pose.y-pose.y,2.0)); - if(dist<min_dist) + length=this->links[i]->find_closest_world_pose(pose,tmp_pose); + angle=diff_angle(normalize_angle(pose.heading),tmp_pose.heading); + if(fabs(angle)<angle_tol) { - min_dist=dist; - closest_length=length; - closest_pose=tmp_pose; + dist=sqrt(pow(tmp_pose.x-pose.x,2.0)+pow(tmp_pose.y-pose.y,2.0)); + if(dist<min_dist) + { + min_dist=dist; + closest_length=length; + closest_pose=tmp_pose; + } } } } @@ -516,7 +524,7 @@ double COpendriveRoadNode::get_closest_pose(TOpendriveWorldPose &pose,TOpendrive return closest_length; } -void COpendriveRoadNode::get_closest_poses(TOpendriveWorldPose &pose,std::vector<TOpendriveWorldPose> &closest_poses,std::vector<double> &closest_lengths,double dist_tol,double angle_tol) const +void COpendriveRoadNode::get_closest_poses(TOpendriveWorldPose &pose,std::vector<TOpendriveWorldPose> &closest_poses,std::vector<double> &closest_lengths,double dist_tol,bool only_lanes,double angle_tol) const { double dist; double angle; @@ -529,15 +537,18 @@ void COpendriveRoadNode::get_closest_poses(TOpendriveWorldPose &pose,std::vector { if(&this->links[i]->get_prev()==this)// links starting at this node { - length=this->links[i]->find_closest_world_pose(pose,closest_pose); - angle=diff_angle(normalize_angle(pose.heading),closest_pose.heading); - if(fabs(angle)<angle_tol) + if(!only_lanes || (only_lanes && this->links[i]->lane!=NULL)) { - dist=sqrt(pow(closest_pose.x-pose.x,2.0)+pow(closest_pose.y-pose.y,2.0)); - if(dist<=dist_tol) + length=this->links[i]->find_closest_world_pose(pose,closest_pose); + angle=diff_angle(normalize_angle(pose.heading),closest_pose.heading); + if(fabs(angle)<angle_tol) { - closest_poses.push_back(closest_pose); - closest_lengths.push_back(length); + dist=sqrt(pow(closest_pose.x-pose.x,2.0)+pow(closest_pose.y-pose.y,2.0)); + if(dist<=dist_tol) + { + closest_poses.push_back(closest_pose); + closest_lengths.push_back(length); + } } } }