基于AirSim仿真平台进行无人机强化学习算法实验代码学习

https://github.com/AirSimDroneSimulator/AirSim/tree/master/3D_path_finding
以上代码基于AirSim仿真平台进行无人机强化学习算法实验,有部分代码还没理解,在此博客中记录学习和移植过程。

class MsgpackMixin:
    def __repr__(self):
        from pprint import pformat
        return "<" + type(self).__name__ + "> " + pformat(vars(self), indent=4, width=1)

    def to_msgpack(self, *args, **kwargs):
        return self.__dict__

    @classmethod
    def from_msgpack(cls, encoded):
        obj = cls()
        #obj.__dict__ = {k.decode('utf-8'): (from_msgpack(v.__class__, v) if hasattr(v, "__dict__") else v) for k, v in encoded.items()}
        obj.__dict__ = { k : (v if not isinstance(v, dict) else getattr(getattr(obj, k).__class__, "from_msgpack")(v)) for k, v in encoded.items()}
        #return cls(**msgpack.unpack(encoded))
        return obj
class Vector3r(MsgpackMixin):
    x_val = np.float32(0)
    y_val = np.float32(0)
    z_val = np.float32(0)

    def __init__(self, x_val = np.float32(0), y_val = np.float32(0), z_val = np.float32(0)):
        self.x_val = x_val
        self.y_val = y_val
        self.z_val = z_val
    def getMultirotorState(self) -> MultirotorState:
        return MultirotorState.from_msgpack(self.client.call('getMultirotorState'))
    def getPosition(self):
        return Vector3r.from_msgpack(self.client.call('getPosition'))
    def getVelocity(self):
        return Vector3r.from_msgpack(self.client.call('getVelocity'))
    def getOrientation(self):
        return Quaternionr.from_msgpack(self.client.call('getOrientation'))
    def getLandedState(self):
        return self.client.call('getLandedState')
    def getGpsLocation(self):
        return GeoPoint.from_msgpack(self.client.call('getGpsLocation'))
    def getPitchRollYaw(self):
        return self.toEulerianAngle(self.getOrientation())

有几个问题:

  • self.client.call()是什么意思
  • from_msgpack()是什么意思
  • 类方法是什么?
  • def getMultirotorState(self) -> MultirotorState:是什么意思

————————————————————————————————————————
def getMultirotorState(self) -> MultirotorState:这个函数下面要引用这类,具体的意思不清楚
————————————————————————————————————————
类方法:
python的classmethod叫做python的类方法,是只需要在普通方法上加上@classmethod这样一个装饰器就可以。
普通方法

def hello(self):
    pass

类方法

@classmethod
def hello(cls):
    pass

其中的参数从self变成了cls,self所代表的其实是对象的指针,它可以指向任意一个对象。在实例化对象的时候self就会变成对象实例。cls所代表的东西代表的其实是一个类本身,它可以用来调用类自己的属性和类自己的方法
————————————————————————————————————————
比如上面的from_msgpack函数代码里:

 obj = cls()

cls就相当于MsgpackMixin类,这个时候obj相当于MsgpackMixin类。
下一句代码:

obj.__dict__ = { k : (v if not isinstance(v, dict) else getattr(getattr(obj, k).__class__, "from_msgpack")(v)) for k, v in encoded.items()}

分解来看,{k : v for k, v in encoded.items()}的意思是k:v遍历encoded里面的key和value(不确定),encode是函数的参数
其中isinstance(v,dict)函数的作用:判断v是不是字典类型,即是不是v={1:4,a:b}这种类型。
其中item()函数的作用:返回可遍历的(键, 值) 元组数组,即返回参数encode的元组数组。
————————————————————————————————————————
self.client.call()和上面的import msgpackrpc有关,首先了解rpc是什么:
RPC—远程过程调用,它是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。RPC协议假定某些传输协议的存在,如TCP或UDP,为通信程序之间携带信息数据。

RPC采用客户机/服务器模式。请求程序是一个客户机,服务提供程序是一个服务器。
首先,客户机调用进程发送一个有进程参数的调用信息到服务进程,然后等待应答信息。在服务器端,进程保持睡眠状态直到调用信息到达为止。当一个调用信息到达,服务器获得进程参数,计算结果,发送答复信息,然后等待下一个调用信息。最后,客户端调用进程接收答复信息,获得进程结果,然后调用执行继续进行。
见什么是RPC(Remote Procedure Call)
也就是说两台服务器A,B,一个应用部署在A服务器上,想要调用B服务器上应用提供的函数/方法,由于不在一个内存空间,不能直接调用,需要通过网络来表达调用的语义和传达调用的数据。

——————————————————————————————————————
RPC

  • Call ID映射:

    怎么告诉远程机器我们要调用funA,而不是funB或者funC,在本地调用中,函数体是直接通过函数指针来指定的,我们调用funA,编译器就自动帮我们调用它相应的函数指针。但是在远程调用中,函数指针是不行的,因为两个进程的地址空间是完全不一样的。所以,在RPC中,所有的函数都必须有自己的一个ID。这个ID在所有进程中都是唯一确定的。客户端在做远程过程调用时,必须附上这个ID。然后我们还需要在客户端和服务端分别维护一个 {函数 <–> Call ID} 的对应表。两者的表不一定需要完全相同,但相同的函数对应的Call ID必须相同。

  • 序列化和反序列化:
    客户端怎么把参数值传给远程的函数呢?在本地调用中,只需要把参数压到栈里,然后让函数自己去栈里读就行。
    但是在远程过程调用时,客户端跟服务端是不同的进程,不能通过内存来传递参数。甚至有时候客户端和服务端使用的都不是同一种语言(比如服务端用C++,客户端用Java或者Python)。
    这时候就需要客户端把参数先转成一个字节流(编码),传给服务端后,再把字节流转成自己能读取的格式(解码)。这个过程叫序列化和反序列化。同理,从服务端返回的值也需要序列化反序列化的过程。

  • 网络传输
    网络传输层需要把Call ID和序列化后的参数字节流传给服务端,然后再把序列化后的调用结果传回客户端。只要能完成这两者的,都可以作为传输层使用。因此,它所使用的协议其实是不限的,能完成传输就行。尽管大部分RPC框架都使用TCP协议,但其实UDP也可以,而gRPC干脆就用了HTTP2。

————————————————————————————————————————
在官方代码的readme中有个例子:

import msgpackrpc
client = msgpackrpc.Client(msgpackrpc.Address("localhost", 18800))
result = client.call('sum', 1, 2)  # = > 3

其中call函数的意义在于调用’sum’函数进行计算,所以可能就是远程调用的作用。

你可能感兴趣的:(强化学习实验,python)