Carsim高级开发:VS Connect通讯开发指南


前言

为什么要使用VS Connect:

联合仿真:VS Connect API 允许在多个仿真软件之间进行同步仿真。这意味着可以在同一时间步内,多个仿真程序共享数据和状态信息,从而实现更复杂的联合仿真场景。例如,CarSim 可以与 TruckSim 或 BikeSim 同步运行,以模拟不同类型车辆在同一交通环境中的相互影响。

分布式仿真:VS Connect API 支持分布式仿真,这意味着仿真程序可以运行在不同的计算机上,通过网络( UDP)进行通信和数据交换。这对于需要大量计算资源的仿真场景特别有用,因为可以利用多台计算机的计算能力来分担仿真负载。

实时通信:通过 UDP 协议,VS Connect API 能够实现低延迟的实时数据通信。这对于需要实时交互和快速响应的仿真应用非常重要,例如实时驾驶模拟器、交通仿真系统等。

关键: carsim求解器与VS Connect方法不同的是,carsim求解器调用方法无法在运行的时候加入时间延迟以控制求解器的运行频率,一旦加入时间延迟将无法正常输出动力学信息。

正常情况下,carsim求解器的运行周期大概为0.0005s,显然我们正常的显卡是无法让仿真软件画面的更新频率达到0.0005s,当然你也可以让carsim以0.0005s的运行频率计算动力学信息,然后仿真软件以0.01s或者其他时间去获取动力学信息并更新仿真动画。Vs Connect已经兼容这种方式,并且支持多个通讯服务。

CARLA官方集成CARSIM的方法,其实就是CARSIM给UE专门开发了一个VehicleSim Dynamics插件,原理就是通过Vs Connect实现;


一、VS Connect 概念引入

名称 描述
VscNode 表示本地通信端点,并包含多个 VscLink。应用程序可以创建任意数量的 VscNode。
VscLink 表示与远程 VS Connect 节点的通信通道。要建立连接,一个 VscLink 需要与本地的 VscNode 对象关联。一个 VscNode 可以关联多个 VscLink。
VscField 通俗的讲就是要用于存放 carsim 变量参数的结构体,如变量名为“IMP_PCON_BK”,属性为“ADD 0.0”。
VscSchema VscField 的有序集合。schema 描述了发送或接收的数据更新的结构。一个 schema 可以关联多个 VscField。
VscUpdateDefinition 描述将发送哪些数据以及何时发送。VscUpdateDefinition 包括一个 VscSchema(将发送什么)和调度参数(何时发送数据)。
VscContract 两个连接节点之间的协议,描述了要发送的数据以及发送时间。VscContract 将 VscUpdateDefinition 与 VscLink 关联。Contract 是节点之间传输数据的完整描述,包括传输方向、数据结构(Schema)和数据发送的时间表。
VscUpdateData 在单一更新时间(仿真时间)内的一包仿真数据。VS Connect 的主要目的是允许应用程序交换 VscUpdateData 实例中包含的数据。VscUpdateData 的实例与 VscContract 及其关联的 VscSchema 相关联,后者描述了更新中包含的数据的结构。

二、VS Connect 通讯框架

在这里插入图片描述

三、Carsim 工程配置

1、车辆模型配置

随便选择个车辆模型

在这里插入图片描述

2、procedure配置

1)开环的节气门开度控制-油门
2)开环的制动主缸压力控制-刹车
3)开环的方向盘角度控制
4)运行条件选择Run forver

在这里插入图片描述

3、Run Control配置

1)选择Transfer to Local Windows Directory
在这里插入图片描述

2)选择工作目录,即simfile要保存的地方

在这里插入图片描述

4、受控车辆名称配置

车辆名称配置:VSC_VEHICLE_NAME Vs Vehicle 0 ,以便我们客户端定义需要控制的车辆

在这里插入图片描述

四、VS Connect Server代码

1、打开Sln工程

1、首先下载Visual Studio(我用的是2022和2019),打开Carsim项目工程路径,如:C:\Program Files (x86)\CarSim2022.1_Data\Extensions\Custom_C\wrapper_live_animation中的wrapper_live_animation.sln

在这里插入图片描述

2、代码修改

1)为什么要修改工程?
因为Carsim官方的案例只支持从Carsim输出变量,不支持输入变量到Carsim,因此需要增加接收Client发送过来的输入变量;打开vs_connect_live_animation.cpp代码进行修改

