Example #1
0
/*!

*/
Vector2D
Segment2D::projection( const Vector2D & p ) const
{
    Vector2D dir = terminal() - origin();
    double len = dir.r();

    if ( len < EPSILON )
    {
        return origin();
    }

    dir /= len; // normalize

    double d = dir.innerProduct( p - origin() );
    if ( -EPSILON < d && d < len + EPSILON )
    {
        dir *= d;
        return Vector2D( origin() ) += dir;
    }

    return Vector2D::INVALIDATED;

#if 0
    Line2D my_line = this->line();
    Vector2D sol = my_line.projection( p );

    if ( ! sol.isValid()
         || ! this->contains( sol ) )
    {
        return Vector2D::INVALIDATED;
    }

    return sol;
#endif
}
Example #2
0
/*!

 */
bool
Segment2D::onSegmentWeakly( const Vector2D & p ) const
{
    Vector2D proj = projection( p );

    return ( proj.isValid()
             && p.equalsWeakly( proj ) );

#if 0
    Vector2D o = origin();
    Vector2D t = terminal();

    const double buf = ( allow_on_terminal
                         ? EPSILON
                         : 0.0 );

    if ( std::fabs( ( t - o ).outerProduct( p - o ) ) < EPSILON )
    {
        if ( std::fabs( o.x - t.x ) < EPSILON )
        {
            return ( ( o.y - buf < p.y && p.y < t.y + buf )
                     || ( t.y - buf < p.y && p.y < o.y + buf ) );
        }
        else
        {
            return ( ( o.x - buf < p.x && p.x < t.x + buf )
                     || ( t.x - buf < p.x && p.x < o.x + buf) );
        }
    }

    return false;
#endif
}
Example #3
0
/*!

*/
Vector2D
Segment2D::intersection( const Segment2D & other,
                         const bool allow_end_point ) const
{
    Vector2D sol = this->line().intersection( other.line() );

    if ( ! sol.isValid()
         || ! this->contains( sol )
         || ! other.contains( sol ) )
    {
        return Vector2D::INVALIDATED;
    }

    if ( ! allow_end_point
         && ! existIntersectionExceptEndpoint( other ) )
    {
        return Vector2D::INVALIDATED;
    }

    return sol;

#if 0
    // Following algorithm seems faster ther above.
    // In fact, the following algorithm slower...

    Vector2D ab = terminal() - origin();
    Vector2D dc = other.origin() - other.terminal();
    Vector2D ad = other.terminal() - origin();

    double det = dc.outerProduct( ab );

    if ( std::fabs( det ) < 1.0e-9 )
    {
        // area size is 0.
        // segments has same slope.
        std::cerr << "Segment2D::intersection()"
                  << " ***ERROR*** parallel segments"
                  << std::endl;
        return Vector2D::INVALIDATED;
    }

    double s = ( dc.x * ad.y - dc.y * ad.x ) / det;
    double t = ( ab.x * ad.y - ab.y * ad.x ) / det;

    if ( s < 0.0 || 1.0 < s || t < 0.0 || 1.0 < t )
    {
        return Vector2D::INVALIDATED;
    }

    return Vector2D( origin().x + ab.x * s, origin().y + ab.y * s );
#endif
}
Example #4
0
/*!

*/
Vector2D
Segment2D::intersection( const Line2D & l ) const
{
    Line2D my_line = this->line();

    Vector2D sol = my_line.intersection( l );

    if ( ! sol.isValid()
         || ! this->contains( sol ) )
    {
        return Vector2D::INVALIDATED;
    }

    return sol;
}
/*!

 */
