microsoft / AirSim

Open source simulator for autonomous vehicles built on Unreal Engine / Unity, from Microsoft AI & Research
https://microsoft.github.io/AirSim/
Other
16.06k stars 4.48k forks source link

Multirotor Y-axis drift but not X-axis #4780

Open WreckItTim opened 1 year ago

WreckItTim commented 1 year ago

Bug report

What's the issue you encountered?

I was doing some RL training, and noticed a drift in some of the episodes. I wrote some test script to isolate the problem and found that there is some odd behavior that happens only along the Y-axis. This is causing the drift, but not apparent along the X-axis.

I added a YouTube video showing the problem: https://youtu.be/Nwjk_-ua3K4 Also below is the test script you can use to repeat the isolated problem and tinker with it yourself.

Settings

{ 'ClockSpeed': 8, "SimMode": "Multirotor", "ViewMode": "SpringArmChase", "SubWindows": [] }

How can the issue be reproduced?

I made this script to just plug and play and repeat error. Run this python script (replacing as needed to launch configuration). I used the v1.8.1 Blocks release on Windows and dropped the parent folder in the same folder as the bellow python script file, along with setup_path.py. After launching, you can use the terminal to input commands.

  1. Enter 'y' to line up with the y-axis then 'f' to move forward. Watch. After moving, the drone will begin to spin in a slow circle. Press 'f' to go forward again. The circle will make the movement forward look like a drift.
  2. Now enter 'x' to line up with the x-axis then 'f' to move forward. Watch. The drone will not spin in a circle. Press 'f' to go forward again, no apparent drift.
  3. Line up with the y-axis again and go forward. The same spin and drift will reappear!
  4. Repeat as much as you want to make sure you're not crazy.

Note that reducing the clock speed will have the same bug but it will be slower and harder to see, but trust me it is still there if you look close enough.

import subprocess
import setup_path
import airsim
import json
import os

release_path = 'Blocks/WindowsNoEditor/Blocks.exe'

flags = '-Windowed'

settings = {
  'ClockSpeed': 8,
  "SimMode": "Multirotor",
  "ViewMode": "SpringArmChase",
  "SubWindows": []
}
settings_path = os.getcwd() + '/settings.json'
json.dump(settings, open(settings_path, 'w'), indent=2)

terminal_command = f'{release_path} {flags} -settings=\"{settings_path}\"'
process = subprocess.Popen(terminal_command, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)

print('send any key when ready...')
x = input()

client = airsim.MultirotorClient()
client.confirmConnection()
client.enableApiControl(True)
client.armDisarm(True)
client.takeoffAsync().join()
client.moveByVelocityAsync(0, 0, -1, 2).join()

facing = ''

def rotate_to(yaw):
    client.rotateToYawAsync(yaw) 

def move(x_speed, y_speed, z_speed, duration):
    client.moveByVelocityAsync(x_speed, y_speed, z_speed, duration).join()

while True:
    print('x to rotate facing x-axis')
    print('y to rotate facing y-axis')
    print('f to move forward')
    response = input()
    if response not in ['x', 'y', 'f']:
        print('invalid input')
        continue
    if response == 'x':
        rotate_to(180)
        facing = 'x'
    if response == 'y':
        rotate_to(270)
        facing = 'y'
    if response == 'f':
        if facing == 'x':
            move(-2, 0, 0, 2)
        elif facing == 'y':
            move(0, -2, 0, 2)
        else:
            print('must enter x or y first')

Include full error message in text form

no error message

What's better than filing an issue? Filing a pull request :).

edit* (did some debugging and found a stop-gap / narrowed down the problem) I am trying to get some results for my RL research from this asap (have a paper deadline). So I'd be thrilled to just find a stop-gap for the moment, even until a full fix is found. So I did some trial and error tonight....

I have tried the following, but get the same bug:

  1. different map release (AirSimNH)
  2. clockspeed=1
  3. default settings
  4. different PID gains as suggested by https://github.com/microsoft/AirSim/issues/2851
  5. fetching collision info as suggested by https://github.com/microsoft/AirSim/issues/2852
  6. not windowed mode (no flags or settings file passed into command line)
  7. launching Blocks separately from script, then only running control script
  8. using moveToPositionAsync().join()
  9. not using .join()
  10. facing the y-axis but moving along the x-axis

Number 10 gave me the stop-gap I needed! Rotate yaw to face the x-axis, move to desired position, rotate back to original yaw. Works for the moment, LOL!

WreckItTim commented 1 year ago

Found that a better stop-gap is to either sleep until oscillations stop (expensive) or force the velocity of the drone to 0 in all dims, by adding something like this to where it is needed in your code:

# stabalize drone
if stabelize:
    self._airsim._client.rotateByYawRateAsync(0, 0.1)
    self._airsim._client.moveByVelocityAsync(0, 0, 0, 0.1).join()
sandilyasg commented 5 months ago

@WreckItTim Can you please share how you set the different PID gains? Is it using the API calls or directly in AirSim/AirLib/include/vehicles/multirotor/firmwares/simple_flight/firmware/Params.hpp?