📄 objects.cpp
字号:
DoLog(LOG_UPDATE, "Estimate Ball Moving with (%.2f %.2f) at %d", Vel(time).x, Vel(time).y, time);
}
}
void MobileObject::estimate_pos(Time time){
Vector epos = Pos(time -1) + gvel.ChkData(time) / speed_decay + Self.pos_gap.ChkData(time);
gpos.Setdata(epos , time);
pos_conf *= conf_decay;
pos_time = time;
if(Self.pos_gap.IsDataKnown(time)){
coordinate_time = time;
}
}
//overloaded function, no use
bool MobileObject::Isupdate_heard(){
if(!heard_pos) return false;
if(!pos_valid()) return true;
return true;
}
void MobileObject::update_heard(Time time){
#ifdef _Up_FState
isupdateheard = false;
return ;
#endif
isupdateheard = Isupdate_heard();
if (isupdateheard){
newpos = true;
gpos.Setdata(heardpos_info.data.mean, heardpos_info.time);
pos_time = heardpos_info.time;
coordinate_time = pos_time;
//0.2f 代表双方的定位误差. 当别人喊出一个绝对坐标时,有他的坐标系和自己的坐标系的偏差
float relateive_delta = heardpos_info.data.delta + CP_coordinate_gap_between_agents;
relateive_delta -= (heardpos_info.data.mean - Self.pos).mod() * ServerParam::dist_qstep;
relateive_delta = Max(relateive_delta, 0.0f);
original_postime = heardpos_info.time;
pos_conf = (float)pow(conf_decay, relateive_delta);
//由于没有喊出original_postime,暂时取消这的更新
//original_postime = heardpos_info.time;
pos_delta_time = heardpos_info.time;
pos_deltas.Setdata(heardpos_info.data.delta + CP_coordinate_gap_between_agents, pos_delta_time);
pos_delta_valid = true;
}
}
bool MobileObject::inview(Time time){
if (!IsValidObject()) return false;
if (pos_time < time){
estimate(time);
}
Vector tmp_pos = (Pos(time) - Self.Pos(time)).Rotate(-Self.Headfacing(time));
if(tmp_pos.mod() < ServerParam::feel_distance * 0.5f) return true;
//DoLog(7,"The Object is assumed to be at rel(%.2f %.2f)", tmp_pos.x, tmp_pos.y);
float slide_dist = 1.0f / Sin(Self.MyViewAngle(Self.viewwidth.Data(time)));
tmp_pos -= Vector(slide_dist, 0.0f);
return bool(fabs(tmp_pos.Angle()) <= Self.MyViewAngle(Self.viewwidth.Data(time)));
}
void MobileObject::forget(){
forgot = true;
}
bool MobileObject::speed_valid(){
return bool(speed_conf > min_valid_conf);
}
Vector MobileObject::PredictPos(int cycles){
Vector predictpos = pos;
Vector vel = global_vel;
int i;
for(i = 0; i < cycles;i++){
predictpos += vel;
vel *= speed_decay;
}
return predictpos;
}
void MobileObject::PredictPos(Vector p[], int cycles){
if(cycles <= 0) return;
Vector vel = global_vel;
p[0] = pos + vel;
int i;
for(i = 1; i < cycles;i++){
vel *= speed_decay;
p[i] = p[i-1] + vel;
}
}
float MobileObject::MinDist(const Vector& tpos){
float Min_dist = domain.Data(situation.CurrentTime).Dist(tpos - Self.pos);
Min_dist = Max(Min_dist, pos.dist(tpos) - pos_delta);
return Min_dist;
}
float MobileObject::Max_posx(){
float max = pos.x + pos_delta;
max = Min(max, domain.Data(situation.CurrentTime).Getmax_x() + Self.pos.x);
return max;
}
float MobileObject::Min_posx(){
float min = pos.x - pos_delta;
min = Max(min, domain.Data(situation.CurrentTime).Getmin_x() + Self.pos.x);
return min;
}
float MobileObject::GetOffsensitivity(){
return GetOffsensitivity(situation.CurrentTime);
}
float MobileObject::GetOffsensitivity(Time t){
if(!offsensitivity.IsDataKnown(t)){
offsensitivity.Setdata(FieldInfo.GetOffensiveSensitivity(Pos(t)), t);
}
return offsensitivity.Data(t);
}
float MobileObject::GetDefsensitivity(){
return GetDefsensitivity(situation.CurrentTime);
}
float MobileObject::GetDefsensitivity(Time t){
if(!defsensitivity.IsDataKnown(t)){
defsensitivity.Setdata(FieldInfo.GetDefensiveSensitivity(Pos(t)), t);
}
return defsensitivity.Data(t);
}
bool MobileObject::IsLastSeen(){
return bool(Last_seen_time() == Self.Last_seen_time()) ;
}
/********************* Ball **************************/
Ball::Ball(){
posgap_time = -1;
velgap_time = -1;
}
void Ball::update_seengap(Time t){
#ifdef _Up_FState
if(sensory.HasFullState() && acc_vel.IsDataKnown(t)){
posgap.Setdata(0, t);
posgap_time = t;
velgap.Setdata(0, t);
velgap_time = t;
return;
}
#endif
if(!seenposinfo.IsDataKnown(t)) return;
Vector t_posgap;
float headfacingap = 1.5f;
float dist = seen_distance(t);
float rposagl = NormalizeAngle(Self.Headfacing(t) + seen_rel_angle(t));
float fcosagl = (float)fabs(Cos(rposagl));
float fsinagl = (float)fabs(Sin(rposagl));
//相对距离与角度误差
float dis_gap = 0.05f + 0.513f * dist * ServerParam::dist_qstep/0.9f;
float agl_gap = Deg2Rad(0.5f + headfacingap);
//投影到全局坐标上的误差换算
t_posgap.x = dis_gap * fcosagl + (dist + dis_gap) * agl_gap * fsinagl;
t_posgap.y = dis_gap * fsinagl + (dist + dis_gap) * agl_gap * fcosagl;
posgap.Setdata(t_posgap,t);
Vector rpos = Pos(t) - Self.Pos(t);
DoLog(LOG_UPDATE,"ball rpos(%.4f,%.4f) gap(%.4f %.4f) hafcing %.1f at %d", rpos.x,rpos.y, t_posgap.x, t_posgap.y, Self.Headfacing(t),t);
posgap_time = t;
if(seenchinfo.IsDataKnown(t)){
Vector t_velgap;
//相对速度误差
t_velgap.x = dis_gap / dist * (float)fabs(seen_distCh(t)) + (dist + dis_gap) * ServerParam::disch_qstep * 0.5f;
t_velgap.y = dis_gap * Deg2Rad(seen_dirCh(t)) + (dist + dis_gap) * Deg2Rad(ServerParam::dir_qstep * 0.5f);
t_velgap = t_velgap.Rotate(rposagl);
t_velgap.x = (float)fabs(t_velgap.x);
t_velgap.y = (float)fabs(t_velgap.y);
//旋转rposagl引入的误差
float tmp = t_velgap.y;
t_velgap.y += t_velgap.x * agl_gap;
t_velgap.x += tmp * agl_gap;
//Self的速度误差
Vector svelgap;
float rvelagl = NormalizeAngle(Self.Headfacing(t) + Self.SpeedAngle(t));
fcosagl = (float)fabs(Cos(rvelagl));
fsinagl = (float)fabs(Sin(rvelagl));
svelgap.x = (Self.Speed(t) + 0.005f) * agl_gap * fsinagl;
svelgap.y = (Self.Speed(t) + 0.005f) * agl_gap * fcosagl;
t_velgap += svelgap;
velgap.Setdata(t_velgap,t);
velgap_time = t;
DoLog(LOG_UPDATE,"ball vel(%.4f,%.4f) gap(%.4f %.4f) selfvel gap(%.2f,%.2f)",Vel(t).x,Vel(t).y,t_velgap.x,t_velgap.y,svelgap.x,svelgap.y);
}
}
void Ball::estimategap(Time t){
#ifdef _Up_FState
if(sensory.HasFullState() && acc_vel.IsDataKnown(t)){
velgap.Setdata(0, t);
velgap_time = t;
posgap.Setdata(0, t);
posgap_time = t;
return;
}
#endif
Time i;
Vector gap;
for(i = velgap_time; i < t; i++){
gap = (velgap.ChkData(i) + Vector(1,1) * ServerParam::ball_rand * (velgap.ChkData(i).mod() + gvel.ChkData(i+1).mod()/speed_decay)) * speed_decay;
gap.x = gap.x > max_speed ? max_speed : gap.x;
gap.y = gap.y > max_speed ? max_speed : gap.y;
velgap.Setdata(gap, i+1);
DoLog(LOG_UPDATE,"Estimate velgap (%.3f,%.3f) at %d", velgap.ChkData(i+1).x, velgap.ChkData(i+1).y, i+1);
}
velgap_time = t;
//DoLog(LOG_UPDATE, "Estimate posgap (%.3f,%.3f) at %d(%.2f %.2f %.2f)",posgap.ChkData(posgap_time).x, posgap.ChkData(posgap_time).y, posgap_time, speed_decay, ServerParam::player_rand, ServerParam::player_decay);
for(i = posgap_time; i < t; i++){
posgap.Setdata(posgap.ChkData(i) + velgap.ChkData(i+1)/speed_decay + Vector(1,1) * ServerParam::player_rand * Self.Vel(i+1).mod() / ServerParam::player_decay, i+1);
//DoLog(LOG_UPDATE, "Estimate posgap (%.3f,%.3f) selfvel (%.2f,%.2f) at %d",posgap.ChkData(i+1).x, posgap.ChkData(i+1).y, Self.Vel(i+1).x, Self.Vel(i+1).y, i+1);
}
posgap_time = t;
}
void Ball::update_seen(Time time){
/* What's special about ball's updation?
Collisions, and a more accurate velocity is needed*/
#ifdef _Up_FState
if(sensory.HasFullState() && acc_pos.IsDataKnown(time)){
MobileObject::update_seen(time);
return;
}
#endif
if(!seen) return;
Time last_update_time = Max(update_seen_time, time -2);
Vector predictpos, predictvel;
Vector allowposgap, allowvelgap;
Vector predictpos_gap, predictvel_gap;
int t;
for(t = last_update_time + 1; t <= time; t++){
if(!seenposinfo.IsDataKnown(t)) continue;
estimate(t);
predictpos = Pos(t) - Self.Pos(t);
DoLog(LOG_UPDATE, "estimate relpos %.2f, %.2f", predictpos.x, predictpos.y);
predictvel = Vel(t);
allowposgap = posgap.ChkData(t);
allowvelgap = velgap.ChkData(t);
Time last_seen_time = original_postime;
Time last_seench_time = original_veltime;
MobileObject::update_seen(t);
update_seengap(t);
if(seen_distance(t) > 30.0f) continue;
if (seen_distance(t) > (Self.kickable_area+0.04f)){
Skill::action.ResetKickEffect(t); //then the kick command sent at seen_time must be a fault
}
int postime_gap = t - last_seen_time;
if(postime_gap <= 0){
DoLog(LOG_UPDATE,"why postime_gap = 0? %d", t);
continue;
}
allowposgap += posgap.ChkData(t);
predictpos_gap = Pos(t) - Self.Pos(t) - predictpos;// - Self.SummarizePosGap(last_seen_time, t);
DoLog(LOG_UPDATE,"T gap%d, V gap%d, Predictpos Gap(%.2f,%.2f)", postime_gap, t - last_seench_time, predictpos_gap.x, predictpos_gap.y);
bool selfcoll = Self.SelfColl(last_seen_time+1, t);
float erroridx = 0;
bool PredictError = IsposError(allowposgap, predictpos_gap, erroridx);
if(seenchinfo.IsDataKnown(t)){
allowvelgap += velgap.ChkData(t);
predictvel_gap = Vel(t) - predictvel;
DoLog(LOG_UPDATE,"predictvel Gap(%.2f,%.2f)",predictvel_gap.x,predictvel_gap.y);
float verroridx;
bool PrevelError = IsposError(allowvelgap, predictvel_gap, verroridx);
if(PredictError || PrevelError){
erroridx += verroridx;
DoLog(LOG_UPDATE, "Error Index %.3f",erroridx);
find_kick = true;
}else if(predictvel_gap.mod2() > Sqr(0.3f)){
find_kick = true;
}
error_idx.Setdata(erroridx, t);
continue;
}else if(Self.IsMoved(last_seen_time, t)){
continue;
}
if(predictpos.mod() < ServerParam::ball_size + ServerParam::player_size){
DoLog(LOG_UPDATE, "predict coll, unhandled yet");
}
error_idx.Setdata(erroridx, t);
float sqrconf = max_conf * Sqr(conf_decay);
float CP_collision_maxdis = 0.75f;
if(!PredictError ){
if(postime_gap ==1 && !OtherKick(last_seen_time,t) && velgap.IsDataKnown(t) && (posgap.Data(t).mod() + posgap.Data(t-1).mod()) > velgap.Data(t).mod()){
DoLog(LOG_UPDATE, "estimate maybe more accurate, reset velconf");
speed_conf = max_conf;
//wait for estimate
}else if(selfcoll && postime_gap <= 2){
DoLog(LOG_UPDATE, "self coll, pos still correct fortunately");
//wait for estimate
}else if(!gpos.IsDataKnown(last_seen_time)){
DoLog(LOG_UPDATE, "last pos is lost, have to estimate");
//wait for estimate
}else if(postime_gap<4 && speed_valid()){
ApplyPosbased_vel(last_seen_time,t,max_conf);
}else if(postime_gap<6){
ApplyPosbased_vel(last_seen_time,t,sqrconf);
}else
ApplyPosbased_vel(last_seen_time,t,sqrconf * sqrconf);
if(!selfcoll && postime_gap == 1 && seen_distance(t) < 2.0f){
original_veltime = t - 1;
DoLog(LOG_UPDATE,"Reliable predict vel at %d", t);
}
continue;
}else{
find_kick = true;
DoLog(LOG_UPDATE,"why ball is here, Error Index %.3f at %d", erroridx, t);
}
//unmoved posgap limit;
float dist_moved;
if(gpos.IsDataKnown(last_seen_time)){
dist_moved = (gpos.Data(last_seen_time) + Self.SummarizePosGap(last_seen_time, t)).dist(gpos.Data(t)) - allowposgap.mod();
}else{
dist_moved = predictpos.dist(gpos.Data(t)) - Vel(t).mod() * postime_gap - allowposgap.mod();
}
if(dist_moved > max_speed * postime_gap){
DoLog(LOG_UPDATE,"ball is moved");
gvel.Setdata(0, t);
vel_time = t;
if(postime_gap ==1){
speed_conf = max_conf;
}else if(postime_gap == 2){
speed_conf = sqrconf;
}
}else if(postime_gap ==1){
if(OtherKick(last_seen_time)){
ApplyPosbased_vel(last_seen_time,t,sqrconf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -