#ifndef __SELECT_TOOL__H #define __SELECT_TOOL__H #include #include "loc_point.h" #include "line.h" #include #include "ant.h" #include "card_path.h" #include "loc_message.h" struct solpoint:point { solpoint() :m_score(100) { } double m_score; bool operator<(const solpoint&p)const { return m_scorem_score=score; } double score()const { return m_score; } }; struct push_data_point:point { push_data_point() :ct(0) ,valid(false) ,stop_cnt(0) { } point dstp; int ct; bool valid; // if valid int stop_cnt; // if calculate speed loc_point lp; }; class select_point_object; struct select_tool { std::mutex m_mtx; zlist m_push_list; select_point_object *m_spo=nullptr; virtual loc_point select_solution(const std::vector p,const std::vector&lm)=0; push_data_point getDpt() { push_data_point dpt; std::lock_guard lock(m_mtx); if (m_push_list.empty()) //empty { return dpt; } else if(m_push_list.size()==1) //size=1 { dpt = m_push_list[0]; m_push_list[0].valid=false; if(m_push_list[0].stop_cnt>5)m_push_list[0].stop_cnt=5; if(m_push_list[0].stop_cnt>0)m_push_list[0].stop_cnt--; } else{ //size>1 dpt = m_push_list[0]; m_push_list.skip(1); } return dpt; } virtual ~select_tool(); }; //--------------person------solution one-------- struct select_tool_person_1:select_tool { virtual loc_point select_solution(const std::vector p,const std::vector&lm); ~select_tool_person_1() { } }; struct select_tool_person_2:select_tool { virtual loc_point select_solution(const std::vector p,const std::vector&lm) { loc_point lp; return lp; } }; //----------------------car---------- struct select_tool_car_1:select_tool { virtual loc_point select_solution(const std::vector p,const std::vector&lm); }; //---------------------drivingfaceCar struct select_tool_drivingface_car_1:select_tool { virtual loc_point select_solution(const std::vector p,const std::vector&lm) { loc_point lp; return lp; } }; //---------------------------------------- struct select_point_object { select_tool * m_owner; public: select_point_object(select_tool * owner) :m_owner(owner) ,m_ct(-10) { att_initiate(); } inline int last_ct(){return m_ct;} public: const static int max_histime=60; //±£Áô×îºó60sµÄÊý¾Ý zlist m_d; line m_line; int m_ct = -10; fit_batch m_fitk,m_fita; fit_result m_cur_fit; loc_point* m_begin; loc_point* m_last; public: int find_last(int start); int find_first(int start); void save_k(); void att_initiate(); void remove_history(); bool make_line(); point select_solution0(std::vector &vp,const double scale); bool select_solution(const std::vector &vp,const site*sit,loc_point &p); loc_point select_solution_impl(const std::vector p,const std::vector&lm); fit_result* best_fit_raw(int num_point=0,int start=0,int end=-1); bool filter_by_acc(loc_point&c,std::array&v,double a); bool filter_by_fit(loc_point & c,const std::vector & vp,const double scale); void select_one_ant(loc_point &c,const std::vector & vp); public: virtual void select_solution1(loc_point &c,const std::vector &vp,const double scale)=0; virtual fit_result * get_best_fit()=0; virtual double getA(const fit_result * fit,const double scale,const double dt)=0; virtual void reset_fit(double d)=0; virtual bool revise_by_history(point & pt, const site*sit, int64_t m_time)=0; virtual ~select_point_object(){} }; struct person_point_filter:select_point_object { person_point_filter(select_tool * owner) :select_point_object(owner) ,m_filter_man_count(0) {} int m_filter_man_count=0; virtual void reset_fit(double d) { if(d>1) m_filter_man_count++; else m_filter_man_count = 0; if(m_filter_man_count==3) { m_fitk.reset_data(); m_fita.reset_data(); m_cur_fit.reset(); m_begin=m_last=nullptr; m_filter_man_count = 0; } } virtual void select_solution1(loc_point &c,const std::vector &vp,const double scale) { if(filter_by_fit(c,vp,scale)) { c.inc_cl(40); } else if(c.cl()>0 && vp.size()==2) { c[0]=vp[0]; c[1]=vp[1]; c.inc_cl(10); } else { select_one_ant(c,vp); } } virtual fit_result * get_best_fit() { return best_fit_raw(4,4); } virtual double getA(const fit_result * fit,const double scale,const double dt) { double a=2.5; if(fabs(fit->k)<2/(3.6*scale) && fabs(fit->k)>0.5/(3.6*scale) && dt<10) { a=0.3; } return a; } virtual bool revise_by_history(point & pt, const site*sit, int64_t timestamp) { //log_info("lemon test revise preson:cardid:%d sit:%d sitid:%d %0X",m_d(0).m_cid,sit->m_id,m_d(0).m_sid,sit); point dstp = sit->get_dstp(pt); if(dstp.empty()) log_error("person.dstp empty()"); push_data_point dp; dp.dstp.set(dstp); dp.ct=m_d(0).m_ct; dp.valid=true; dp.stop_cnt=5; dp.lp=m_d(0); dp.set(pt); { //don't delete the braces std::lock_guard lock(m_owner->m_mtx); m_owner->m_push_list.clear(); m_owner->m_push_list.push(dp); //dp.lp.debug_out("person"); } return true; } }; struct car_point_filter:select_point_object { car_point_filter(select_tool * owner) :select_point_object(owner) ,m_last_fit_valid(false) ,m_last_fit_k(0) ,m_last_fit_kb(0) ,m_last_fit_ka(0) ,m_last_fit_xo(0) ,m_last_fit_yo(0) ,m_last_fit_md_x(0) ,m_last_fit_md_y(0) ,m_last_fit_time_sec(0) ,m_last_fit_nearest_time_sec(0) ,m_last_time_sec(0) ,m_if_turning(false) {} bool m_last_fit_valid = false; double m_last_fit_k ; double m_last_fit_kb; double m_last_fit_ka; double m_last_fit_xo ; double m_last_fit_yo; double m_last_fit_md_x; double m_last_fit_md_y; double m_last_fit_time_sec; //x(0) of latest valid fit double m_last_fit_nearest_time_sec; double m_last_time_sec=0; bool m_if_turning=false; point m_turning_pt; point m_turning_ept; double m_simple_rec_kx,m_simple_rec_ky; const double m_fit_differ=4; const double m_pos_differ=8; virtual void reset_fit(double d){} virtual void select_solution1(loc_point &c,const std::vector &vp,const double scale) { //two ants. if(c.cl()>0 && vp.size()==2)//m_card->smoothFlag() ) { c[0]=vp[0]; c[1]=vp[1]; c.inc_cl(50); } else if(filter_by_fit(c,vp,scale)) { c.inc_cl(40); } else { select_one_ant(c,vp); } } const fit_result* best_fit()const { if(m_cur_fit.k==0 && m_cur_fit.ke==0) return nullptr; return &m_cur_fit; } virtual fit_result * get_best_fit() { return best_fit_raw(5); } virtual double getA(const fit_result * fit,const double scale,const double dt) { double a=2.5; if(fabs(fit->k)<10/(3.6*scale) && fabs(fit->k)>1/(3.6*scale) && dt<20) { a=1; } if(fabs(fit->k)<=1/(3.6*scale) && dt<20) { a=-1; } return a; } void reset_turning() { m_if_turning=false; m_turning_pt.set(0,0); m_turning_ept.set(0,0); } void generate_list(point &pt, const site*sit, bool is_whole_list) { //log_info("lemon test 4 :cardid:%d sit:%d sitid:%d",m_d(0).m_cid,sit->m_id,m_d(0).m_sid); if(is_whole_list) { put_loc_point(pt, sit, m_d(0).m_ct, m_d(0)); } else { put_single_loc_point(pt, sit, m_d(0).m_ct, m_d(0)); } } void turning_mapping(point &rpt,const site*sit) { if(!m_if_turning)return; point sit_location; //projection //sit_location.set(sit->x,sit->y); sit_location = sit->get_dstp(m_turning_pt); if(sit_location.empty()) std_error("get_dstp point error....."); double dist1=sit_location.dist(rpt); double dist2=sit_location.dist(m_turning_pt); double dist3=m_turning_pt.dist(rpt); // dist1 is supposed to be = dist2+dist3 if(dist1<=dist2 || dist1<=dist3) { if(dist2-dist1>3||dist1<=dist3) { printf("reset turning\n"); reset_turning(); // may encounter problems } return; } if(dist3>10)dist3=10; // turning distance no more than 10 double turning_x,turning_y; double dist4=m_turning_pt.dist(m_turning_ept); turning_x=m_turning_pt.x + dist3 * (m_turning_ept.x - m_turning_pt.x) / dist4; turning_y=m_turning_pt.y + dist3 * (m_turning_ept.y - m_turning_pt.y) / dist4; printf("turning mapping:(%.2f,%.2f)->(%.2f,%.2f),d1:%f,d2:%f,d3:%f\n", rpt.x,rpt.y,turning_x,turning_y,dist1,dist2,dist3); rpt.set(turning_x,turning_y); } void put_single_loc_point(point &pt, const site*sit, int ct, loc_point &lp) { //log_info("lemon test 6 :cardid:%d sit:%d sitid:%d",m_d(0).m_cid,sit->m_id,m_d(0).m_sid); point rpt; rpt.set(pt); turning_mapping(rpt,sit); if(!card_path::inst().is_at_path(rpt)) //if point not on the path { lp.debug_out(); printf("out of path:t=%ld,sit=%d,card=l,ct=%d," "tof1=%d,tof2=%d,pt=(%.2lf,%.2lf)\n", m_d(0).m_time, m_d(0).m_sid,m_d(0).m_ct, m_d(0).m_tof[0], m_d(0).m_tof[1], pt.x, pt.y); return; } point dstp; //projection if(!m_if_turning) { //dstp.set(sit->x,sit->y); dstp = sit->get_dstp(pt); if(dstp.empty()) log_error("error.here....here."); } else { dstp.set(m_turning_pt); } push_data_point dp; dp.dstp.set(dstp); dp.ct=ct; dp.valid=true; dp.stop_cnt=5; dp.lp=lp; dp.set(rpt); { //don't delete the braces std::lock_guard lock(m_owner->m_mtx); m_owner->m_push_list.clear(); m_owner->m_push_list.push(dp); //dp.lp.debug_out("single point ."); } } double estimate_point_by_history(const site*sit, double m_time_sec) { double estimate_dist = m_last_fit_k * (m_time_sec-m_last_fit_xo) + m_last_fit_kb + m_last_fit_yo; point pt(m_last_fit_md_x + estimate_dist * m_simple_rec_kx, m_last_fit_md_y + estimate_dist * m_simple_rec_ky); int fidx=find_first(0); if(fidx>=0) { loc_point&f=m_d[fidx]; estimate_dist = f.loc_dist(pt); } else estimate_dist = 0; return estimate_dist; } point convert_dist_to_pt(double dist, const site*sit) { int fidx=find_first(0); if(fidx<0)return point(0, 0); loc_point&f=m_d[fidx]; return point(f.m_sol[0].x + dist * m_simple_rec_kx, f.m_sol[0].y + dist * m_simple_rec_ky); } void put_loc_point(point &pt, const site*sit, int ct, loc_point &lp) { //log_info("lemon test 5 :cardid:%d sit:%d sitid:%d",m_d(0).m_cid,sit->m_id,m_d(0).m_sid); point rpt; rpt.set(pt); turning_mapping(rpt,sit); if(!card_path::inst().is_at_path(pt)) //if point not on the path { lp.debug_out(); printf("out of path:t=%ld,sit=%d,card=0,ct=%d," "tof1=%d,tof2=%d,pt=(%.2lf,%.2lf)\n", m_d(0).m_time, m_d(0).m_sid,m_d(0).m_ct, m_d(0).m_tof[0], m_d(0).m_tof[1], pt.x, pt.y); return; } point dstp; //projection if(!m_if_turning) { dstp = sit->get_dstp(pt); if(dstp.empty()) log_error("dstp.empty().."); //dstp.set(sit->x,sit->y); } else { dstp.set(m_turning_pt); } int size = 0; push_data_point dp[13]; dp[size].dstp.set(dstp); dp[size].ct=ct; dp[size].valid=true; dp[size].stop_cnt=5; dp[size].lp=lp; dp[size].set(rpt); double missing_time = m_d(0).m_time/1000.; size++; for(;size<13;size++) { dp[size].dstp.set(dstp); dp[size].ct = ct; dp[size].valid=true; dp[size].stop_cnt=5; double mt = missing_time + size; double missing_dist = estimate_point_by_history(sit, mt); point missing_point = convert_dist_to_pt(missing_dist, sit); if(!card_path::inst().is_at_path(missing_point)) //if point not on the path { break; } turning_mapping(missing_point,sit); //turning dp[size].set(missing_point); dp[size].lp.set(missing_point); dp[size].lp.m_time=(int64_t)(missing_time * 1000); dp[size].lp.m_sid = sit->m_id; //dp[size].lp.m_cid = m_d(0).m_cid; } { std::lock_guard lock(m_owner->m_mtx); m_owner->m_push_list.clear(); for(int i=0;im_push_list.push(dp[i]); //dp[i].lp.debug_out("push_list"); } } } double convert_pt_to_dist(point &pt, const site*sit) { double dist=0; int fidx=find_first(0); if(fidx>=0) { loc_point&f=m_d[fidx]; //printf("find_first:(%.2f,%.2f)(%.2f,%.2f)\n",f.m_sol[0].x,f.m_sol[0].y,pt.x,pt.y); //dist = f.dist(pt) * (ptdist_direct(pt); //if(dist == 0)return 0; //m_simple_rec_kx = (pt.x - (*sit).x) / dist; //m_simple_rec_ky = (pt.y - (*sit).y) / dist; return dist; } virtual bool revise_by_history(point & pt, const site*sit, int64_t timestamp) { //log_info("lemon test 3 :cardid:%d sit:%d sitid:%d",m_d(0).m_cid,sit->m_id,m_d(0).m_sid); bool flag =false; if(m_line.empty() || !m_line.contain(m_d(0),0.1)) { m_last_fit_valid = false; m_last_fit_time_sec = 0; m_last_fit_k = 0; m_last_fit_kb = 0; m_last_fit_ka = 0; m_last_fit_xo = 0; m_last_fit_yo = 0; m_last_fit_nearest_time_sec = 0; m_last_time_sec = 0; reset_turning(); generate_list(pt, sit, false); return true; } // convert pt to distance double dist = convert_pt_to_dist(pt, sit); double m_time_sec = timestamp / 1000.; //second //if(m_time_sec - m_last_fit_nearest_time_sec > 30)m_last_fit_valid = false; if(m_time_sec - m_last_fit_time_sec > 60)m_last_fit_valid = false; // update acc //m_accumulate_acc = m_d(0).m_acc; // choose data by fit const fit_result*fit=best_fit(); bool if_change_fit=false; if(fit!=nullptr && fit->ke<=1 && m_time_sec - m_fitk.x(0) <= 15 && fabs(fit->k) < m_pos_differ) { //printf("change fit time:%f,%f,%f\n",m_time_sec, fit->d.x(0), m_time_sec - fit->d.x(0)); // put m_acccumulate_acc into consideration // fit->k - m_last_fit_k < m_accumulate_acc if(m_last_fit_valid == true && m_last_fit_k * fit->k > -0.6) //if((sit->dist(pt)<20 ||m_last_fit_k * fit->k > -0.6)) { //if point is too near the sit: do not not judge the backwards double est1 = estimate_point_by_history(sit, m_last_fit_time_sec); double est2 = fit->k * (m_time_sec-fit->xo) + fit->kb + fit->yo; //printf("change fit:1(%f,%f),2(%f,%f),differ:(%f,%f)\n", // m_last_fit_nearest_time_sec,est1,m_time_sec,est2,m_time_sec-m_last_fit_nearest_time_sec,est2-est1); //if(fabs(est1-est2)>40)printf("change fit:%f,%f,%f\n",fabs(est1-est2),est1,est2); if(fabs(est1-est2)< (m_time_sec - m_last_fit_time_sec) * 5) // large jump is not allowed if_change_fit=true; } else if(m_last_fit_valid==false) if_change_fit=true; } if(if_change_fit) { m_last_fit_valid = true; m_last_fit_time_sec = m_fitk.x(0); m_last_fit_k = fit->k; m_last_fit_kb = fit->kb; m_last_fit_ka = fit->ka; m_last_fit_xo = fit->xo; m_last_fit_yo = fit->yo; m_last_fit_nearest_time_sec = m_fitk.x(0); int fidx=find_first(0); if(fidx<0) { m_last_fit_md_x = 0; m_last_fit_md_y = 0; } else{ loc_point&f=m_d[fidx]; m_last_fit_md_x = f.m_sol[0].x; m_last_fit_md_y = f.m_sol[0].y; } // update acc //m_accumulate_acc=0 //printf("change line------------, k=%f,ke=%f\n",fit->k,fit->ke); } // revise double estimate_dist = estimate_point_by_history(sit, m_time_sec); //printf("revise:est:%f, d:%f, fitvalid:%d, timesecdiffer:%f\n", //estimate_dist, dist, m_last_fit_valid, m_time_sec - m_last_fit_time_sec); if(m_last_fit_valid && m_time_sec - m_last_fit_time_sec < 20) { if(fabs(m_last_fit_k) > 0.5 && fabs(estimate_dist-dist)>m_fit_differ) dist=estimate_dist; else if(fabs(m_last_fit_k) <= 0.5 && fabs(estimate_dist-dist)>m_fit_differ * 2) dist=estimate_dist; else flag = true; //m_last_fit_nearest_time_sec = m_time_sec; //need more tests to uncomment this sentence } else m_last_fit_nearest_time_sec = m_time_sec; m_last_time_sec = m_time_sec; // convert the estimated dist to pt point mpt = convert_dist_to_pt(dist, sit); // judging turning detect_turning(mpt, sit); // create the list //if(m_accumulate_acc<-10)generate(mpt, sit,false); generate single point if(m_last_fit_valid && timestamp/1000. - m_last_fit_time_sec < 20 && fabs(m_last_fit_k) > 0.5) generate_list(mpt, sit, true); //generate the whole list else generate_list(mpt, sit, false); //generate single point //turning map turning_mapping(mpt, sit); pt = mpt; return flag; } void detect_turning(point &mpt, const site*sit) { if(m_if_turning)return; //IMPORTANT: only car-1121 and car-1136 have accurate rav values currently. May delete this sentence in the future. //if(m_id!=1121 && m_id!=1136)return; double detect_area = 4; double detect_angle = 15; //15 double detect_para = 0.25; //0.25 // check angle double angle=-m_d(0).m_rav; // right+ left- if(fabs(angle)>180)return; // invalid data if(fabs(angle) turning_list=card_path::inst().find_possible_path(mpt, detect_area);; //angle1 int fidx=find_first(0); if(fidx<0)return; double dist=m_d[fidx].loc_dist(mpt); point pt1; pt1.set(m_d[fidx].m_sol[0]); double angle1; if(m_last_fit_k * dist>0) angle1=calc_turning_angle(pt1, mpt); else angle1=calc_turning_angle(mpt, pt1); if(angle1<0)return; //finding for(unsigned int i=0;i180)delta=delta-360; if(delta<-180)delta=delta+360; if(fabs(delta)<5)continue; if(fabs(delta)>175)continue; //printf("angle:%f, delta:%f. mul:%f\n",angle, delta, delta*detect_para); // turning angle must be correct if(angle*delta>0 && fabs(angle)>fabs(delta)*detect_para) { printf("turning:(%.5f,%.5f)(%.5f,%.5f)(%.5f,%.5f),a1:%f,a2:%f,delta:%f,angle:%f\n", pt1.x,pt1.y,l.v[0].x,l.v[0].y,l.v[1].x,l.v[1].y,angle1,angle2,delta,angle); m_if_turning=true; m_turning_pt.set(l.v[0]); m_turning_ept.set(l.v[1]); break; } } } double calc_turning_angle(point &a, point &b) { if(fabs(a.x-b.x)<0.001) { if(fabs(a.y-b.y)<0.001)return -1; return b.y>a.y?90:270; } double angle=std::atan((b.y-a.y)/(b.x-a.x))*180/3.1415926; if(a.x>b.x)angle=angle+180; if(angle<0)angle=angle+360; return angle; } }; //---------------------smooth struct smooth_tool { std::unique_ptr&m_st; bool smooth_initial_setting; double smooth_speed; double smooth_speed_presentation; int smooth_speed_presentation_cnt; point smooth_last_position; double smooth_last_time_sec; point smooth_last_true_position; line smooth_line; bool smooth_line_reset; //if line reset bool smooth_halt_condition; //if halting int smooth_halt_count; //halting count point smooth_halt_position; //position while begin halting point smooth_halt_position_plus; point smooth_halt_position_minus; smooth_tool()=default; smooth_tool(std::unique_ptr&st) :m_st(st) ,smooth_initial_setting(false) ,smooth_speed(0) ,smooth_speed_presentation(0) ,smooth_speed_presentation_cnt(0) ,smooth_last_time_sec(0) ,smooth_halt_condition(0) ,smooth_halt_count(0) {} void smooth_set_loc_point(double t, int ct, const site*sit, loc_point *lp) { point pt; if(smooth_halt_condition) pt.set(smooth_halt_position); else pt.set(smooth_last_position); lp->m_dist2=sit->dist_direct(pt); lp->m_smooth_x=pt.x; lp->m_smooth_y=pt.y; lp->m_time=(int64_t)(t*1000); lp->m_ct=ct; if(smooth_halt_condition) { lp->m_speed=0; lp->m_stat=0; } else { lp->m_speed=smooth_speed_presentation * (3.6*sit->m_scale) ; //(m/s) to (km/h) if(smooth_speed<0) lp->m_speed = -lp->m_speed; if(std::isnan(lp->m_speed)) lp->m_speed=0; lp->m_stat=1; //if(fabs(smooth_speed_presentation) < 0.1) // lp->m_speed=0; } } void smooth_reset() { smooth_initial_setting=false; smooth_speed=0; //smoothed speed //smooth_speed_presentation=0; smooth_speed_presentation_cnt=0; smooth_last_position=point(0,0); //last position of smoothed point smooth_last_true_position=point(0,0); //last position of true point smooth_last_time_sec=0; //last time second smooth_halt_condition = false; smooth_halt_count=0; } bool smooth_initiate(point &pt, double t, const site*sit) { smooth_initial_setting=true; smooth_speed=0; //smooth_speed_presentation=0; smooth_speed_presentation_cnt=0; smooth_last_position = pt; smooth_last_true_position = pt; smooth_last_time_sec = t; smooth_halt_condition=false; smooth_halt_count=0; smooth_halt_position=pt; smooth_halt_position_plus=pt; smooth_halt_position_minus=pt; return true; } virtual void set(point &pt,loc_point &lp)=0; loc_point smooth_strategy() { loc_point lp; push_data_point dpt = m_st->getDpt(); if(dpt.empty()) return lp; point pt; pt.set(dpt); double current_t=time(NULL); const auto & sit = sit_list::instance()->get(dpt.lp.m_sid); if(dpt.valid) { smooth_dist(pt, current_t, dpt.ct, sit.get(), dpt.dstp, &lp); set(pt,lp); dpt.lp.m_dist2=lp.m_dist2; dpt.lp.m_time=lp.m_time; dpt.lp.m_ct=lp.m_ct; dpt.lp.set(lp); dpt.lp.m_dist=sit->dist_direct(dpt); dpt.lp.m_speed=lp.m_speed; dpt.lp.m_stat=lp.m_stat; dpt.lp.debug_out("get_point"); } else { smooth_set_loc_point(current_t, dpt.ct, sit.get(), &lp); if(dpt.stop_cnt<=0) { lp.m_speed=0; lp.m_stat=0; } set(pt,lp); } return lp; } virtual void smooth_dist(point &pt, double t, int ct, const site*sit, point dstp, loc_point *m_lp = nullptr)=0; virtual ~smooth_tool(){} }; struct smooth_tool_person_1:smooth_tool { smooth_tool_person_1(std::unique_ptr&m) :smooth_tool(m) {} virtual void set(point &pt,loc_point &lp) { lp.set(pt); } void smooth_dist(point &pt, double t, int ct, const site*sit, point dstp, loc_point *m_lp = nullptr) { if(smooth_line.empty() || !smooth_line.contain(pt,0.1)) { if(!smooth_line_reset) { smooth_reset(); smooth_line_reset=true; } else { std::vector path=card_path::inst().find_path(smooth_last_true_position, pt); if(!path.empty() && smooth_last_true_position.dist(path[0])>200) path.clear(); if(path.empty()) { smooth_line.set(smooth_last_true_position, pt); smooth_line_reset=false; } else { smooth_reset(); } } } else smooth_line_reset=false; if(!smooth_initial_setting) { smooth_initiate(pt, t, sit); } else { double current_dist = dstp.dist_direct(pt); double last_true_position = dstp.dist_direct(smooth_last_true_position); double max_span = 100; if(fabs(current_dist-last_true_position)1)new_speed=smooth_speed +1*(new_speed>smooth_speed?1:-1); smooth_speed = smooth_speed * 0.4 + new_speed * 0.6; smooth_last_true_position = pt; smooth_last_position = pt; smooth_last_time_sec = t; if(fabs(smooth_speed_presentation)<1e-6 || std::isnan(smooth_speed_presentation)) { smooth_speed_presentation=fabs(smooth_speed); } else smooth_speed_presentation = smooth_speed_presentation * 0.4 + fabs(smooth_speed) * 0.6; if(fabs(smooth_speed)<0.1)smooth_speed_presentation=0; } else { smooth_reset(); smooth_initiate(pt, t, sit); } } if(m_lp != nullptr)//m_time,m_ct,x,y,m_speed,m_stat { smooth_set_loc_point(t, ct, sit, m_lp); } } }; struct smooth_tool_car_1:smooth_tool { smooth_tool_car_1(std::unique_ptr&m) :smooth_tool(m) {} virtual void set(point &pt,loc_point &lp) { lp.set(lp.m_smooth_x,lp.m_smooth_y); } void smooth_dist(point &pt, double t, int ct, const site*sit, point dstp, loc_point *m_lp = nullptr) { point init_pt(pt.x, pt.y); if(smooth_line.empty() || !smooth_line.contain(pt,0.1) || smooth_halt_count>6) { if(!smooth_line_reset) { if(!smooth_line.empty() && !smooth_line.contain(pt,0.1) && !smooth_last_true_position.empty()) { std::vector path=card_path::inst().find_path(smooth_last_true_position, pt); if(!path.empty() && smooth_last_true_position.dist(path[0])>200) path.clear(); printf("generating critical point in smooth(car):(%.2f,%.2f)->(%.2f,%.2f)\n", smooth_last_true_position.x, smooth_last_true_position.y, pt.x, pt.y); if(!path.empty()) { point critical_point=path[0]; printf("critical point generated in smooth(car):pt=(%.2f,%.2f),(%.2f,%.2f)->(%.2f,%.2f)\n", critical_point.x, critical_point.y, smooth_last_true_position.x, smooth_last_true_position.y, pt.x, pt.y); init_pt.set(critical_point); } } smooth_reset(); smooth_line_reset=true; } else { std::vector path=card_path::inst().find_path(smooth_last_true_position, pt); if(!path.empty() && smooth_last_true_position.dist(path[0])>200) path.clear(); if(path.empty()) { smooth_line.set(smooth_last_true_position, pt); smooth_line_reset=false; } else { smooth_reset(); } } } else smooth_line_reset=false; if(!smooth_initial_setting) { smooth_initiate(init_pt, t, sit); } else { double current_dist = dstp.dist_direct(pt); double last_position = dstp.dist_direct(smooth_last_position); double last_true_position = dstp.dist_direct(smooth_last_true_position); double rec_kx=0; double rec_ky=0; if(current_dist!=0) { rec_kx = (pt.x - dstp.x)/current_dist; rec_ky = (pt.y - dstp.y)/current_dist; } double next_dist = last_position + smooth_speed * (t-smooth_last_time_sec); double max_span = 200; //printf("smooth dist:%f,%f,%f\n",next_dist,current_dist,next_dist-current_dist); if(fabs(next_dist-current_dist)=3 && fabs(smooth_speed) < 0.2) { smooth_halt_condition=true; smooth_halt_position=smooth_last_position; smooth_halt_position_plus=pt; smooth_halt_position_minus=pt; } // handle speed if(smooth_halt_condition) { double halt_position = dstp.dist_direct(smooth_halt_position); double halt_position_plus = dstp.dist_direct(smooth_halt_position_plus); double halt_position_minus = dstp.dist_direct(smooth_halt_position_minus); if(halt_position_pluscurrent_dist)halt_position_minus=current_dist; smooth_halt_position_plus = point(dstp.x + halt_position_plus * rec_kx, dstp.y + halt_position_plus * rec_ky); smooth_halt_position_minus = point(dstp.x + halt_position_minus * rec_kx, dstp.y + halt_position_minus * rec_ky); if(fabs(halt_position_plus - halt_position_minus)>1) { smooth_halt_condition=false; last_position = halt_position; smooth_speed = 0; //printf("smooth stop halting\n"); } } else { if(fabs(smooth_speed)<1e-6 || std::isnan(smooth_speed)) { smooth_speed=new_speed; if(smooth_speed>2.5)smooth_speed=2.5; if(smooth_speed<-2.5)smooth_speed=-2.5; } else { double speed_differ = fabs(new_speed-smooth_speed); if(speed_differ>1) new_speed=smooth_speed +1*(new_speed>smooth_speed?1:-1); smooth_speed = smooth_speed * 0.4 + new_speed * 0.6; } if(fabs(smooth_speed_presentation)<1e-6 || std::isnan(smooth_speed_presentation)) { smooth_speed_presentation=fabs(smooth_speed); } else smooth_speed_presentation = smooth_speed_presentation * 0.4 + fabs(smooth_speed) * 0.6; //printf(",%f,%f\n",new_speed,smooth_speed); // must obey speed direction if(smooth_speed * (current_dist-last_position) > 0) { last_position = last_position+smooth_speed*(t-smooth_last_time_sec); if(smooth_speed * (current_dist-last_position) < 0) { last_position = current_dist; } smooth_speed_presentation_cnt=0; } else { if(smooth_speed_presentation_cnt<3) smooth_speed_presentation_cnt++; else smooth_speed_presentation=0; } if(fabs(smooth_speed)<0.1)smooth_speed_presentation=0; double revise_para = 0.2; if(fabs(smooth_speed) < 0.01 || smooth_speed * (current_dist-last_position) < 0) revise_para=0; last_position=last_position+(current_dist-last_position)*revise_para; } smooth_last_position = point(dstp.x + last_position * rec_kx, dstp.y + last_position * rec_ky); smooth_last_true_position = pt; smooth_last_time_sec = t; } else { smooth_reset(); smooth_initiate(pt, t, sit); } } if(m_lp != nullptr)//m_time,m_ct,x,y,m_speed,m_stat { smooth_set_loc_point(t, ct, sit, m_lp); } } }; struct smooth_tool_drivingface_car_1:smooth_tool { smooth_tool_drivingface_car_1(std::unique_ptr&m) :smooth_tool(m) {} virtual void set(point&p,loc_point&lp){} virtual void smooth_dist(point &pt, double t, int ct, const site*sit, point dstp, loc_point *m_lp = nullptr){} }; //--------------------------------- struct select_tool_manage { void create_tool(const std::string &s,std::unique_ptr &set,std::unique_ptr &smt) { if(!s.compare(std::string{"person1"})) { set.reset(new select_tool_person_1()); smt.reset(new smooth_tool_person_1(set)); } else if(!s.compare(std::string{"person2"})) { set.reset(new select_tool_person_2()); smt.reset(new smooth_tool_person_1(set)); } else if(!s.compare(std::string{"car1"})) { set.reset(new select_tool_car_1()); smt.reset(new smooth_tool_car_1(set)); } else if(!s.compare(std::string{"drivingface1"})) { set.reset(new select_tool_drivingface_car_1()); smt.reset(new smooth_tool_drivingface_car_1(set)); } } static select_tool_manage * instance(); }; #endif