• AirSim 自动驾驶仿真 (3) 飞机控制API和opencv获取图像


    官方api

    https://microsoft.github.io/AirSim/api_docs/html/

    https://zhuanlan.zhihu.com/p/307956920?utm_source=wechat_session

    设置摄像机参数和图像参数

    修改UE4仿真环境的参数,同样是修改settings.json文件,可以修改AirSim摄像机保存图像的尺寸等参数。示例如下:

    {
      "SettingsVersion": 1.2,
      "CameraDefaults": {
          "CaptureSettings": [
            {
              "ImageType": 0,
              "Width": 1920,
              "Height": 1080,
              "FOV_Degrees": 90,
              "AutoExposureSpeed": 100,
              "MotionBlurAmount": 0
            }
        ]
      },
      "SimMode": "ComputerVision"
    }
    

      只是个参考

    基本api代码整理

    官方自带的测试程序

     自己整理的测试python

    1 基本控制移动,两种控制模式

      1-1依靠速度控制.

      1-2依靠坐标位置控制

            备注说明,例如一边拍照一边控制移动,的开个多线程专门处理移动不能影响彩图卡顿。去掉jion函数不会等待动作执行完毕才去执行拍照,就可以做到一边移动一边拍照。

    2获取集本数据 gps  position

    3获取图像,转化成opencv可以操作的数据

      3-1修改相机编号  下视还是前视,默认下视

      3-2修改画面数据,彩色还是深度图,默认彩色图

    # In settings.json first activate computer vision mode: 
    # https://github.com/Microsoft/AirSim/blob/master/docs/image_apis.md#computer-vision-mode
    
    #基本集成了飞机所有的控制,图像转换到opencv
    
    #import setup_path 
    #导入自己的airsim编译路径
    import sys
    sys.path.append("/home/dongdong/3Code/Airsim/AirSim/PythonClient")
    
    import airsim
    
    import cv2
    import time
    import sys
    
    import pprint
    import numpy as np
    import os
    import tempfile
    
    #选择要采集的图像类型
    cameraType = "scene" #正常画面 12fps  1920*1080
    
    cameraTypeMap = { 
     "depth": airsim.ImageType.DepthVis,#黑白景深图像
     "segmentation": airsim.ImageType.Segmentation,#彩色目标分割图像
     "seg": airsim.ImageType.Segmentation,#彩色目标分割图像
     "scene": airsim.ImageType.Scene,#正常图像
     "disparity": airsim.ImageType.DisparityNormalized,
     "normals": airsim.ImageType.SurfaceNormals
    }
    
    #选择摄像头
    '''
    ---camera_name_val: airsim自带的simple flight,每个无人机自带5个相机,其ID 与相机分别对应如下:
    0 = front_center
    1 = front_right
    2 = front_left
    3 = bottom_center #下视画面
    4 = back_center
    '''
    cameraUse="3" 
    
    # 连接到Airsim仿真器
    #client = airsim.MultirotorClient()#默认本机
    client = airsim.MultirotorClient("192.168.0.1")#局域网主机IP
    # 每1秒检查一次连接状态,并在控制台中报告,以便用户可以查看连接的进度(应该是开启了个线程,因为只是调用了一次)
    client.confirmConnection()
    #开启api控制,默认是false,有的设备不允许用API控制,所以用isApiControlEnabled可以查看是否可以用API控制
    client.enableApiControl(True)
    
    
    
    #获取无人飞机的所有数据
    Flystate = client.getMultirotorState()
    #s = pprint.pformat(state)
    #print("state: %s" % s)
    
    #从所有数据扣出 position坐标  北偏地坐标系
    position1=Flystate.kinematics_estimated.position
    #print(position1)
    print("position位置")
    print(position1.x_val)
    print(position1.y_val)
    print(position1.z_val) #负为上升,北偏地坐标系
    
    #从所有数据扣出 gps_data数据  经纬度
    gps_data=Flystate.gps_location
    #print(gps_data)
    print("GPS数据")
    print(gps_data.altitude)
    print(gps_data.latitude)
    print(gps_data.longitude)
    
    #单独获取当前位置GPS数据的api
    #gps_data = client.getGpsData()
    #s = pprint.pformat(gps_data)
    #print("gps_data: %s" % s)
    
    
    
    
    #按键等待
    airsim.wait_key('安任何按键,开始采集起飞')
    #起飞
    landed = client.getMultirotorState().landed_state
    if landed == airsim.LandedState.Landed:
        print("taking off...")
        client.takeoffAsync().join()
    else:
        print("already flying...")
        client.hoverAsync().join()
    
    
    #悬停
    client.hoverAsync().join()
    
    #飞行代码测试 有两种模式 定点飞和恒定速度飞 注销开启测试
    '''
    ----------------------------飞行控制模式1----------------------------------
    (1)坐标点控制 
    	初始化原点,化点为x,y,z是全局坐标位置,velocity是速度。
    	实现的效果是以 1m/s 的速度飞到 (5, 0) 点,3m 高的位置。
    	.join() 后缀的意思是程序在这里等待直到任务完成,也就是四旋翼到达目标位置点,同时到达设置的高度。
    	如果不加 .join() 后缀,则不用等待任务是否完成,函数直接返回,程序继续往下执行。
    
    '''
    
    '''
    airsim.wait_key('Press any key to fly1') 
    client.moveToZAsync(-3, 1).join()              # 上升到3m高度
    client.moveToPositionAsync(5, 0, -3, 1).join()  # 飞到(5,0)点坐标 高度3米 速度1m/s
    client.moveToPositionAsync(5, 5, -3, 1).join()  # 飞到(5,5)点坐标 高度3米 速度1m/s
    '''
    
    
    '''
    ----------------------------飞行控制模式2----------------------------------
      (2) 速度运动控制模式
    	#全局坐标系是北东地坐标系
    	vx:全局坐标系下x轴方向上的速度
    	vy:全局坐标系下y轴方向上的速度
    	z:全局坐标系下的高度
    	duration:持续的时间,单位:秒
    '''
    '''
    airsim.wait_key('Press any key to fly2') 
    client.moveToZAsync(-6, 1).join()              # 上升到6m高度
    client.moveByVelocityZAsync(1, 0, -6, 3).join()     # 第三阶段:以1m/s速度向x前飞3秒钟 -6米高度
    client.moveByVelocityZAsync(0, 1, -6, 3).join()     # 第三阶段:以1m/s速度向y前飞3秒钟 -6米高度
    '''
    
    
    
    
    
    #按键等待
    airsim.wait_key('按任何按键,开始采集图像,记得修改相机编号和图像类型')
    client.moveToZAsync(-10, 10).join()  #飞到10米高      10米速度
    #client.moveByVelocityZAsync(0, 1, -10, 9)     # 以y轴1m/s速度向y前飞9秒钟 10米高度  为了移动采集画面,不用等待join() 结束
    client.moveByVelocityZAsync(100, 0, -10, 2)   #2米/妙速度  10米高度  飞到 (100 ,0)位置
    
    #---------------------画图输出帧率字体格式------------------
    fontFace = cv2.FONT_HERSHEY_SIMPLEX
    fontScale = 0.5
    thickness = 2
    textSize, baseline = cv2.getTextSize("FPS", fontFace, fontScale, thickness)
    print (textSize)
    textOrg = (10, 10 + textSize[1])
    frameCount = 0
    startTime=time.clock()
    fps = 0
    #---------------------画图输出帧率字体格式------------------
    
    cv2.namedWindow("Airsim", cv2.WINDOW_NORMAL)
    
    while True:
        # because this method returns std::vector<uint8>, msgpack decides to encode it as a string unfortunately.
        rawImage = client.simGetImage(cameraUse, cameraTypeMap[cameraType])#获取airsim原始格式视频数据
        if (rawImage == None):
            print("图像为空")
            #sys.exit(0)
            continue
        else:
            png = cv2.imdecode(airsim.string_to_uint8_array(rawImage), cv2.IMREAD_UNCHANGED)#AIRSIM转换数据OPENCV
            cv2.putText(png,'FPS ' + str(fps),textOrg, fontFace, fontScale,(255,0,255),thickness)
            cv2.imshow("Airsim", png)
    
        frameCount  = frameCount  + 1
        endTime=time.clock()
        diff = endTime - startTime
        if (diff > 1):
            fps = frameCount
            frameCount = 0
            startTime = endTime
        
    
        key = cv2.waitKey(1) & 0xFF;
        if (key == 27 or key == ord('q') or key == ord('Q')):
            break;
    
    cv2.destroyAllWindows() 
          
    #降落
    landed = client.getMultirotorState().landed_state
    if landed == airsim.LandedState.Landed:
        print("already landed...")
    else:
        print("landing...")
        client.landAsync().join()
    
    # 上锁
    client.armDisarm(False)
    client.reset()
    #关闭控制
    client.enableApiControl(False)
    

      

    四旋翼飞行控制 API 讲解

    AirSim 坐标系定义总结

    水平位置控制函数

    函数定义:

    def moveToPositionAsync(
             self,
             x,          # 位置坐标(北东地坐标系)
             y,
             z,
             velocity,   # 速度
             timeout_sec=3e38,
             drivetrain=DrivetrainType.MaxDegreeOfFreedom,
             yaw_mode=YawMode(),
             lookahead=-1,
             adaptive_lookahead=1,
             vehicle_name="",
         )
    

      输入参数包括:

     
    x,y,z:位置坐标(全局坐标系 - 北东地)
    velocity: 飞行速度(m/s)
    timeout_sec: 如果没有响应,超时时间
    drivetrain,yaw_mode: 设置飞行朝向模式和yaw角控制模式
    lookahead, adaptive_lookahead: 设置路径飞行的时候的yaw角控制模式
    vehicle_name: 控制的四旋翼名字
    

    x, y, z, velocity 这四个参数是必须要设置的量,指示四旋翼以多大的速度飞往哪个坐标点。后面的几个参数都有其默认值,不用设置也可以。

    lookahead 和 adaptive_lookahead 这两个参数是设置当四旋翼飞轨迹的时候的朝向,目前还用不到。

    vehicle_name 是将指令发送给哪个四旋翼,当做多个四旋翼协同飞行控制的时候,这个参数就派上用场了,后面会有多机协同编队的教程。

    drivetrain 和 yaw_mode 这两个参数的组合可以设置四旋翼的偏航角控制模式,下面详细介绍。

     

    2.3 偏航角控制模式详解

    drivetrain 参数可以设置为两个量:

    • airsim.DrivetrainType.ForwardOnly: 始终朝向速度方向
    • airsim.DrivetrainType.MaxDegreeOfFreedom:手动设置yaw角度

    yaw_mode 必须设置为 YawMode() 类型的变量,这个结构体类型包含两个属性:

    • YawMode().is_rate:True - 设置角速度;False - 设置角度
    • YawMode().yaw_or_rate:可以是任意浮点数

     AirSim 坐标系定义总结

      

    Unreal 引擎中的坐标系与 AirSim 定义的坐标系是不同的,甚至长度单位都不同。Unreal的长度单位是厘米,而AirSim的长度单位是米。不过不用担心,AirSim已经非常好的处理了这个问题,你不用管Unreal的坐标系是什么,只需要按照AirSim的坐标系设置即可,AirSim会帮你自动转换的。

     

    本文先说明两个坐标系的定义: 全局坐标系、机体坐标系。

    全局坐标系是固连到大地的,x,y,z三个坐标轴的指向分别是北,东,地,也就是朝北是x轴的正方向,朝南就是x轴的负方向。全局坐标系的原点位置是大地的某一点(可以在settings文件中设置)。

    机体坐标系是固连到四旋翼机身的,x,y,z三个坐标轴的指向分别是前,右,下,也就是飞机的前方是x轴的正方向,飞机后方是x轴的负方向。机体坐标系的原点位置是机体的重心位置。

    如果按照1.2节的设置,将 playerStart的旋转都设为0,那么仿真刚开始的时候,四旋翼的机体坐标系与全局坐标系是重合的。

     

    暂停和继续的API

    可以使用pause(True)实现暂停。可能会遇到这样的情况,特别是在使用强化学习时,会在指定的时间内运行模拟,然后自动暂停。当模拟暂停时,可以执行一些昂贵的计算,发送一个新命令,然后在指定的时间内再次运行模拟。这个也可以使用continueForTime(seconds)实现(非常重要,太关键了),执行一段时间然后暂停。这个例子的使用,可以参考 pause_continue_car.py 和 pause_continue_drone.py.

      

     

  • 相关阅读:
    嵌入式根文件系统的制作和挂载【转】
    嵌入式Linux内核制作【转】
    Linux按键驱动程序设计--从简单到不简单【转】
    Linux设备驱动工程师之路——内核链表的使用【转】
    linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟【转】
    linux设备驱动归纳总结(十二):简单的数码相框【转】
    linux设备驱动归纳总结(十一):写个简单的看门狗驱动【转】
    linux设备驱动归纳总结(十):1.udev&misc【转】
    linux设备驱动归纳总结(九):1.platform总线的设备和驱动【转】
    linux设备驱动归纳总结(八):4.总线热插拔【转】
  • 原文地址:https://www.cnblogs.com/kekeoutlook/p/14246936.html
Copyright © 2020-2023  润新知