一心想要写个python的发送mavlink协议的自定义消息的程序,网上资源太少微乎其微。于是去mavlink的官方仔细研读终于实现了。
先挂一个mavlink官方网址:https://mavlink.io/
1.先通过pip安装pymavlink的官方库:pip install pymavlink
其他还需安装的依赖库有pyserial(串口连接依赖库),安装future库(异步执行操作库)
2.生成自定义mavlink消息依赖库这个网上有教程贴个图,是这个:
3.生成自定义后的python依赖文件后将文件放入到安装的pymavlink的路径下的dialects文件夹下
pymavlink的路径如图
dialects文件结构如图,放v10或者v20文件夹下都可以,一般1.0的mavlink放v10,2.0的mavlink放v20
4.在pymavlink的文件路径中找到工具类mavutil
在mavutil类的最前面加上:
os.environ['MAVLINK_DIALECT'] = "自定义生成,刚才拷贝进pymavlink路径的python依赖文件"
os.environ["MAVLINK20"] = "2.0"
#示例:
#os.environ['MAVLINK_DIALECT'] = "mavlink"
#os.environ["MAVLINK20"] = "2.0"
#比如使用mavlink的生成工具生成的库名字为mavlink.py,此处添加只能用mavlink,不然出现以下报错
ModuleNotFoundError: No module named 'pymavlink.dialects.v20.mavlink.py'; 'pymavlink.dialects.v20.mavlink' is not a package也就是评论1的报错
在mavutil类中以下两个代码片段实现将默认的v1.0中的ardupilotmega mavlink协议引入工具类mavutil,调用mavutil类时默认的收发解析时调用的即为v1.0中ardupilotmega
在加入以上代码片段后在工具类mavutil中即引入的为v2.0中拷贝的自定义生成的自定义mavlink消息协议。
if not 'MAVLINK_DIALECT' in os.environ:
os.environ['MAVLINK_DIALECT'] = 'ardupilotmega'
def set_dialect(dialect):
'''set the MAVLink dialect to work with.
For example, set_dialect("ardupilotmega")
'''
global mavlink, current_dialect
from .generator import mavparse
if 'MAVLINK20' in os.environ:
wire_protocol = mavparse.PROTOCOL_2_0
modname = "pymavlink.dialects.v20." + dialect
elif mavlink is None or mavlink.WIRE_PROTOCOL_VERSION == "1.0" or not 'MAVLINK09' in os.environ:
wire_protocol = mavparse.PROTOCOL_1_0
modname = "pymavlink.dialects.v10." + dialect
else:
wire_protocol = mavparse.PROTOCOL_0_9
modname = "pymavlink.dialects.v09." + dialect
try:
mod = __import__(modname)
except Exception:
# auto-generate the dialect module
from .generator.mavgen import mavgen_python_dialect
mavgen_python_dialect(dialect, wire_protocol)
mod = __import__(modname)
components = modname.split('.')
for comp in components[1:]:
mod = getattr(mod, comp)
current_dialect = dialect
mavlink = mod
# Set the default dialect. This is done here as it needs to be after the function declaration
set_dialect(os.environ['MAVLINK_DIALECT'])
5,在需要调用mavlink的类中引入mavlink的工具类mavutil,该工具类实现了很多mavlink的通用方法,如各种串口,udp,tcp的连接方法,即可调用类mavutil进行连接,消息收发解析等
from pymavlink import mavutil
//建立mavlink协议连接
the_connection2 = mavutil.mavlink_connection(('udp:127.0.0.1:20'))
一些连接的字符串示例
连接类型 | 连接字符串 |
通过USB连接到车辆的Linux计算机 | / dev / ttyUSB0 |
通过串行端口连接到车辆的Linux计算机(以RaspberryPi为例) | / dev / ttyAMA0(还设置了baud = 57600) |
MAVLink API通过UDP监听SITL连接 | udpin:localhost:14540(或udp:localhost:14540、127.0.0.1:14540等) |
MAVLink API通过UDP启动到SITL的连接 | udpout:localhost:14540(或udpout:127.0.0.1:14540) |
GCS通过UDP连接到车辆 | 127.0.0.1:14550或udp:localhost:14550 |
通过TCP连接到车辆的SITL | tcp:127.0.0.1:5760(仅ArduPilot,PX4不支持TCP) |
通过USB连接到车辆的OSX计算机 | dev / cu.usbmodem1 |
Windows计算机通过USB连接到车辆(在本例中为COM14) | com14 |
Windows计算机使用COM14上的3DR遥测无线电连接到车辆 | com14(还设置了baud = 57600) |
两台电脑之间连接示例:
python端:
远程端:
6.调用发送mavutil发送消息,以下代码段中如果没有进行第4步操作则the_connection2中的mav实列为默认的ardupilotmega协议类,若进行修改则为自定义生成的mavlink协议类
//发送心跳包
the_connection2.mav.heartbeat_send(mavutil.mavlink.MAV_TYPE_ONBOARD_CONTROLLER,
mavutil.mavlink.MAV_AUTOPILOT_INVALID, 1, 0, 0)
7.在the_connection2中的mav实列即自定义生成的mavlink协议类中包含所有xml中定义的消息收发接收解析方法,直接调用即可
部分接收消息函数截图:
8.消息接收
例如,使用the_connection
的设置,可以等待任何消息,如下所示:
msg = the_connection.recv_match(blocking=True) #blocking参数为是否阻塞
并且在尝试解析该消息之前检查该消息是否有效:
msg = m.recv_match(type='SYS_STATUS',blocking=True)
if not msg:
return
if msg.get_type() == "BAD_DATA":
if mavutil.all_printable(msg.data):
sys.stdout.write(msg.data)
sys.stdout.flush()
else:
#Message is valid
# Use the attribute
print('Mode: %s' % msg.mode)
请求多条指定消息
msg = the_connection2.recv_match(type=['HEARTBEAT','OPTITRACK_POSITION','TARGET_INFORMATION'], blocking=True)
请求一条指定消息
msg = the_connection2.recv_match(type='HEARTBEAT', blocking=True)