Tower 实战一:MavLink的连接与通信

1 废话不多说,Tower的连接方式之一是通过android通过手机自带蓝牙模块,和遥控器蓝牙通信,最后在连接飞空,飞空是一块单片机,里面也有一套程序处理逻辑,然后遥控器坐传输媒介

这样做的好处就是把一些用户操作放到android上面,比如航点规划,客服端控制飞机的起飞,降落等,最后飞空来控制无人机玩成一系列的操作

连接方式如图

2 今天主要说一下Mavlink的连接首先在Tower的源码里构建了一个类

public class MAVLinkClient implements MAVLinkStreams.MAVLinkOutputStream {
    public MAVLinkClient(Context context, MAVLinkStreams.MavlinkInputStream listener) {
        this.listener = listener;
    }

    private void connectMAVConnection() {
}

    public void sendMavPacket(MAVLinkPacket pack) {
}

    @Override
    public void toggleConnectionState() {
        if (isConnected()) {
            closeConnection();
        } else {
            openConnection();
        }
    }
}

这个了主要实习了 连接,切换连接,发送数据包,和注入一个listener , 这个listener主要是接受到数据的时候回调,所以这个类主要就是实习这个几个功能,Tower向无人机发送数据基本都是通过这个sendMavPacket方法去实现的

3 我们看看listener是个什么东西

    public interface MavlinkInputStream {
        void notifyConnected();

        void notifyDisconnected();

        void notifyReceivedData(MAVLinkMessage m);
    }

这个listener的声明 ,他是用来处理收到消息的 ,调用notifyReceivedData 接受一个MavLinkmessage

4  接来我们看MavLinkClient的初始化,差看源码可以看到,在Application的初始化OnCreatef 方法里面 MAVLinkClient MAVClient = new MAVLinkClient(this, this); 可以看到Application 实现了MavlinkInputStream 接口,并且实现了 notifyReceivedData 方法

    @Override
    public void notifyReceivedData(MAVLinkMessage msg) {
        mavLinkMsgHandler.receiveData(msg);
    }

5 这样你就很容易看到在哪里处理 MAVLinkMessage 了,so , MavLinkMsgHandler 就是 MAVLinkMessage 的处类了,你可以看到关于多种MAVLinkMessage 的处理,这些消息有心跳消息,事件消息等。。。

6 现在条理是不是很清楚了,那我们就来看android如果通过蓝牙连接飞控的,首先你必须会蓝牙连接的基础知识,网上资料很多

7 我们看连接函数

    private void connectMAVConnection() {
        bluetoothConnection.addMavLinkConnectionListener("blue",mConnectionListener);
        Toast.makeText(parent, R.string.status_connecting, Toast.LENGTH_SHORT).show();
        if (bluetoothConnection.getConnectionStatus() == MavLinkConnection.MAVLINK_DISCONNECTED) {
            bluetoothConnection.connect();
        }
    }

