Continuous Goal in Malmo

Malmo is the Microsoft AI platform for Minecraft, consisting of a mod for the game itself and a multi-platform platform for sending inputs and receiving data about the world.

Minecraft's aspiration is cylindrical. It is stored in yaw (left and right) and step (up and down) instead of a full quaternion of rotation. Yaw goes from -180 degrees in the far left corner and wraps up to 180 in the far right corner. The step goes from -90, pointing straight up (zenith) 90 down (nadir). In my code, I save them as Vector2(recreated to work just like XNA), so X represents Yaw and Y represents Pitch.

I’m having problems creating a continuous targeting algorithm, so that the AI ​​can aim its camera at a given jerk and step. Since the only way to do this while maintaining continuous movement is to aim continuously (to set the yaw rate and pitch, and not the values), I need to repeatedly increase the yaw and feed in the direction of the target.

I do this by keeping the destination direction in the nullable property. If the property is NULL, this means that the target cannot be changed. Otherwise, subtract the distance between the saved value (target) and the current target (supplied via the parameter) each time the update method is called. Then it scales the difference, so either the yaw or the step is 1 (maximum speed), and the other is the correct proportion for this. This proportional speed Vector2is divided by its yaw and step, and then sent to the client using the turnand commands pitch. Once within 10 degrees of the target direction, the target is set to zero.

On paper, it seems that this would make the camera’s aim directed directly toward the target (excluding yaw). However, the client’s step usually goes directly beyond the target direction, despite the fact that the update method sends a command pitchthat says that it goes in the opposite direction. This means that the step somehow “gets stuck” at the zenith and nadir, but fixes itself and “turns” and is stuck at the opposite pole after a couple of seconds. The amount of time spent stuck before a turn seems to increase exponentially (or perhaps quadratically) each time.

Here is the source code of my target update method:

public void UpdateAim(Observations obs)
{
    // AimTarget is a Vector2? property
    if (AimTarget == null || obs == null)
    {
        return;
    }

    if (AimTarget.Value.Distance(obs.Aim) < AIM_CLOSE_ENOUGH) // < 10
    {
        Logger.LogInfo("Reached {0}", AimTarget.Value);
        Look(Vector2.Zero);
        AimTarget = null;
        return;
    }

    double deltaYaw = AimTarget.Value.X - obs.Aim.X;
    double deltaPitch = AimTarget.Value.Y - obs.Aim.Y;

    // These two are stored as private Vector2 fields
    deltaAim = new Vector2(deltaYaw, deltaPitch);
    scaledAim = deltaAim / Math.Max(Math.Abs(deltaAim.X), Math.Abs(deltaAim.Y));

    Look(scaledAim); // sets continuous aim velocity
}

And (simplified) source code Look(Vector2):

public void Look(Vector2 direction)
{
    // Agent is an AgentHost property
    Agent.sendCommand("turn " + velocity);
    Agent.sendCommand("pitch " + velocity);
}

UpdateAim() called 20 times per second (although I tried up to 50 times per second and only 5) during the main game cycle.

AI ( ), :

// Format: (yaw, pitch)
Target Aim: (134.75, 27.90)
Actual In-Game Aim: (-6.50, 90.00) // Lines up with MC debug screen
Delta Aim :  (145.17, -62.10) // Total degrees needed to go in yaw and pitch
Scaled Aim Velocity: (1.00, -0.43)

- , Look(). , , , 90 - . ?

+4
2

, , . nadir , Agent.sendCommand, .

, , , , ​​? ? , ?

+1

, , , , :

  • Look() :

    Agent.sendCommand("turn " + velocity);
    Agent.sendCommand("pitch " + velocity);
    

, velocity - , SO? , , .

  1. - , - ? Math.Max(Math.Abs(deltaAim.X), Math.Abs(deltaAim.Y))? ( ) , , - , .

  2. /. , (deltaYaw == 0). , - (1 -1 ). , 0,0001, . (, AIM_CLOSE_ENOUGH , , , turnSpeedDegs - . http://microsoft.imtqy.com/malmo/0.17.0/Schemas/MissionHandlers.html#element_ContinuousMovementCommands)

cart_test.py - https://github.com/Microsoft/malmo/blob/master/Malmo/samples/Python_examples/cart_test.py

. yaw_to_mob - , yaw - .

# Find shortest angular distance between the two yaws, preserving sign:
deltaYaw = yaw_to_mob - yaw
while deltaYaw < -180:
    deltaYaw += 360;
while deltaYaw > 180:
    deltaYaw -= 360;
deltaYaw /= 180.0;
# And turn:
agent_host.sendCommand("turn " + str(deltaYaw))

, , MazeRunner.py( , cart_test.py), turnSpeedDegs . Minecraft / , , .

+1

Source: https://habr.com/ru/post/1648071/


All Articles