Robot 움직임 전략 - 반중력 운동

로그[log]/로보코드 2013. 3. 22. 01:13



파트너스 활동을 통해 일정액의 수수료를 제공받을 수 있음
728x90
'


반중력 운동(Anti-gravity movement)은 유연성이 뛰어난 기술로서 전투장 내에서 피신할 수 있는 특별한 지점 (중력 지점-gravity points)을 정의하여 패턴 분석 로봇을 혼란에 빠트린다. 각각의 중력 지점(gravity point)은 세기(strength)에 따라 할당된다. x와 y의 방향에서 세기의 요소를 결정하여 모든 적군 로봇을 피할 수 있다. ("반중력(Anti-gravity) 용어정리" 참조)


반중력 운동의 수학원리

반중력에 내포된 수학은 실제로 매우 간단하다. 삼각법만 알면 된다.

그림 1에서 "F"라는 화살은 Crazy로 부터 AntiGravityBot에 가해지는 힘의 방향을 나타낸다. 힘은 다른 두 개의 화살에서 보이듯이 x와 y에 있는 컴포넌트로 간주될 수 있다. 힘을 결정하여 x와 y 방향의 모든 중력 지점에서 모든 힘을 한데 모을 수 있다 .


반중력(Anti-gravity) 용어정리


중력 지점(Gravity points):
공격하기 원하는 장소로 정의된 Robocode 전투장 내의 장소들.

힘(Forces): 각각의 중력 지점은 힘(force) 또는 세기(strength)를 할당 받는다. 값이 클수록 로봇은 그 지점에서 힘을 만들어 내면서 공격할 수 있다.

힘의 컴포넌트: 각각의 힘은 x (수평) 방향과 , y (수직) 방향에서 작동하는 컴포넌트를 갖고있다. 45도 각도는 x와 y 방향에서 동등한 컴포넌트를 갖고있다. 90도 각도는 x 방향에서 전적으로 작동한다.

힘 결정하기: 여러 힘들이 작동할 때 만들어진 모든 힘을 산정하는 과정이다. 예를 들어 x 방향에서 작동하는 -200의 힘이 있고 또한 x 방향에서 300의 힘이 있다면 만들어진 힘의 전체는 100이다.

로봇이 멀리있는 로봇에 의해 영향받지 않도록 하려면, 세기(strength)가 중력 지점의 힘이고 거리(distance)가 중력 지점과 로봇 사이의 거리인 곳에서 force = strength/Math.pow(distance,2) 함수를 사용하여 중력 지점으로부터 로봇에 가해지는 힘을 계산해야한다.


코드
다음 코드는 기본적인 시스템 코드이다. Listing 1은 반중력의 주요 함수를 보여주고 있다. 한 벡터 내에서 모든 중력 지점을 통해 순환하고 힘을 결정하며 정확한 방향으로 로봇을 움직인다. 적군 로봇들이 격퇴 지점에 가있도록 할 것을 권장하는 바이다. 이렇게 하려면 전투장 모양을 항상 업데이트 해야한다.


Listing 1.반중력의 일꾼: antiGravMove()

void antiGravMove() {
    double xforce = 0;
    double yforce = 0;
    double force;
    double ang;
    GravPoint p;
    
    for(int i = 0;i<gravpoints.size();i++) {
        p = (GravPoint)gravpoints.elementAt(i);
        //Calculate the total force from this point on us
        force = p.power/Math.pow(getRange(getX(),getY(),p.x,p.y),2);
        //Find the bearing from the point to us
        ang = 
    normaliseBearing(Math.PI/2 - Math.atan2(getY() - p.y, getX() - p.x)); 
        //Add the components of this force to the total force in their 
        //respective directions
        xforce += Math.sin(ang) * force;
        yforce += Math.cos(ang) * force;
    }
    
    /**The following four lines add wall avoidance.  They will only 
    affect us if the bot is close to the walls due to the
    force from the walls decreasing at a power 3.**/
    xforce += 5000/Math.pow(getRange(getX(), 
      getY(), getBattleFieldWidth(), getY()), 3);
    xforce -= 5000/Math.pow(getRange(getX(), 
      getY(), 0, getY()), 3);
    yforce += 5000/Math.pow(getRange(getX(), 
      getY(), getX(), getBattleFieldHeight()), 3);
    yforce -= 5000/Math.pow(getRange(getX(), 
      getY(), getX(), 0), 3);
    
    //Move in the direction of our resolved force.
    goTo(getX()-xforce,getY()-yforce);
}

Listing 2의 helper 메소드는 가장 효율적인 방법으로 어떤 지점으로 움직일 수 있도록 하면서 로봇과 적군로봇 사이의 거리를 두도록 한다.


Listing 2. Helper 메소드

/**Move in the direction of an x and y coordinate**/
void goTo(double x, double y) {
    double dist = 20; 
    double angle = Math.toDegrees(absbearing(getX(),getY(),x,y));
    double r = turnTo(angle);
    setAhead(dist * r);
}

/**Turns the shortest angle possible to come to a heading, then returns 
the direction the bot needs to move in.**/
int turnTo(double angle) {
    double ang;
    int dir;
    ang = normalisebearing(getHeading() - angle);
    if (ang > 90) {
        ang -= 180;
        dir = -1;
    }
    else if (ang < -90) {
        ang += 180;
        dir = -1;
    }
    else {
        dir = 1;
    }
    setTurnLeft(ang);
    return dir;
}

/**/Returns the distance between two points**/
double getRange(double x1,double y1, double x2,double y2) {
    double x = x2-x1;
    double y = y2-y1;
    double range = Math.sqrt(x*x + y*y);
    return range;	
}

마지막으로, Listing 3에서 GravPoint 클래스를 볼 수 있는데 이것은 중력 지점에 대해 우리가 필요로하는 모든 데이터를 보유하고 있다. 격퇴하기 위해서는 power는 마이너스(-)가 되어야한다.


Listing 3. GravPoint class

class GravPoint {
    public double x,y,power;
    public GravPoint(double pX,double pY,double pPower) {
        x = pX;
        y = pY;
        power = pPower;
    }
}

출처: http://www.ibm.com/developerworks/kr/library/j-antigrav/

 

'

 

728x90