AFSim学习-自定义Processor开发2-将平台状态存储到csv

前言

编译与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
相关推荐
bu_shuo1 小时前
计算机二级学习-查找和排序
学习·算法·排序算法
爱奥尼欧1 小时前
轻量级可扩展日志框架-异步日志与系统集成
开发语言·数据库·c++·学习
MartinYeung51 小时前
[论文学习]BackdoorLLM:大语言模型后门攻击与防御的综合性基准——深度解析
人工智能·学习·语言模型
凉、介2 小时前
KVM + QEMU 虚拟化
笔记·学习·嵌入式·arm·qemu·虚拟化·kvm
承渊政道2 小时前
【MySQL数据库学习】(MySQL访问、连接池原理与简易网站数据流动)
数据库·学习·mysql·mysql访问·连接池原理
LiaoWL1232 小时前
【SpringBoot合集-03】Spring Boot 启动过程学习
java·spring boot·学习
Byron__11 小时前
AI学习_06_短期记忆与长期记忆
人工智能·python·学习
试剂界的爱马仕12 小时前
Anti-mouse PD-1 mAb (Clone RMP1-14) 与 Axitinib 小鼠实验使用方案整理汇总
大数据·人工智能·深度学习·学习
Gp7HH6hrE13 小时前
OpenAI 与 Anthropic 开放公共学习平台
人工智能·学习·chatgpt