bool
Bhv_PenaltyKick::doGoalieSlideChase( PlayerAgent* agent )
{
    const WorldModel & wm = agent->world();

    if ( std::fabs( 90.0 - wm.self().body().abs() ) > 2.0 )
    {
        Vector2D face_point( wm.self().pos().x, 100.0);
        if ( wm.self().body().degree() < 0.0 )
        {
            face_point.y = -100.0;
        }
        Body_TurnToPoint( face_point ).execute( agent );
        agent->setNeckAction( new Neck_TurnToBall() );
        return true;
    }

    Ray2D ball_ray( wm.ball().pos(), wm.ball().vel().th() );
    Line2D ball_line( ball_ray.origin(), ball_ray.dir() );
    Line2D my_line( wm.self().pos(), wm.self().body() );

    Vector2D intersection = my_line.intersection( ball_line );
    if ( ! intersection.isValid()
         || ! ball_ray.inRightDir( intersection ) )
    {
        Body_Intercept( false ).execute( agent ); // goalie mode
        agent->setNeckAction( new Neck_TurnToBall() );
        return true;
    }

    if ( wm.self().pos().dist( intersection )
         < ServerParam::i().catchAreaLength() * 0.7 )
    {
        Body_StopDash( false ).execute( agent ); // not save recovery
        agent->setNeckAction( new Neck_TurnToBall() );
        return true;
    }

    AngleDeg angle = ( intersection - wm.self().pos() ).th();
    double dash_power = ServerParam::i().maxDashPower();
    if ( ( angle - wm.self().body() ).abs() > 90.0 )
    {
        dash_power = ServerParam::i().minDashPower();
    }
    agent->doDash( dash_power );
    agent->setNeckAction( new Neck_TurnToBall() );
    return true;
}
Example #6
0
/*!

 */