2)修改Build()函数,在创建Node节点的时候增加ReceiveUpdateCallback回调函数;

  VscNode node  = msVscApi->Node_Create_UDPIP(  mListenHost.c_str()       // listenAddress
                                              , mListenPort               // listenPort
                                              , mMaxConnections           // maxConnections
                                              , VSC_TSM_NONE              // requiredTsMode
                                              , LinkConnectCallback       // linkConnectCallback
                                              , LinkDisconnectCallback    // linkdisconnectCallback
                                              , ContractRequestCallback   // contractRequestCallback
                                              , ContractCanceledCallback  // contractCanceledCallback
                                              , SendUpdateCallback        // sendUpdateCallback
                                              , ReceiveUpdateCallback     // receiveUpdateCallback
                                              , NULL                      // pingResultsCallback
                                              , &tempResult               // out_result
                                            );

在这里插入图片描述


3)修改ContractRequestCallback()函数,增加接收Client端传输过来的变量,在if ( VSC_ROLE_SENDER != VsLiveAnimation::GetVscApi()->Contract_GetLocalRole(contract) )条件中增加此部分代码;

    //外部传入
    sLogFunc("Incomming Contract request received... ");
	//获取Link链接
    const auto  node = VsLiveAnimation::GetVscApi()->Link_GetNode(link);
	//获取车辆Handle
    auto  veh = (VSEW_VEHICLE_HANDLE)VsLiveAnimation::GetVscApi()->Node_GetAppData(node);

    if (!veh || !vsew_IsOk(veh))
    {
   
   
        sLogFunc("Contract cannot be processed because vehicle is not OK. ");
        retRes = VSC_RES_ERROR_UNAVAILABLE;
    }
    else
    {
   
   
        // Find each solver variable named in the Schema of this contract.
        auto        schema = VsLiveAnimation::GetVscApi()->Contract_GetSchema(contract);
        const auto  numFields = VsLiveAnimation::GetVscApi()->Schema_GetNumFields(schema);

        retRes = VSC_RES_ERROR_INVALID_DATA;  // We'll return this error (rejecting the Contract) if we don't find any solver variables to send.

        for (int i = 0; i < numFields; ++i)
        {
   
   
            auto field = VsLiveAnimation::GetVscApi()->Schema_GetField(schema, i);

            const auto  dataType = VsLiveAnimation::GetVscApi()->Field_GetDataType(field);
            const auto  sizeInBits = VsLiveAnimation::GetVscApi()->Field_GetElementSizeInBits(field);
            const auto  numElements = VsLiveAnimation::GetVscApi()->Field_GetNumElements(field);

            // We only support fields that are a single 64-bit floating point value. Ignore others:

            if (VSC_DATATYPE_FLOAT == dataType
                && 64 == sizeInBits
                && 1 == numElements
                )
            {
   
   
            	//获取Client发送过来的变量信息
                const auto objectName = VsLiveAnimation::GetVscApi()->Field_GetObjectName(field);
                const auto propertyName = VsLiveAnimation::GetVscApi()->Field_GetPropertyName(field);
                const auto Parameters = VsLiveAnimation::GetVscApi()->Field_GetParams(field);

                // 将const char* 转换为std::string
                string parametersString(Parameters);
                // 使用std::stringstream来提取数字部分
                stringstream ss(parametersString);

                string command;
                double Parameters_double;

                // 读取第一个字符串(例如 "ADD")
                ss >> command;
                // 读取第二个字符串(数字部分)
                ss >> Parameters_double;

                //添加变量到carsim import
                vsew_Import_Add3(veh, propertyName, Parameters_double, FALSE, "REPLACE", VSEW_IVA_DEFAULT, VSEW_IVCO_DEFAULT);
                const auto varId = vsew_Import_GetId(veh, propertyName);

                if (varId >=0)
                {
   
                          
                    cout << endl;
                    cout << "Add CARSIM IMPORT VARIABLE: "<< propertyName << " SUCCESS" << endl;
                }
                else 
                {
   
   
                    cout << endl;
                    cout << "CAN NOT ADD VARIABLE: " << propertyName << ",PLEASE CHECK THE RIGHT FORMAT <ADD 0>" << endl;
                }
            }
        }
        retRes = VSC_RES_OK;  // Returning "OK" accepts this Contract request.
    }

在这里插入图片描述


4)增加ReceiveUpdateCallback()函数,用于周期地将变量值传入Carsim(可以在SendUpdateCallback()下方的空白处加入次函数);

VscResult  ReceiveUpdateCallback(  const VscLink       link
                                 , const VscContract   contract
                                 , const VscRecord     out_data)
{
   
   
  VscResult   retRes = VSC_RES_UNDEFINED;

  if (VSC_ROLE_SENDER != VsLiveAnimation::GetVscApi()->Contract_GetLocalRole(contract))
  {
   
   
    
    const auto  node = VsLiveAnimation::GetVscApi()->Link_GetNode(link);

    auto  veh = (VSEW_VEHICLE_HANDLE)VsLiveAnimation::GetVscApi()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自动驾驶simulation

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值