直接调用了bluetoothConnection.connect(),  MavLinkConnection bluetoothConnection是一个抽象类,也住无人机地面站里面的一个比较核心的类,

  /**
     * Listen for incoming data on the mavlink connection.
     */
    private final Runnable mConnectingTask = new Runnable() {

        @Override
        public void run() {
            Thread sendingThread = null, loggingThread = null;
            try {
                // Open the connection
                openConnection();
                mConnectionStatus.set(MAVLINK_CONNECTED);
                // Launch the ‘Sending‘, and ‘Logging‘ threads
                sendingThread = new Thread(mSendingTask, "MavLinkConnection-Sending Thread");
                sendingThread.start();

                final Parser parser = new Parser();
                parser.stats.mavlinkResetStats();

                final byte[] readBuffer = new byte[READ_BUFFER_SIZE];
                while (mConnectionStatus.get() == MAVLINK_CONNECTED&&!isAndroidfor4_4()) {
                    int bufferSize = readDataBlock(readBuffer);
                    if (readBuffer==null||readBuffer.length==0){
                        continue;
                    }
                    handleData(parser, bufferSize, readBuffer);
                }
            } catch (Exception e) {
                Log.i("===>>","disconent");
                if (loggingThread != null && loggingThread.isAlive()) {
                    loggingThread.interrupt();
                }

                if (sendingThread != null && sendingThread.isAlive()) {
                    sendingThread.interrupt();
                }
                mConnectionStatus.set(MAVLINK_DISCONNECTED);
                disconnect();
            }
        }

8 这个类有几个核心的方法 1打开连接 openConnection(),2 sendingThread不停地发送数据 3  handleData()处理数据,在其实现类里面主要也是完成这3个方法,

public Bluetoothfor2_0Connection(Context parentContext) {
        prefs = new DroidPlannerPrefs(parentContext);
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            Log.d(BLUE, "Null adapters");
        }
    }

    protected void openAndroidConnection() throws IOException {
        Log.d(BLUE, "Connect");

        // Reset the bluetooth connection
        resetConnection();

        // Retrieve the stored device
        BluetoothDevice device = null;
        final String addressName = prefs.getBluetoothDeviceAddress();

        if (addressName != null) {
            // strip name, use address part - stored as <address>;<name>
            final String part[] = addressName.split(";");
            try {
                device = mBluetoothAdapter.getRemoteDevice(part[0]);
            } catch (IllegalArgumentException ex) {
                // invalid configuration (device may have been removed)
                // NOP fall through to ‘no device‘
            }
        }
        // no device
        if (device == null)
            device = findSerialBluetoothBoard();

        Log.d(BLUE, "Trying to connect to device with address " + device.getAddress());
        Log.d(BLUE, "BT Create Socket Call...");
        bluetoothSocket = device.createInsecureRfcommSocketToServiceRecord(UUID
                .fromString(UUID_SPP_DEVICE));

        Log.d(BLUE, "BT Cancel Discovery Call...");
        mBluetoothAdapter.cancelDiscovery();

        Log.d(BLUE, "BT Connect Call...");
        bluetoothSocket.connect(); // Here the IOException will rise on BT
                                    // protocol/handshake error.

        Log.d(BLUE, "## BT Connected ##");
        out = bluetoothSocket.getOutputStream();
        in = bluetoothSocket.getInputStream();
    }

    @Override
    protected int readDataBlock(byte[] buffer) throws IOException {
        return in.read(buffer);

    }

    @Override
    protected void sendBuffer(byte[] buffer) throws IOException {
        if (out != null) {
            out.write(buffer);
        }
    }