Circle2D
Circle2D::circumcircle( const Vector2D & p0,
                        const Vector2D & p1,
                        const Vector2D & p2 )
{
    Vector2D center = Triangle2D::circumcenter( p0, p1, p2 );

    if ( ! center.isValid() )
    {
        std::cerr << "Circle2D::circumcircle()"
                  << " ***ERROR*** failed to get circumcenter from "
                  << p0 << p1 << p2
                  << std::endl;
        return Circle2D();
    }

    return Circle2D( center, center.dist( p0 ) );
}
/*!
  ball_pos & my_pos is set to self localization oriented.
  if ( onfiled_side != our_side ), these coordinates must be reversed.
*/
Vector2D
Bhv_PenaltyKick::getGoalieMovePos( const Vector2D & ball_pos,
                                   const Vector2D & my_pos )
{
    const ServerParam & SP = ServerParam::i();
    const double min_x = -SP.pitchHalfLength() + SP.catchAreaLength()*0.9;

    if ( ball_pos.x < -49.0 )
    {
        if ( ball_pos.absY() < SP.goalHalfWidth() )
        {
            return Vector2D( min_x, ball_pos.y );
        }
        else
        {
            return Vector2D( min_x,
                             sign( ball_pos.y ) * SP.goalHalfWidth() );
        }
    }

    Vector2D goal_l( -SP.pitchHalfLength(), -SP.goalHalfWidth() );
    Vector2D goal_r( -SP.pitchHalfLength(), +SP.goalHalfWidth() );

    AngleDeg ball2post_angle_l = ( goal_l - ball_pos ).th();
    AngleDeg ball2post_angle_r = ( goal_r - ball_pos ).th();

    // NOTE: post_angle_r < post_angle_l
    AngleDeg line_dir = AngleDeg::bisect( ball2post_angle_r,
                                          ball2post_angle_l );

    Line2D line_mid( ball_pos, line_dir );
    Line2D goal_line( goal_l, goal_r );

    Vector2D intersection = goal_line.intersection( line_mid );
    if ( intersection.isValid() )
    {
        Line2D line_l( ball_pos, goal_l );
        Line2D line_r( ball_pos, goal_r );

        AngleDeg alpha = AngleDeg::atan2_deg( SP.goalHalfWidth(),
                                              SP.penaltyAreaLength() - 2.5 );
        double dist_from_goal
            = ( ( line_l.dist( intersection ) + line_r.dist( intersection ) ) * 0.5 )
            / alpha.sin();

        dlog.addText( Logger::TEAM,
                      __FILE__": goalie move. intersection=(%.1f, %.1f) dist_from_goal=%.1f",
                      intersection.x, intersection.y, dist_from_goal );
        if ( dist_from_goal <= SP.goalHalfWidth() )
        {
            dist_from_goal = SP.goalHalfWidth();
            dlog.addText( Logger::TEAM,
                          __FILE__": goalie move. outer of goal. dist_from_goal=%.1f",
                          dist_from_goal );
        }

        if ( ( ball_pos - intersection ).r() + 1.5 < dist_from_goal )
        {
            dist_from_goal = ( ball_pos - intersection ).r() + 1.5;
            dlog.addText( Logger::TEAM,
                          __FILE__": goalie move. near than ball. dist_from_goal=%.1f",
                          dist_from_goal );
        }

        AngleDeg position_error = line_dir - ( intersection - my_pos ).th();

        const double danger_angle = 21.0;
        dlog.addText( Logger::TEAM,
                      __FILE__": goalie move position_error_angle=%.1f",
                      position_error.degree() );
        if ( position_error.abs() > danger_angle )
        {
            dist_from_goal *= ( ( 1.0 - ((position_error.abs() - danger_angle)
                                         / (180.0 - danger_angle)) )
                                * 0.5 );
            dlog.addText( Logger::TEAM,
                          __FILE__": goalie move. error is big. dist_from_goal=%.1f",
                          dist_from_goal );
        }

        Vector2D result = intersection;
        Vector2D add_vec = ball_pos - intersection;
        add_vec.setLength( dist_from_goal );
        dlog.addText( Logger::TEAM,
                      __FILE__": goalie move. intersection=(%.1f, %.1f) add_vec=(%.1f, %.1f)%.2f",
                      intersection.x, intersection.y,
                      add_vec.x, add_vec.y,
                      add_vec.r() );
        result += add_vec;
        if ( result.x < min_x )
        {
            result.x = min_x;
        }
        return result;
    }
    else
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": goalie move. shot line has no intersection with goal line" );

        if ( ball_pos.x > 0.0 )
        {
            return Vector2D(min_x , goal_l.y);
        }
        else if ( ball_pos.x < 0.0 )
        {
            return Vector2D(min_x , goal_r.y);
        }
        else
        {
            return Vector2D(min_x , 0.0);
        }
    }
}
Example #8
0
/*!
  execute action
*/
bool
Bhv_GoalieChaseBall::execute( PlayerAgent * agent )
{
    dlog.addText( Logger::TEAM,
                  __FILE__": Bhv_GoalieChaseBall" );

    //////////////////////////////////////////////////////////////////
    // tackle
    if ( Bhv_BasicTackle( 0.8, 90.0 ).execute( agent ) )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": tackle" );
        return true;
    }

    const ServerParam & SP = ServerParam::i();
    const WorldModel & wm = agent->world();

    ////////////////////////////////////////////////////////////////////////
    // get active interception catch point

    Vector2D my_int_pos = wm.ball().inertiaPoint( wm.interceptTable()->selfReachCycle() );
    dlog.addText( Logger::TEAM,
                  __FILE__": execute. intercept point=(%.2f %.2f)",
                  my_int_pos.x, my_int_pos.y );

    double pen_thr = wm.ball().distFromSelf() * 0.1 + 1.0;
    if ( pen_thr < 1.0 ) pen_thr = 1.0;

    //----------------------------------------------------------
    const Line2D ball_line( wm.ball().pos(), wm.ball().vel().th() );
    const Line2D defend_line( Vector2D( wm.self().pos().x, -10.0 ),
                              Vector2D( wm.self().pos().x, 10.0 ) );

    if ( my_int_pos.x > - SP.pitchHalfLength() - 1.0
         && my_int_pos.x < SP.ourPenaltyAreaLineX() - pen_thr
         && my_int_pos.absY() < SP.penaltyAreaHalfWidth() - pen_thr )
    {
        bool save_recovery = false;
        if ( ball_line.dist( wm.self().pos() ) < SP.catchableArea() )
        {
            save_recovery = true;
        }
        dlog.addText( Logger::TEAM,
                      __FILE__": execute normal intercept" );
        agent->debugClient().addMessage( "Intercept(0)" );
        Body_Intercept( save_recovery ).execute( agent );
        agent->setNeckAction( new Neck_TurnToBall() );
        return true;
    }

    int self_goalie_min = wm.interceptTable()->selfReachCycle();
    int opp_min_cyc = wm.interceptTable()->opponentReachCycle();

    Vector2D intersection = ball_line.intersection( defend_line );
    if ( ! intersection.isValid()
         || ball_line.dist( wm.self().pos() ) < SP.catchableArea() * 0.8
         || intersection.absY() > SP.goalHalfWidth() + 3.0
         )
    {
        if ( ! wm.existKickableOpponent() )
        {
            if ( self_goalie_min <= opp_min_cyc + 2
                 && my_int_pos.x > -SP.pitchHalfLength() - 2.0
                 && my_int_pos.x < SP.ourPenaltyAreaLineX() - pen_thr
                 && my_int_pos.absY() < SP.penaltyAreaHalfWidth() - pen_thr
                 )
            {
                if ( Body_Intercept( false ).execute( agent ) )
                {
                    dlog.addText( Logger::TEAM,
                                  __FILE__": execute normal interception" );
                    agent->debugClient().addMessage( "Intercept(1)" );
                    agent->setNeckAction( new Neck_TurnToBall() );
                    return true;
                }
            }

            dlog.addText( Logger::TEAM,
                          __FILE__": execute. ball vel has same slope to my body??"
                          " myvel-ang=%f body=%f. go to ball direct",
                          wm.ball().vel().th().degree(),
                          wm.self().body().degree() );
            // ball vel angle is same to my body angle
            agent->debugClient().addMessage( "GoToCatch(1)" );
            doGoToCatchPoint( agent, wm.ball().pos() );
            return true;
        }
    }

    //----------------------------------------------------------
    // body is already face to intersection
    // only dash to intersection

    // check catch point
    if ( intersection.absX() > SP.pitchHalfLength() + SP.catchableArea()
         || intersection.x > SP.ourPenaltyAreaLineX() - SP.catchableArea()
         || intersection.absY() > SP.penaltyAreaHalfWidth() - SP.catchableArea()
         )
    {
        dlog.addText( Logger::TEAM,
                      __FILE__": execute intersection(%.2f, %.2f) over range.",
                      intersection.x, intersection.y );
        if ( Body_Intercept( false ).execute( agent ) )
        {
            agent->debugClient().addMessage( "Intercept(2)" );
            agent->setNeckAction( new Neck_TurnToBall() );
            return true;
        }
        else
        {
            return Bhv_GoalieBasicMove().execute( agent );
        }
    }

    //----------------------------------------------------------
    // check already there
    const Vector2D my_inertia_final_pos
        = wm.self().pos()
        + wm.self().vel()
        / (1.0 - wm.self().playerType().playerDecay());
    double dist_thr = 0.2 + wm.ball().distFromSelf() * 0.1;
    if ( dist_thr < 0.5 ) dist_thr = 0.5;

    // if already intersection point stop dash
    if ( my_inertia_final_pos.dist( intersection ) < dist_thr )
    {
        agent->debugClient().addMessage( "StopForChase" );
        Body_StopDash( false ).execute( agent );
        agent->setNeckAction( new Neck_TurnToBall() );
        return true;
    }

    //----------------------------------------------------------
    // forward or backward

    dlog.addText( Logger::TEAM,
                  __FILE__": slide move. point=(%.1f, %.1f)",
                  intersection.x, intersection.y );
    if ( wm.ball().pos().x > -35.0 )
    {
        if ( wm.ball().pos().y * intersection.y < 0.0 ) // opposite side
        {
            intersection.y = 0.0;
        }
        else
        {
            intersection.y *= 0.5;
        }
    }

    agent->debugClient().addMessage( "GoToCatch(2)" );
    doGoToCatchPoint( agent, intersection );
    return true;
}
/*!

 */
