前言
编译与mission使用见前述文章,在我主页里找。
自定义Processor:将平台状态存储到csv
新建文件
在src/core/wsf/source/processor/下新建文件:
WsfStateLoggerProcessor.hpp;
WsfStateLoggerProcessor.cpp。
说明
相比"自定义Processor开发1-读取平台状态并打印出来",添加了:
1 WsfStateLoggerProcessor.hpp加了private变量 ,
包括输出文件名
std::string mFilename;
输出流
std::ofstream mFile;
以及
bool mHeaderWritten;
2 头文件加了:
cpp
#include <fstream>
#include <string>
3 WsfStateLoggerProcessor.hpp的初始化函数要重写 。
bool Initialize(double aSimTime) override;
4 WsfStateLoggerProcessor.cpp的构造函数
cpp
// 创建Processor时调用。
// aScenario表示当前所属的仿真场景。
WsfStateLoggerProcessor::WsfStateLoggerProcessor(WsfScenario& aScenario)
// 调用父类WsfProcessor的构造函数
: WsfProcessor(aScenario)
, mFilename("state.csv")
, mHeaderWritten(false)
{
}
5 WsfStateLoggerProcessor.cpp的拷贝构造函数
注意要复制父类的数据
cpp
// Clone()会调用这里。
// AFSIM内部复制Processor时使用。
WsfStateLoggerProcessor::WsfStateLoggerProcessor(const WsfStateLoggerProcessor& aSrc)
// 先复制父类的数据
: WsfProcessor(aSrc)
, mFilename(aSrc.mFilename)
, mHeaderWritten(aSrc.mHeaderWritten)
{
}
WsfStateLoggerProcessor.hpp
cpp
// ① 头文件保护(Header Guard)
// 防止同一个头文件被重复包含(#include 多次)。
#ifndef WSFSTATELOGGERPROCESSOR_HPP
#define WSFSTATELOGGERPROCESSOR_HPP
// sqrt()计算速度大小
#include <cmath>
// 输出到终端
#include <iostream>
#include <fstream>
#include <string>
// ② 导出宏
// Windows 下会展开成 __declspec(dllexport)
// Linux 下一般为空
#include "wsf_export.h"
// ③ 前向声明(Forward Declaration)
// 这里只告诉编译器:有一个类叫 UtInput。真正使用它的时候(cpp)#include "UtInput.hpp"
class UtInput;
// ④ 包含父类
#include "WsfProcessor.hpp"
// 类定义
// WsfStateLoggerProcessor继承自WsfProcessor
class WSF_EXPORT WsfStateLoggerProcessor : public WsfProcessor
{
public:
// 构造函数,创建 Processor。new WsfStateLoggerProcessor(scenario);
WsfStateLoggerProcessor(WsfScenario& aScenario);
// 禁止赋值。例如WsfStateLoggerProcessor a(...);WsfStateLoggerProcessor b(...);a = b; // 编译错误
WsfStateLoggerProcessor& operator=(const WsfStateLoggerProcessor&) = delete;
// 析构函数。对象销毁时调用。
~WsfStateLoggerProcessor() override;
// 利用拷贝构造,复制一个新的 Processor。Template Processor-Clone()-》Platform A-Clone()-》Platform B
WsfProcessor* Clone() const override;
bool Initialize(double aSimTime) override;
// 解析 Mission Script
bool ProcessInput(UtInput& aInput) override;
// 整个 Processor 最核心的函数。AFSIM 每次仿真推进都会调用:Simulation-》Processor Update()
void Update(double aSimTime) override;
protected:
//! Copy constructor for Clone()
// 拷贝构造函数,这就是刚才 Clone() 用到的,*this就是调用WsfStateLoggerProcessor(const ...)
WsfStateLoggerProcessor(const WsfStateLoggerProcessor& aSrc);
private:
// 输出文件名
std::string mFilename;
// // 输出时间间隔(秒)
// double mInterval;
bool mHeaderWritten;
// // 是否追加
// bool mAppend;
// 输出流
std::ofstream mFile;
};
#endif
WsfStateLoggerProcessor.cpp
cpp
#include "WsfStateLoggerProcessor.hpp"
// AFSIM输入解析类(ProcessInput会用到)
#include "UtInput.hpp"
// AFSIM平台类,可以获取飞机、舰艇、导弹等平台的信息
#include "WsfPlatform.hpp"
//==============================================================
// 构造函数
//==============================================================
// 创建Processor时调用。
// aScenario表示当前所属的仿真场景。
WsfStateLoggerProcessor::WsfStateLoggerProcessor(WsfScenario& aScenario)
// 调用父类WsfProcessor的构造函数
: WsfProcessor(aScenario)
, mFilename("state.csv")
, mHeaderWritten(false)
{
}
WsfStateLoggerProcessor::~WsfStateLoggerProcessor()
{
if (mFile.is_open())
{
mFile.close();
}
}
//==============================================================
// 拷贝构造函数
//==============================================================
// Clone()会调用这里。
// AFSIM内部复制Processor时使用。
WsfStateLoggerProcessor::WsfStateLoggerProcessor(const WsfStateLoggerProcessor& aSrc)
// 先复制父类的数据
: WsfProcessor(aSrc)
, mFilename(aSrc.mFilename)
, mHeaderWritten(aSrc.mHeaderWritten)
{
}
//==============================================================
// Clone()
//==============================================================
// AFSIM要求所有Processor都必须能够Clone。
// 系统在复制平台时,就是调用这个函数。
WsfProcessor* WsfStateLoggerProcessor::Clone() const
{
// 调用拷贝构造函数创建一个新的对象
return new WsfStateLoggerProcessor(*this);
}
bool WsfStateLoggerProcessor::Initialize(double aSimTime)
{
bool ok = WsfProcessor::Initialize(aSimTime);
std::cout<<"=====Initialize====="<<std::endl;
std::cout << "Filename = [" << mFilename << "]" << std::endl;
// mFile.open(mFilename);
mFile.open(mFilename.c_str(), std::ios::out);
if (!mFile.is_open())
{
std::cout << "Open " << mFilename << " FAILED!" << std::endl;
}
else
{
std::cout << "Open " << mFilename << " SUCCESS!" << std::endl;
mFile << "time,name,lat,lon,alt,x,y,z,vx,vy,vz,speed\n";
}
return ok;
}
//==============================================================
// ProcessInput()
//==============================================================
// 读取脚本里的参数。
bool WsfStateLoggerProcessor::ProcessInput(UtInput& aInput)
{
std::string command(aInput.GetCommand());
if (command == "filename"){
aInput.ReadValue(mFilename);
std::cout
<< "CSV filename = "
<< mFilename
<< std::endl;
return true;
}
return WsfProcessor::ProcessInput(aInput);
}
// Update()是Processor最重要的函数。
// 每次仿真更新都会执行一次。
void WsfStateLoggerProcessor::Update(double aSimTime)
{
// 先执行父类Update。
WsfProcessor::Update(aSimTime);
// 获取所属平台
// 如果Processor没有挂到任何平台上,就退出。
if (GetPlatform() == nullptr)
{
return;
}
std::cout<<"=====Update====="<<std::endl;
// 获取ECEF(World Coordinate System)坐标
// 世界坐标(x,y,z),单位:米。
double locWCS[3];
GetPlatform()->GetLocationWCS(locWCS);// 获取平台当前位置
// 获取ECEF速度
double velWCS[3];// 世界坐标速度(vx,vy,vz),单位:m/s。
GetPlatform()->GetVelocityWCS(velWCS);// 获取平台速度
// 获取经纬高
double lat;// 纬度(deg)
double lon;// 经度(deg)
double alt;// 高度(m)
GetPlatform()->GetLocationLLA(lat, lon, alt);// 获取平台经纬高
// 计算速度大小
double speed = std::sqrt(// 得到平台真实速度(m/s)
velWCS[0] * velWCS[0] +
velWCS[1] * velWCS[1] +
velWCS[2] * velWCS[2]);
std::cout << aSimTime << ","
<< GetPlatform()->GetName() << ","
<< lat << ","
<< lon << ","
<< alt << ","
<< locWCS[0] << ","
<< locWCS[1] << ","
<< locWCS[2] << ","
<< velWCS[0] << ","
<< velWCS[1] << ","
<< velWCS[2] << ","
<< speed
<< std::endl;
mFile << aSimTime << ","// 输出CSV格式
<< GetPlatform()->GetName() << ","
<< lat << ","
<< lon << ","
<< alt << ","
<< locWCS[0] << ","
<< locWCS[1] << ","
<< locWCS[2] << ","
<< velWCS[0] << ","
<< velWCS[1] << ","
<< velWCS[2] << ","
<< speed
<< std::endl;
mFile.flush();
}
编译
直接重新编译就行
afsim-src/afsim/swdev文件夹下
bash
cmake --build buil --target wsf -j12
cmake --build buil --target mission -j12
测试场景
注册两个平台,红和蓝,并设置输出的csv文件名和路径。
bash
end_time 60 sec
platform_type BLUE_AIRCRAFT WSF_PLATFORM
mover WSF_AIR_MOVER
update_interval 1 sec
roll_rate_limit 1 rad/sec
default_linear_acceleration 1.0 g
default_radial_acceleration 6.5 g
default_climb_rate 400 fps
maximum_climb_rate 400 fps
maximum_speed 600.0 knots
minimum_speed 150.0 knots
maximum_altitude 50000 ft
minimum_altitude 50 ft
maximum_linear_acceleration 9 g
at_end_of_path extrapolate
turn_rate_limit 4.0 deg/sec
end_mover
processor state_logger MY_STATE_LOGGER_PROCESSOR
update_interval 10 sec
filename /home/ubuntu/afsim_ws/project1/11-two-platform-logger/blue.csv
end_processor
end_platform_type
platform_type RED_AIRCRAFT WSF_PLATFORM
mover WSF_AIR_MOVER
update_interval 1 sec
roll_rate_limit 1 rad/sec
default_linear_acceleration 1.0 g
default_radial_acceleration 6.5 g
default_climb_rate 400 fps
maximum_climb_rate 400 fps
maximum_speed 600.0 knots
minimum_speed 150.0 knots
maximum_altitude 50000 ft
minimum_altitude 50 ft
maximum_linear_acceleration 9 g
at_end_of_path extrapolate
turn_rate_limit 4.0 deg/sec
end_mover
processor state_logger MY_STATE_LOGGER_PROCESSOR
update_interval 10 sec
filename /home/ubuntu/afsim_ws/project1/11-two-platform-logger/red.csv
end_processor
end_platform_type
platform blue_1 BLUE_AIRCRAFT
side blue
position 38:49:12.88n 93:08:16.09w altitude 35000.00 ft msl
heading 90 deg
route
position 38:49:12.88n 93:08:16.09w altitude 35000.00 ft msl speed 500 kts
position 38:49:12.11n 89:52:40.60w altitude 35000.00 ft msl speed 500 kts
end_route
execute at_time 0.1 sec absolute
writeln("time,name,lat,lon,alt,x,y,z,vx,vy,vz,speed");
end_execute
end_platform
platform red_1 RED_AIRCRAFT
side red
position 38:49:12.88n 90:08:16.09w altitude 35000.00 ft msl
heading 270 deg
route
position 38:49:12.88n 90:08:16.09w altitude 35000.00 ft msl speed 450 kts
position 38:49:12.11n 93:52:40.60w altitude 35000.00 ft msl speed 450 kts
end_route
end_platform
运行
bash
./buil/mission -sm /home/ubuntu/afsim_ws/project1/11-two-platform-logger/two_platform_logger.txt
cat /home/ubuntu/afsim_ws/project1/11-two-platform-logger/red.csv
自定义Processor:取目标的参数,计算相对量
计算相对距离,相对高度,相对速度,接近速度。
要点
.hpp加上目标名:
cpp
std::string mTargetName;
.hpp加上头文件:
cpp
#include "WsfSimulation.hpp"
.cpp的构造函数加上:
cpp
, mTargetName("")
.cpp的拷贝构造函数加上:
cpp
, mTargetName(aSrc.mTargetName)
修改ProcessInput函数:
cpp
if (command == "target")
{
aInput.ReadValue(mTargetName);
std::cout
<< "Target name = "
<< mTargetName
<< std::endl;
return true;
}
修改Update函数:
cpp
// 获取目标平台
WsfPlatform* target = nullptr;
if (!mTargetName.empty())
{
target = GetSimulation()->GetPlatformByName(mTargetName);
if (target == nullptr)
{
std::cout << "Target platform [" << mTargetName << "] not found!" << std::endl;
}
}
//相对
std::string targetNameForOutput = "";
double range = 0.0;
double altDiff = 0.0;
double targetSpeed = 0.0;
double closingSpeed = 0.0;
bool hasTarget = false;
if (target != nullptr)
{
hasTarget = true;
targetNameForOutput = target->GetName();
double targetLoc[3];
double targetVel[3];
target->GetLocationWCS(targetLoc);
target->GetVelocityWCS(targetVel);
double targetLat;
double targetLon;
double targetAlt;
target->GetLocationLLA(targetLat, targetLon, targetAlt);
double dx = targetLoc[0] - locWCS[0];
double dy = targetLoc[1] - locWCS[1];
double dz = targetLoc[2] - locWCS[2];
range = std::sqrt(dx * dx + dy * dy + dz * dz);
altDiff = targetAlt - alt;
targetSpeed = std::sqrt(
targetVel[0] * targetVel[0] +
targetVel[1] * targetVel[1] +
targetVel[2] * targetVel[2]);
if (range > 1.0e-6)
{
double ux = dx / range;
double uy = dy / range;
double uz = dz / range;
double relVx = targetVel[0] - velWCS[0];
double relVy = targetVel[1] - velWCS[1];
double relVz = targetVel[2] - velWCS[2];
closingSpeed = -(relVx * ux + relVy * uy + relVz * uz);
}
}
改two_platform_logger.txt
bash
processor state_logger MY_STATE_LOGGER_PROCESSOR
update_interval 10 sec
filename /home/ubuntu/afsim_ws/project1/11-two-platform-logger/blue.csv
target red_1
end_processor
WsfStateLoggerProcessor.hpp
cpp
// Qiu写的
// ① 头文件保护(Header Guard)
// 防止同一个头文件被重复包含(#include 多次)。
#ifndef WSFSTATELOGGERPROCESSOR_HPP
#define WSFSTATELOGGERPROCESSOR_HPP
// sqrt()计算速度大小
#include <cmath>
// 输出到终端
#include <iostream>
#include <fstream>
#include <string>
// ② 导出宏
// Windows 下会展开成 __declspec(dllexport)
// Linux 下一般为空
#include "wsf_export.h"
// ③ 前向声明(Forward Declaration)
// 这里只告诉编译器:有一个类叫 UtInput。真正使用它的时候(cpp)#include "UtInput.hpp"
class UtInput;
// ④ 包含父类
#include "WsfProcessor.hpp"
#include "WsfPlatform.hpp"
#include "WsfSimulation.hpp"
// 类定义
// WsfStateLoggerProcessor继承自WsfProcessor
class WSF_EXPORT WsfStateLoggerProcessor : public WsfProcessor
{
public:
// 构造函数,创建 Processor。new WsfStateLoggerProcessor(scenario);
WsfStateLoggerProcessor(WsfScenario& aScenario);
// 禁止赋值。例如WsfStateLoggerProcessor a(...);WsfStateLoggerProcessor b(...);a = b; // 编译错误
WsfStateLoggerProcessor& operator=(const WsfStateLoggerProcessor&) = delete;
// 析构函数。对象销毁时调用。
~WsfStateLoggerProcessor() override;
// 利用拷贝构造,复制一个新的 Processor。Template Processor-Clone()-》Platform A-Clone()-》Platform B
WsfProcessor* Clone() const override;
bool Initialize(double aSimTime) override;
// 解析 Mission Script
bool ProcessInput(UtInput& aInput) override;
// 整个 Processor 最核心的函数。AFSIM 每次仿真推进都会调用:Simulation-》Processor Update()
void Update(double aSimTime) override;
protected:
//! Copy constructor for Clone()
// 拷贝构造函数,这就是刚才 Clone() 用到的,*this就是调用WsfStateLoggerProcessor(const ...)
WsfStateLoggerProcessor(const WsfStateLoggerProcessor& aSrc);
private:
// 输出文件名
std::string mFilename;
// // 输出时间间隔(秒)
// double mInterval;
bool mHeaderWritten;
std::string mTargetName;
// 输出流
std::ofstream mFile;
};
#endif
WsfStateLoggerProcessor.cpp
cpp
#include "WsfStateLoggerProcessor.hpp"
// AFSIM输入解析类(ProcessInput会用到)
#include "UtInput.hpp"
// AFSIM平台类,可以获取飞机、舰艇、导弹等平台的信息
// #include "WsfPlatform.hpp"
//==============================================================
// 构造函数
//==============================================================
// 创建Processor时调用。
// aScenario表示当前所属的仿真场景。
WsfStateLoggerProcessor::WsfStateLoggerProcessor(WsfScenario& aScenario)
// 调用父类WsfProcessor的构造函数
: WsfProcessor(aScenario)
, mFilename("state.csv")
, mHeaderWritten(false)
, mTargetName("")
{
}
WsfStateLoggerProcessor::~WsfStateLoggerProcessor()
{
if (mFile.is_open())
{
mFile.close();
}
}
//==============================================================
// 拷贝构造函数
//==============================================================
// Clone()会调用这里。
// AFSIM内部复制Processor时使用。
WsfStateLoggerProcessor::WsfStateLoggerProcessor(const WsfStateLoggerProcessor& aSrc)
// 先复制父类的数据
: WsfProcessor(aSrc)
, mFilename(aSrc.mFilename)
, mHeaderWritten(false)
, mTargetName(aSrc.mTargetName)
{
}
//==============================================================
// Clone()
//==============================================================
// AFSIM要求所有Processor都必须能够Clone。
// 系统在复制平台时,就是调用这个函数。
WsfProcessor* WsfStateLoggerProcessor::Clone() const
{
// 调用拷贝构造函数创建一个新的对象
return new WsfStateLoggerProcessor(*this);
}
bool WsfStateLoggerProcessor::Initialize(double aSimTime)
{
bool ok = WsfProcessor::Initialize(aSimTime);
std::cout<<"=====Initialize====="<<std::endl;
std::cout << "Filename = [" << mFilename << "]" << std::endl;
// mFile.open(mFilename);
mFile.open(mFilename.c_str(), std::ios::out);
if (!mFile.is_open())
{
std::cout << "Open " << mFilename << " FAILED!" << std::endl;
}
else
{
std::cout << "Open " << mFilename << " SUCCESS!" << std::endl;
// mFile << "time,name,lat,lon,alt,x,y,z,vx,vy,vz,speed\n";
mFile << "time,name,lat,lon,alt,x,y,z,vx,vy,vz,speed,"
<< "target,range_m,alt_diff_m,speed_target_mps,closing_speed_mps\n";
}
return ok;
}
//==============================================================
// ProcessInput()
//==============================================================
// 读取脚本里的参数。
bool WsfStateLoggerProcessor::ProcessInput(UtInput& aInput)
{
std::string command(aInput.GetCommand());
if (command == "filename"){
aInput.ReadValue(mFilename);
std::cout
<< "CSV filename = "
<< mFilename
<< std::endl;
return true;
}
if (command == "target")
{
aInput.ReadValue(mTargetName);
std::cout
<< "Target name = "
<< mTargetName
<< std::endl;
return true;
}
return WsfProcessor::ProcessInput(aInput);
}
// Update()是Processor最重要的函数。
// 每次仿真更新都会执行一次。
void WsfStateLoggerProcessor::Update(double aSimTime)
{
// 先执行父类Update。
WsfProcessor::Update(aSimTime);
// 获取所属平台
// 如果Processor没有挂到任何平台上,就退出。
auto* platform = GetPlatform();
if (GetPlatform() == nullptr)
{
return;
}
WsfPlatform* target = nullptr;
if (!mTargetName.empty())
{
target = GetSimulation()->GetPlatformByName(mTargetName);
if (target == nullptr)
{
std::cout << "Target platform [" << mTargetName << "] not found!" << std::endl;
}
}
std::cout<<"=====Update====="<<std::endl;
// 获取ECEF(World Coordinate System)坐标
// 世界坐标(x,y,z),单位:米。
double locWCS[3];
GetPlatform()->GetLocationWCS(locWCS);// 获取平台当前位置
// 获取ECEF速度
double velWCS[3];// 世界坐标速度(vx,vy,vz),单位:m/s。
GetPlatform()->GetVelocityWCS(velWCS);// 获取平台速度
// 获取经纬高
double lat;// 纬度(deg)
double lon;// 经度(deg)
double alt;// 高度(m)
GetPlatform()->GetLocationLLA(lat, lon, alt);// 获取平台经纬高
//相对
std::string targetNameForOutput = "";
double range = 0.0;
double altDiff = 0.0;
double targetSpeed = 0.0;
double closingSpeed = 0.0;
bool hasTarget = false;
if (target != nullptr)
{
hasTarget = true;
targetNameForOutput = target->GetName();
double targetLoc[3];
double targetVel[3];
target->GetLocationWCS(targetLoc);
target->GetVelocityWCS(targetVel);
double targetLat;
double targetLon;
double targetAlt;
target->GetLocationLLA(targetLat, targetLon, targetAlt);
double dx = targetLoc[0] - locWCS[0];
double dy = targetLoc[1] - locWCS[1];
double dz = targetLoc[2] - locWCS[2];
range = std::sqrt(dx * dx + dy * dy + dz * dz);
altDiff = targetAlt - alt;
targetSpeed = std::sqrt(
targetVel[0] * targetVel[0] +
targetVel[1] * targetVel[1] +
targetVel[2] * targetVel[2]);
if (range > 1.0e-6)
{
double ux = dx / range;
double uy = dy / range;
double uz = dz / range;
double relVx = targetVel[0] - velWCS[0];
double relVy = targetVel[1] - velWCS[1];
double relVz = targetVel[2] - velWCS[2];
closingSpeed = -(relVx * ux + relVy * uy + relVz * uz);
}
}
// 计算速度大小
double speed = std::sqrt(// 得到平台真实速度(m/s)
velWCS[0] * velWCS[0] +
velWCS[1] * velWCS[1] +
velWCS[2] * velWCS[2]);
std::cout << aSimTime << ","
<< GetPlatform()->GetName() << ","
<< lat << ","
<< lon << ","
<< alt << ","
<< locWCS[0] << ","
<< locWCS[1] << ","
<< locWCS[2] << ","
<< velWCS[0] << ","
<< velWCS[1] << ","
<< velWCS[2] << ","
<< speed
<< std::endl;
mFile << aSimTime << ","// 输出CSV格式
<< GetPlatform()->GetName() << ","
<< lat << ","
<< lon << ","
<< alt << ","
<< locWCS[0] << ","
<< locWCS[1] << ","
<< locWCS[2] << ","
<< velWCS[0] << ","
<< velWCS[1] << ","
<< velWCS[2] << ","
<< speed << ",";
if (hasTarget)
{
mFile << targetNameForOutput << ","
<< range << ","
<< altDiff << ","
<< targetSpeed << ","
<< closingSpeed;
}
else
{
mFile << ",,,,";
}
mFile << '\n';
mFile.flush();
}
编译
bash
cmake --build buil --target wsf -j12
cmake --build buil --target mission -j12
two_platform_logger.txt
bash
end_time 60 sec
platform_type BLUE_AIRCRAFT WSF_PLATFORM
mover WSF_AIR_MOVER
update_interval 1 sec
roll_rate_limit 1 rad/sec
default_linear_acceleration 1.0 g
default_radial_acceleration 6.5 g
default_climb_rate 400 fps
maximum_climb_rate 400 fps
maximum_speed 600.0 knots
minimum_speed 150.0 knots
maximum_altitude 50000 ft
minimum_altitude 50 ft
maximum_linear_acceleration 9 g
at_end_of_path extrapolate
turn_rate_limit 4.0 deg/sec
end_mover
processor state_logger MY_STATE_LOGGER_PROCESSOR
update_interval 10 sec
filename /home/ubuntu/afsim_ws/project1/11-two-platform-logger/blue.csv
target red_1
end_processor
end_platform_type
platform_type RED_AIRCRAFT WSF_PLATFORM
mover WSF_AIR_MOVER
update_interval 1 sec
roll_rate_limit 1 rad/sec
default_linear_acceleration 1.0 g
default_radial_acceleration 6.5 g
default_climb_rate 400 fps
maximum_climb_rate 400 fps
maximum_speed 600.0 knots
minimum_speed 150.0 knots
maximum_altitude 50000 ft
minimum_altitude 50 ft
maximum_linear_acceleration 9 g
at_end_of_path extrapolate
turn_rate_limit 4.0 deg/sec
end_mover
end_platform_type
platform blue_1 BLUE_AIRCRAFT
side blue
position 38:49:12.88n 93:08:16.09w altitude 35000.00 ft msl
heading 90 deg
route
position 38:49:12.88n 93:08:16.09w altitude 35000.00 ft msl speed 500 kts
position 38:49:12.11n 89:52:40.60w altitude 35000.00 ft msl speed 500 kts
end_route
execute at_time 0.1 sec absolute
writeln("time,name,lat,lon,alt,x,y,z,vx,vy,vz,speed");
end_execute
end_platform
platform red_1 RED_AIRCRAFT
side red
position 38:49:12.88n 90:08:16.09w altitude 35000.00 ft msl
heading 270 deg
route
position 38:49:12.88n 90:08:16.09w altitude 35000.00 ft msl speed 450 kts
position 38:49:12.11n 93:52:40.60w altitude 35000.00 ft msl speed 450 kts
end_route
end_platform
运行
bash
./buil/mission -sm /home/ubuntu/afsim_ws/project1/11-two-platform-logger/two_platform_logger.txt
cat /home/ubuntu/afsim_ws/project1/11-two-platform-logger/blue.csv