9 handledata 方法就是回调之前的 listener.notifydatareceiver(),是不是之前地方了,至于发送数据

 private final Runnable mSendingTask = new Runnable() {
        @Override
        public void run() {
            int msgSeqNumber = 0;
            try {
                while (mConnectionStatus.get() == MAVLINK_CONNECTED) {
                    final MAVLinkPacket packet = mPacketsToSend.take();
                    packet.seq = msgSeqNumber;
                    byte[] buffer = packet.encodePacket();
                        if (buffer==null|| buffer.length==0){
                            continue;
                        }
                    try {
                        sendBuffer(buffer);
                        queueToLog(packet);
                    } catch (IOException e) {
                        reportComError(e.getMessage());
                        mLogger.logErr(TAG, e);
                    }

                    msgSeqNumber = (msgSeqNumber + 1) % (MAX_PACKET_SEQUENCE + 1);
                }
            } catch (InterruptedException e) {

    };

发送数据其实也是Mavclient的 sendMavPacket方法,里面有一个阻塞队列的东西,线程安全的双端队列,可能需要你看看,思路很清晰,2可能会讲 MavlinkMessage

    @Override
    public void sendMavPacket(MAVLinkPacket pack) {
        if (!isConnected()) {
            return;
        }
        bluetoothConnection.sendMavPacket(pack);
    }
时间: 2024-10-07 00:57:12

Tower 实战一:MavLink的连接与通信的相关文章

zookeeper curator ( 实战一)

目录 zookeeper 的伪集群搭建 写在前面 1.1. zookeeper 安装&配置 1.1.1. 创建数据目录和日志目录: 1.1.2. 创建myid文件 1.1.3. 创建和修改配置文件 1.1.4. 配置文件实例 1.1.5. 修改启动命令 1.1.6. 启动伪集群 1.1.7. zk的客户端常用命令 写在最后 疯狂创客圈 亿级流量 高并发IM 实战 系列 zookeeper 的伪集群搭建 疯狂创客圈 Java 分布式聊天室[ 亿级流量]实战系列之 -22[ 博客园 总入口 ] 源码

【转】Delphi+Halcon实战一:两行代码识别QR二维码

Delphi+Halcon实战一:两行代码识别QR二维码 感谢网友:绝代双椒( QQ:51536348)的支持 本文是绝代双椒的作品,因为最近在忙zw量化培训,和ziwang.com网站的升级,halcon没时间操作. 不过,随着国内产业升级,机器人行业的发展,Delphi+Halcon的未来,是无可限量的. 其他网友,有halcon这方面作品的,有需要,也可以交给zw转发. 另外,zw正在争取培训机构合作,开办Delphi+Halcon方面的培训的项目,有兴趣的机构可以联系QQ:3578117

Android 蓝牙开发之搜索、配对、连接、通信大全

        蓝牙( Bluetooth®):是一种无线技术标准,可实现固定设备.移动设备和楼宇个人域网之间的短距离数据 交换(使用2.4-2.485GHz的ISM波段的UHF无线电波).蓝牙设备最多可以同时和7个其它蓝牙设备建立连接,进 行通信,当然并不是每一个蓝牙都可以达到最大值.下面,我们从蓝牙的基本概念开始,一步一步开始了解蓝牙. 基本概念: 安卓平台提供对蓝牙的通讯栈的支持,允许设别和其他的设备进行无线传输数据.应用程序层通过安卓API来调用蓝牙的相关功 能,这些API使程序无线连接

Maven实战一:Maven的安装与配置

Maven实战一Maven的安装与配置 一安装Maven 检查JDK安装 下载Maven 本地安装 1解压 2设置环境变量 3升级Maven 二安装目录分析 M2_HOME m2 三设置HTTP代理 确认是否能够直接访问公共的Maven中央仓库 如果真的需要代理检查代理服务器是否畅通 编辑m2settingsxml 四Eclipse对Maven的支持 五Maven安装最佳实践 设置MAVEN_OPTS环境变量 配置用户范围settingsxml 不要使用IDE内嵌的Maven Maven实战一:

tcp/udp建立连接并通信的过程

基于TCP的socket编程的服务器程序流程如下: 1.创建套接字 SOCKETsockSrv = socket(AF_INET, SOCK_STREAM, 0) ; 2.将套接字绑定到本地地址和端口上 SOCKADDR_INaddrSrv ; addrSrv.sin_addr.S_un.S_addr =htonl(INADDR_ANY) ;                   //把一个u_long类型的值转化为网络字节顺序 addrSrv.sin_family = AF_INET ; add

机器学习实战一(kNN)

机器学习实战一(kNN) 跟着老师做一个项目,关于行车记录仪识别前方车辆,并判断车距,不太好做.本来是用OpenCV,做着做着,突然发现需要补习一下机器学习的内容.<机器学习实战(machine learing in action)>这本书买了很久了,当时还是看了很多人推荐,不过到现在才想起翻出来看.第二章kNN的例子刚跟着做完,书里讲的很清楚,代码条理分明,只不过我是用Python3实现的.具体的过程不再赘述,只是把自己的理解放在这里. 先来看看书里第一章的部分. 机器学习就是把无序的数据转

数据-第19课-递归的应用实战一

第19课-递归的应用实战一 1. 递归的数学思想 (1)      递归是一种数学上分而自治的思想. (2)      递归将大型复杂问题转化为与原问题相同但规模较小的问题进行处理. (3)      递归需要有边界条件. l  当边界条件不满足时,递归继续进行. l  当边界条件满足时,递归停止. 2 . 递归的数学表示 n > 1 n==1 (1)斐波拉契数列递归解法 #include <stdio.h> int fibonacci(int n) { if( n > 1 ) {

信息安全领域大数据应用实战一

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ 希望对您软件项目开发,运维管理,信息按期,系统架构与研

Hangfire实战一

Hangfire:一个开源的任务调度框架 开发环境:VS2017,SQL Server 2012,.NET Framework 4.5 项目类型:控制台应用程序 1.在vs的程序包控制台中为项目添加Hangfire支持 PM>Install-Package Hangfire 2.配置sql server连接 GlobalConfiguration.Configuration.UseColouredConsoleLogProvider().UseSqlServerStorage("Data