double
TackleGenerator::evaluate( const WorldModel & wm,
                           const TackleResult & result )
{
    const ServerParam & SP = ServerParam::i();

    const Vector2D ball_end_point = inertia_final_point( wm.ball().pos(),
                                                         result.ball_vel_,
                                                         SP.ballDecay() );
    const Segment2D ball_line( wm.ball().pos(), ball_end_point );
    const double ball_speed = result.ball_speed_;
    const AngleDeg ball_move_angle = result.ball_move_angle_;

#ifdef DEBUG_PRINT
    dlog.addText( Logger::CLEAR,
                  "(evaluate) angle=%.1f speed=%.2f move_angle=%.1f end_point=(%.2f %.2f)",
                  result.tackle_angle_.degree(),
                  ball_speed,
                  ball_move_angle.degree(),
                  ball_end_point.x, ball_end_point.y );
#endif

    //
    // moving to their goal
    //
    if ( ball_end_point.x > SP.pitchHalfLength()
         && wm.ball().pos().dist2( SP.theirTeamGoalPos() ) < std::pow( 20.0, 2 ) )
    {
        const Line2D goal_line( Vector2D( SP.pitchHalfLength(), 10.0 ),
                                Vector2D( SP.pitchHalfLength(), -10.0 ) );
        const Vector2D intersect = ball_line.intersection( goal_line );
        if ( intersect.isValid()
             && intersect.absY() < SP.goalHalfWidth() )
        {
            double shoot_score = 1000000.0;
            double speed_rate = 1.0 - std::exp( - std::pow( ball_speed, 2 )
                                                / ( 2.0 * std::pow( SP.ballSpeedMax()*0.5, 2 ) ) );
            double y_rate = std::exp( - std::pow( intersect.absY(), 2 )
                                      / ( 2.0 * std::pow( SP.goalWidth(), 2 ) ) );
            shoot_score *= speed_rate;
            shoot_score *= y_rate;
#ifdef DEBUG_PRINT
            dlog.addText( Logger::CLEAR,
                          "__ shoot %f (speed_rate=%f y_rate=%f)",
                          shoot_score, speed_rate, y_rate );
#endif
            return shoot_score;
        }
    }

    //
    // moving to our goal
    //
    if ( ball_end_point.x < -SP.pitchHalfLength() )
    {
        const Line2D goal_line( Vector2D( -SP.pitchHalfLength(), 10.0 ),
                                Vector2D( -SP.pitchHalfLength(), -10.0 ) );
        const Vector2D intersect = ball_line.intersection( goal_line );
        if ( intersect.isValid()
             && intersect.absY() < SP.goalHalfWidth() + 1.0 )
        {
            double shoot_score = 0.0;
            double y_penalty = ( -10000.0
                                 * std::exp( - std::pow( intersect.absY() - SP.goalHalfWidth(), 2 )
                                             / ( 2.0 * std::pow( SP.goalHalfWidth(), 2 ) ) ) );
            double speed_bonus = ( +10000.0
                                   * std::exp( - std::pow( ball_speed, 2 )
                                               / ( 2.0 * std::pow( SP.ballSpeedMax()*0.5, 2 ) ) ) );
            shoot_score = y_penalty + speed_bonus;
#ifdef DEBUG_PRINT
            dlog.addText( Logger::CLEAR,
                          "__ in our goal %f (y_pealty=%f speed_bonus=%f)",
                          shoot_score, y_penalty, speed_bonus );
#endif
            return shoot_score;
        }
    }

    //
    // normal evaluation
    //

    int opponent_reach_step = predictOpponentsReachStep( wm,
                                                         wm.ball().pos(),
                                                         result.ball_vel_,
                                                         ball_move_angle );
    Vector2D final_point = inertia_n_step_point( wm.ball().pos(),
                                                 result.ball_vel_,
                                                 opponent_reach_step,
                                                 SP.ballDecay() );
    {
        Segment2D final_segment( wm.ball().pos(), final_point );
        Rect2D pitch = Rect2D::from_center( 0.0, 0.0, SP.pitchLength(), SP.pitchWidth() );
        Vector2D intersection;
        int n = pitch.intersection( final_segment, &intersection, NULL );
        if ( n > 0 )
        {
            final_point = intersection;
        }
    }

#if 1

    AngleDeg our_goal_angle = ( SP.ourTeamGoalPos() - wm.ball().pos() ).th();
    double our_goal_angle_diff = ( our_goal_angle - ball_move_angle ).abs();
    double our_goal_angle_rate = 1.0 - std::exp( - std::pow( our_goal_angle_diff, 2 )
                                                 / ( 2.0 * std::pow( 40.0, 2 ) ) );

    double y_rate = ( final_point.absY() > SP.pitchHalfWidth() - 0.1
                      ? 1.0
                      : std::exp( - std::pow( final_point.absY() - SP.pitchHalfWidth(), 2 )
                                  / ( 2.0 * std::pow( SP.pitchHalfWidth() * 0.7, 2 ) ) ) );
    double opp_rate = 1.0 - std::exp( - std::pow( (double)opponent_reach_step, 2 )
                                      / ( 2.0 * std::pow( 30.0, 2 ) ) );

    double score = 10000.0 * our_goal_angle_rate * y_rate * opp_rate;

#ifdef DEBUG_PRINT
    dlog.addText( Logger::CLEAR,
                  "__ goal_angle_rate=%f",
                  our_goal_angle_rate, y_rate, score );
    dlog.addText( Logger::CLEAR,
                  "__ y_rate=%f",
                  our_goal_angle_rate, y_rate, score );
    dlog.addText( Logger::CLEAR,
                  "__ opp_rate=%f",
                  opp_rate );

    dlog.addText( Logger::CLEAR,
                  ">>> score=%f",
                  score );
#endif

    return score;

#else

    double x_val = ( final_point.x > SP.pitchHalfLength()
                     ? 1.0
                     : std::exp( - std::pow( final_point.x - SP.pitchHalfLength(), 2 )
                                 / ( 2.0 * std::pow( SP.pitchLength() * 0.4, 2 ) ) ) );
    double y_val = ( final_point.absY() > SP.pitchHalfWidth()
                     ? 1.0
                     : std::exp( - std::pow( final_point.absY() - SP.pitchHalfWidth(), 2 )
                                 / ( 2.0 * std::pow( SP.pitchHalfWidth() * 0.7, 2 ) ) ) );


    double opp_goal_dist = SP.theirTeamGoalPos().dist( final_point );
    double opp_goal_dist_val = std::exp( - std::pow( opp_goal_dist, 2 )
                                         / ( 2.0 * std::pow( 20.0, 2 ) ) );

    double our_goal_dist = SP.ourTeamGoalPos().dist( final_point );
    double our_goal_dist_rate = 1.0 - std::exp( - std::pow( our_goal_dist, 2 )
                                                / ( 2.0 * std::pow( 20.0, 2 ) ) );


    double opp_rate = 1.0 - std::exp( - std::pow( (double)opponent_reach_step, 2 )
                                      / ( 2.0 * std::pow( 30.0, 2 ) ) );

    double score = 0.0;

    score += 1000.0 * x_val;
#ifdef DEBUG_PRINT
    dlog.addText( Logger::CLEAR,
                  "__ x_val %f (%f)", 10000.0 * x_val, score );
#endif

    score += 1000.0 * y_val;
#ifdef DEBUG_PRINT
    dlog.addText( Logger::CLEAR,
                  "__ y_val %f (%f)", 1000.0 * y_val, score );
#endif

    score += 1000.0 * opp_goal_dist_val;
#ifdef DEBUG_PRINT
    dlog.addText( Logger::CLEAR,
                  "__ opp_goal_dist_val %f (%f)", 1000.0 * opp_goal_dist_val, score );
#endif

    score *= our_goal_dist_rate;
#ifdef DEBUG_PRINT
    dlog.addText( Logger::CLEAR,
                  "__ our_goal_dist=%.2f rate=%f (%f)",
                  our_goal_dist, our_goal_dist_rate, score );
#endif

    score *= opp_rate;
#ifdef DEBUG_PRINT
    dlog.addText( Logger::CLEAR,
                  "__ opponent_reach_step=%d rate=%f (%f)",
                  opponent_reach_step, opp_rate, score );
#endif

    return score;

#endif
}