需求
在flightgear中实现控制两个飞行器
一、Fg中双飞行器的显示
1.使用fg提供的multiplay接口
在FlightGear中,Multiplay是用于支持多人联机游戏的接口。通过Multiplay接口,玩家可以连接到FlightGear的多人游戏服务器,与其他玩家一起飞行,进行飞行比赛或共同探索虚拟世界。
Multiplay接口允许玩家在游戏中进行实时通信、位置更新、飞行数据传输等操作。玩家可以使用诸如FGNet、FlightGear模拟器内建的Multiplay功能或其他连接工具来连接到Multiplay服务器。
2.在本地双开fg实例并配置multipaly接口实现两个实例的通信
格式为 --muliplay = 方向 (输入还是输出), 频率 ,ip地址(这里为本地地址) ,端口
--multiplay=out,10,127.0.0.1,5000
--multiplay=in,10,127.0.0.1,5001
3.使用bat脚本用于两个fg实例的初始化
实例1:(aircraft可自定义)
C:
cd C:\Program Files\FlightGear 2020.3
SET FG_ROOT=C:\Program Files\FlightGear 2020.3\data\
SET FG_SCENERY=C:\Program Files\FlightGear 2020.3\data\Scenery
.\bin\fgfs --aircraft=falcon9 --fdm=ufo --altitude=80 --generic=socket,in,10,127.0.0.1,5507,udp,test --airport=KSFO --start-date-lat=2004:06:01:09:00:00 --callsign=FG1 --multiplay=out,10,127.0.0.1,5000 --multiplay=in,10,127.0.0.1,5001
C:
cd C:\Program Files\FlightGear 2020.3
SET FG_ROOT=C:\Program Files\FlightGear 2020.3\data\
SET FG_SCENERY=C:\Program Files\FlightGear 2020.3\data\Scenery
.\bin\fgfs --aircraft=HL20 --fdm=ufo --altitude=100 --generic=socket,in,10,127.0.0.1,5508,udp,test --airport=KSFO --start-date-lat=2004:06:01:09:00:00 --callsign=FG2 --multiplay=out,10,127.0.0.1,5001 --multiplay=in,10,127.0.0.1,5000
4.运行两个脚本
即可看到双机显示
二、控制飞行器
1.配置通信xml文件
进入到protocol文件夹下
新建test.xml文件
这里配置了飞行器的部分参数用于测试通信。
该协议使用二进制通信。
<?xml version="1.0"?>
<PropertyList>
<generic>
<input>
<binary_mode>true</binary_mode>
<binary_footer>none</binary_footer>
<byte_order>host</byte_order>
<record_length>24</record_length>
<chunk>
<name>altitude</name>
<type>double</type>
<node>/position/altitude-ft</node>
</chunk>
<chunk>
<name>throttle</name>
<type>double</type>
<node>/controls/engines/engine[0]/throttle</node>
</chunk>
<chunk>
<name>elevator</name>
<type>double</type>
<node>/controls/flight/elevator</node>
</chunk>
</input>
</generic>
</PropertyList>
在初始化fg时需配置 --generic=socket,in,10,127.0.0.1,5507,udp,test
向fg说明使用test自定义协议,udp报文通信。
2.使用C++编写接口实现控制
项目结构
代码:
udpsender.h
#ifndef UDPSENDER_H
#define UDPSENDER_H
#include <QHostAddress>
#include <QUdpSocket>
#include <QByteArray>
#include <QVector>
#include <QAbstractSocket>
#include <QTimer>
class UdpSender: public QObject
{
Q_OBJECT
public:
UdpSender(QObject *parent = 0);
void send();
private:
QUdpSocket *udpSocketSend1;
QUdpSocket *udpSocketSend2;
QTimer *timer;
QVector<double> vec1 = {
80, // high
0, // throttle
-1 // elevator
};
QVector<double> vec2 = {
35, // high
0, // throttle
0 // elevator
};
};
#endif // UDPSENDER_H
udpsender.cpp
#include "udpsender.h"
#include <iostream>
UdpSender::UdpSender(QObject *parent) : QObject(parent)
{
udpSocketSend1 = new QUdpSocket(this);
udpSocketSend2 = new QUdpSocket(this);
udpSocketSend1->bind(QHostAddress::LocalHost, 5507);
udpSocketSend2->bind(QHostAddress::LocalHost, 5508);
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &UdpSender::send);
timer->start(10); // 每10毫秒发送一次
}
void UdpSender::send()
{
vec1[0] += 0.1;
vec2[0] += 0.1;
QByteArray datagram1 = QByteArray::fromRawData(
reinterpret_cast<const char*>(vec1.constData()),
sizeof(double) * vec1.size()
);
QByteArray datagram2 = QByteArray::fromRawData(
reinterpret_cast<const char*>(vec2.constData()),
sizeof(double) * vec2.size()
);
udpSocketSend1->writeDatagram(datagram1, QHostAddress::LocalHost, 5507);
udpSocketSend2->writeDatagram(datagram2, QHostAddress::LocalHost, 5508);
}
main.cpp
#include <iostream>
#include <QGuiApplication>
#include "udpsender.h"
using namespace std;
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
UdpSender udpSender;
udpSender.send();
return app.exec();
}