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

2024-06-15 20:28

本文主要是介绍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”。
VscSchemaVscField 的有序集合。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);//获取车辆Handleauto  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::stringstring parametersString(Parameters);// 使用std::stringstream来提取数字部分stringstream ss(parametersString);string command;double Parameters_double;// 读取第一个字符串(例如 "ADD")ss >> command;// 读取第二个字符串(数字部分)ss >> Parameters_double;//添加变量到carsim importvsew_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()->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){const auto propertyName = VsLiveAnimation::GetVscApi()->Field_GetPropertyName(field);double* fieldData = (double*)VsLiveAnimation::GetVscApi()->Record_GetFieldValue(out_data, i);//get carsim variable idconst auto varId = vsew_Import_GetId(veh, propertyName);if (varId >= 0){//set init import valuevsew_Import_SetValue(veh, varId, *fieldData);}}}retRes = VSC_RES_OK;  // Returning "OK" accepts this Contract request.}}return retRes;
}

VS Connect Server就加这部分代码。


五、VS Connect Client代码

1、函数的调用关系

代码已上传资源,请在CSDN搜索:carsim vs-connect-client代码
在这里插入图片描述

2、carsim_variable代码

1)这里就是用来实现carsim变量定义,carsim输入变量请求,carsim输出变量获取;

2)Field变量定义的规则
incoming
在这里插入图片描述

outgoing
在这里插入图片描述


import ctypes
from ctypes import *import VsConnectAPIvscapi = VsConnectAPI.vsc_dll.VsConnectApi_Get  # VsConnectApi_GetDefaultvscapi.argtypes=[ctypes.c_int]
vscapi.restype = ctypes.POINTER(VsConnectAPI.Vsc_API)api_ver3 = vscapi(3)
api_ver3_contents = api_ver3.contentsdef StrToChar(string):string_utf8 = string.encode('UTF-8')string_buffer = ctypes.create_string_buffer(string_utf8)return ctypes.cast(string_buffer, c_char_p)def ResetData():global gxglobal gyglobal gzglobal gpitchglobal gyawglobal grollref_x = ctypes.POINTER(ctypes.c_double)api_ver3_contents.InvalidateDouble(ref_x(ctypes.c_double(gx)))ref_y = ctypes.POINTER(ctypes.c_double)api_ver3_contents.InvalidateDouble(ref_y(ctypes.c_double(gy)))ref_z = ctypes.POINTER(ctypes.c_double)api_ver3_contents.InvalidateDouble(ref_z(ctypes.c_double(gz)))ref_pitch = ctypes.POINTER(ctypes.c_double)api_ver3_contents.InvalidateDouble(ref_pitch(ctypes.c_double(gpitch)))ref_yaw = ctypes.POINTER(ctypes.c_double)api_ver3_contents.InvalidateDouble(ref_yaw(ctypes.c_double(gyaw)))ref_roll = ctypes.POINTER(ctypes.c_double)api_ver3_contents.InvalidateDouble(ref_roll(ctypes.c_double(gyaw)))def SendUpdate(out_data):# IMP_THROTTLE_ENGINEfieldData = ctypes.cast(api_ver3_contents.RecordGetFieldValue(out_data, 0), ctypes.POINTER(ctypes.c_double))fieldData[0] = 0.1fieldData1 = ctypes.cast(api_ver3_contents.RecordGetFieldValue(out_data, 1), ctypes.POINTER(ctypes.c_double))fieldData1[0] = 0def ReceiveUpdate(incomingData):global gxglobal gyglobal gzglobal gpitchglobal gyawglobal grollgx = ((ctypes.cast(api_ver3_contents.RecordGetFieldValue(incomingData, 0), ctypes.POINTER(ctypes.c_double))).contents).value  # return pointer doublegy = ((ctypes.cast(api_ver3_contents.RecordGetFieldValue(incomingData, 1), ctypes.POINTER(ctypes.c_double))).contents).value  # return pointer doublegz = ((ctypes.cast(api_ver3_contents.RecordGetFieldValue(incomingData, 2), ctypes.POINTER(ctypes.c_double))).contents).value  # return pointer doublegpitch = ((ctypes.cast(api_ver3_contents.RecordGetFieldValue(incomingData, 3), ctypes.POINTER(ctypes.c_double))).contents).value  # return pointer doublegyaw = ((ctypes.cast(api_ver3_contents.RecordGetFieldValue(incomingData, 4), ctypes.POINTER(ctypes.c_double))).contents).value  # return pointer doublegroll = ((ctypes.cast(api_ver3_contents.RecordGetFieldValue(incomingData, 5), ctypes.POINTER(ctypes.c_double))).contents).value  # return pointer doubledef PrintStatementWhenConnected():print("Dist x: %.2f" % gx, end=" ") if api_ver3_contents.IsValidDouble(gx) \else print("Dist x:?")print("Dist y: %.2f" % gy, end=" ") if api_ver3_contents.IsValidDouble(gy) \else print("Dist y:?")print("Dist z: %.2f" % gz, end=" ") if api_ver3_contents.IsValidDouble(gz) \else print("Dist z:?")print("pitch: %.2f" % gpitch, end=" ") if api_ver3_contents.IsValidDouble(gpitch) \else print("pitch:?")print("yaw: %.2f" % gyaw) if api_ver3_contents.IsValidDouble(gyaw) \else print("yaw:?")print("roll: %.2f" % groll) if api_ver3_contents.IsValidDouble(groll) \else print("roll:?")# define variables
gx = 0.0
gy = 0.0
gz = 0.0gpitch = 0.0
gyaw = 0.0
groll = 0.0#定义Carsim输出变量
incoming_variables = [{"objectName": StrToChar("Vs Vehicle 0"),  "propertyName": StrToChar("Xo"), "propertyParam": StrToChar("")},{"objectName": StrToChar("Vs Vehicle 0"),  "propertyName": StrToChar("Yo"), "propertyParam": StrToChar("")},{"objectName": StrToChar("Vs Vehicle 0"),  "propertyName": StrToChar("Zo"), "propertyParam": StrToChar("")},{"objectName": StrToChar("Vs Vehicle 0"),  "propertyName": StrToChar("pitch"), "propertyParam": StrToChar("")},{"objectName": StrToChar("Vs Vehicle 0"),  "propertyName": StrToChar("Yaw"), "propertyParam": StrToChar("")},{"objectName": StrToChar("Vs Vehicle 0"),  "propertyName": StrToChar("roll"), "propertyParam": StrToChar("")},
]#定义Carsim输入变量
outgoing_variables = [{"objectName": StrToChar("Vs Vehicle 0"),  "propertyName": StrToChar("IMP_THROTTLE_ENGINE"), "propertyParam": StrToChar("ADD 0.0")},{"objectName": StrToChar("Vs Vehicle 0"),  "propertyName": StrToChar("IMP_PCON_BK"), "propertyParam": StrToChar("ADD 0.0")}
]

3、VsConnect_demo代码

1)这里就是client端的主代码,具体作用请查看《二、VS Connect 通讯框架》

import sys
import platform
import ctypes
from ctypes import *
import timeimport VsConnectAPI
from VsConnectAPI import *
import carsim_variablecurrent_os = platform.system()
if (current_os == "Linux"):import termiosimport selectimport atexit# save the terminal settingsfd = sys.stdin.fileno()new_term = termios.tcgetattr(fd)old_term = termios.tcgetattr(fd)# new terminal setting unbufferednew_term[3] = (new_term[3] & ~termios.ICANON & ~termios.ECHO)# switch to normal terminaldef set_normal_term():termios.tcsetattr(fd, termios.TCSAFLUSH, old_term)# switch to unbuffered terminaldef set_curses_term():termios.tcsetattr(fd, termios.TCSAFLUSH, new_term)def kbhit():dr,dw,de = select.select([sys.stdin], [], [], 0)return dr != []def getch():return sys.stdin.read(1).encode('utf-8')else:import msvcrtdef kbhit():return msvcrt.kbhit()def getch():return msvcrt.getch()gWantConnection = True
gQuit = Falseif (current_os == "Linux"):import ctypes.utilpathlib = ctypes.util.find_library("c")libc = ctypes.cdll.LoadLibrary(pathlib)vsprintf = libc.vsprintf
else:vsprintf = ctypes.cdll.msvcrt.vsprintfdef logcallback_fnc(loglevel, node, link, contract, format, argptr):logPrefix = ""byteString = create_string_buffer(4096)realString = ""if (loglevel == VsConnectAPI.VscLogLevel.VSC_LOG_ERROR.value):logPrefix = "ERROR"elif (loglevel == VsConnectAPI.VscLogLevel.VSC_LOG_WARNING.value):logPrefix = "WARNING"else:logPrefix = "Log"byteString = "VS Connect " + logPrefixrealString += byteString.value.decode("utf-8")if (node or link or contract):realString += ","if (node):byteString = " N-" + str(hex(ctypes.addressof(node)))realString += byteString.value.decode("utf-8")if (link):byteString = " L-" + str(hex(ctypes.addressof(link)))realString += byteString.value.decode("utf-8")if (contract):byteString = " C-" + str(hex(ctypes.addressof(contract)))realString += byteString.value.decode("utf-8")realString += ": "# python casted format and argptr to ints. recast to c_void_pvsprintf(byteString,  ctypes.cast(format, c_void_p), ctypes.cast(argptr, c_void_p))realString += byteString.value.decode("utf-8")print(realString)return len(realString)def ProcessKeyboardInput():if kbhit():pressedKey = getch()global gWantConnectionglobal gQuitif (pressedKey == b'q') or (pressedKey == b'Q'):gWantConnection = FalsegQuit = Trueelif (pressedKey == b'd') or (pressedKey == b'D'):gWantConnection = Falseelif (pressedKey == b'c') or (pressedKey == b'C'):gWantConnection = Trueelse:print("Unknown command.\n")print("Press C to connect, D to disconnect, Q to quit.\n")@CFUNCTYPE(ctypes.c_int, ctypes.POINTER(VsConnectAPI.VscLink), ctypes.POINTER(VsConnectAPI.VscContract), ctypes.POINTER(VsConnectAPI.VscRecord))
def sendupdatecallback_fnc(link, contract, out_data):if __debug__:pass# schema = api_ver3_contents.ContractGetSchema(contract)  # check this# field = api_ver3_contents.SchemaGetField(schema, 0)# assert (1 == api_ver3_contents.SchemaGetNumFields(schema))# assert (1 == api_ver3_contents.FieldGetDataTypes(field))# assert (1 == api_ver3_contents.FieldGetNumElements(field))carsim_variable.SendUpdate(out_data)return int(VsConnectAPI.VscResult.VSC_RES_OK)@CFUNCTYPE(ctypes.c_int, ctypes.POINTER(VsConnectAPI.VscLink), ctypes.POINTER(VsConnectAPI.VscContract), ctypes.POINTER(VsConnectAPI.VscRecord))
def receiveupdatecallback_fnc(link, contract, incomingData):if __debug__:pass# schema = api_ver3_contents.ContractGetSchema(contract)# assert (2 == api_ver3_contents.SchemaGetNumFields(schema))# assert (1 == api_ver3_contents.FieldGetDataTypes(api_ver3_contents.SchemaGetField(schema, 0)))# assert (1 == api_ver3_contents.FieldGetNumElements(api_ver3_contents.SchemaGetField(schema, 0)))# assert (1 == api_ver3_contents.FieldGetDataTypes(api_ver3_contents.SchemaGetField(schema, 1)))# assert (1 == api_ver3_contents.FieldGetNumElements(api_ver3_contents.SchemaGetField(schema, 1)))carsim_variable.ReceiveUpdate(incomingData)return int(VsConnectAPI.VscResult.VSC_RES_OK)def get_VsConnectApi():# accessing api_ver3vscapi = VsConnectAPI.vsc_dll.VsConnectApi_Get  # VsConnectApi_GetDefaultvscapi.argtypes = [ctypes.c_int]vscapi.restype = ctypes.POINTER(VsConnectAPI.Vsc_API)# initialize the VS connect library.api_ver3 = vscapi(3)api_ver3_contents = api_ver3.contentsreturn api_ver3_contentsdef create_link(address, portnum):address_buf = address.encode('UTF-8')address_char = ctypes.cast(address_buf, c_char_p)portnum_int = ctypes.c_int(portnum)glink = api_ver3_contents.LinkCreateUDPIP(address_char, portnum_int, cast(None, ctypes.POINTER(c_int)))return glinkdef create_SchemaInitField(variables):Schema = api_ver3_contents.SchemaCreate((len(variables)))for i, variable in enumerate(variables):api_ver3_contents.SchemaInitField(Schema, i, 1, 64, 1, variable.get("objectName"), variable.get("propertyName"), variable.get("propertyParam"), 0, 0, 0)return Schemadef create_IncomingContract(glink, Schema, UpdatePeriod_ms):to_c_double= ctypes.c_doubleUpdatePeriod = to_c_double(UpdatePeriod_ms)UpdateDef = api_ver3_contents.UpdateDefinitionCreate(Schema, 1, UpdatePeriod)  #dfefind update periodapi_ver3_contents.LinkCreateIncomingContract(glink, UpdateDef, receiveupdatecallback_fnc, 0, -1, None)return UpdateDefdef create_OutgoingContract(glink, Schema, UpdatePeriod_ms):to_c_double= ctypes.c_doubleUpdatePeriod = to_c_double(UpdatePeriod_ms)UpdateDef = api_ver3_contents.UpdateDefinitionCreate(Schema, 1, UpdatePeriod)  #dfefind update periodapi_ver3_contents.LinkCreateOutgoingContract(glink, UpdateDef, sendupdatecallback_fnc, 0, -1, None)return UpdateDefdef release_DataHandle(Schema, UpdateDef):ref_Schema = ctypes.POINTER(ctypes.POINTER(VsConnectAPI.VscSchema))ref_UpdateDef = ctypes.POINTER(ctypes.POINTER(VsConnectAPI.VscUpdateDefinition))api_ver3_contents.SchemaHandleRelease(ref_Schema(Schema))api_ver3_contents.UpdateDefinitionHandleRelease(ref_UpdateDef(UpdateDef))def sync_LinkConnect(node, glink):#If it is not synchronized, synchronize itif ((VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_UNCONNECTED.value == connStat) and gWantConnection):res = api_ver3_contents.LinkConnectAsync(node, glink)res_val = api_ver3_contents.DescribeResult(res)print('Initiating connection: %s' % res_val.decode("utf-8"))elif (((VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_CONNECTED.value == connStat) and not gWantConnection) or \(( VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_CONNECTING.value == connStat) and not gWantConnection)):res = api_ver3_contents.LinkDisconnect(glink)print("Initiating disconnection: %s", api_ver3_contents.DescribeResult(res))def run_NodeService(localSimTime):localSimTimeDouble = ctypes.c_doublelocalSimTimeInput = localSimTimeDouble(localSimTime)timeDilationDouble = ctypes.c_doubletimeDilation = timeDilationDouble(1.0)processEventBool = ctypes.c_boolprocessEventInput = processEventBool(True)api_ver3_contents.NodeService(node, localSimTimeInput, timeDilation, processEventInput)def release_NetWorkHandle(glink, node):ref_glink = ctypes.POINTER(ctypes.POINTER(VsConnectAPI.VscLink))ref_node = ctypes.POINTER(ctypes.POINTER(VsConnectAPI.VscNode))api_ver3_contents.LinkHandleRelease(ref_glink(glink))api_ver3_contents.NodeHandleRelease(ref_node(node))api_ver3_contents.ShutDown()# main start here...api_ver3_contents = get_VsConnectApi()# Set logging function
VsConnectAPI.SetLogFuncPtr(logcallback_fnc)api_ver3_contents.Init()node = api_ver3_contents.NodeCreateUDPIP(   None, #None则自动选择IPv4 ip0,  #0则自动通过GetDefaultListenPort()获取-1,0, cast(None, VscLinkConnectedFunc_t), cast(None, VscLinkDisconnectedFunc_t), cast(None, VscProcessContractRequestFunc_t), cast(None, VscContractCanceledFunc_t), sendupdatecallback_fnc, receiveupdatecallback_fnc, cast(None, VscPingResultFunc_t), cast(None, ctypes.POINTER(c_int)))glink = create_link("127.0.0.1", 4380)update_period = 50# this can be loop?
incomingSchema = create_SchemaInitField(carsim_variable.incoming_variables)
incomingUpdateDef = create_IncomingContract(glink, incomingSchema, update_period)
release_DataHandle(incomingSchema, incomingUpdateDef)# now create outgoing contract
# this can be loop?
outgoingSchema = create_SchemaInitField(carsim_variable.outgoing_variables)
outgoingUpdateDef = create_OutgoingContract(glink, outgoingSchema, update_period)
release_DataHandle(outgoingSchema, outgoingUpdateDef)print("Press C to connect, D to disconnect, or Q to quit.")# carsim.ResetData()timeStep = update_period / 1000
timeStepCount = 0
localSimTime = 0.0if (current_os == "Linux"):atexit.register(set_normal_term)set_curses_term()# # while statement will wrap the following statements
while (not gQuit):timeStepCount += 1connStat = api_ver3_contents.LinkGetConnectionStatus(glink)#sync link connect sync_LinkConnect(node, glink)#运行NodeService,数据收发/回调参数处理run_NodeService(localSimTime)if (0 == timeStepCount % 20):  # reduce output to every nth iterationprint("%.2f" % localSimTime)if (connStat == VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_UNCONNECTED.value):print("Disconnected ")elif (connStat == VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_CONNECTING.value):print("Connecting ")elif (connStat == VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_CONNECTED.value):# print("Connected. ")carsim_variable.PrintStatementWhenConnected()elif (connStat == VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_ERROR.value):print("ERROR ")elif (connStat == VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_DISCONNECTING.value):print("Disconnectcing ")else:print("************** ")# a primative timing mechanism.  Should be used with this example only.time.sleep(timeStep)localSimTime += timeStepProcessKeyboardInput()print("Program exiting, disconnecting link (if it's connected).")
api_ver3_contents.LinkDisconnect(glink)while (VsConnectAPI.VscConnectionStatus.VSC_CONNSTAT_UNCONNECTED.value != api_ver3_contents.LinkGetConnectionStatus(glink)):print(".")api_ver3_contents.NodeService(node, api_ver3_contents.GetInvalidSimtime(), 1, True)release_NetWorkHandle(glink, node)

六、Vs Connect联合仿真

1、Server代码编译

在这里插入图片描述
在这里插入图片描述

编译之后有个wrapper_live_animation_Release_x64.exe
在这里插入图片描述

2、运行carsim

在这里插入图片描述

3、运行Server端

.\wrapper_live_animation_Release_x64.exe “C:\Program Files (x86)\CarSim2022.1_Data\simfile.sim” -host “127.0.0.1” -port 4380

IP 和端口号都在Client代码中定义了
在这里插入图片描述
运行Server之后,显示连接数量为0
在这里插入图片描述

4、运行Client端

成功输出我定义的变量,哗啦啦的!

在这里插入图片描述


综上,完成Carsim Vs Connect demo开发;

这篇关于Carsim高级开发:VS Connect通讯开发指南的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1064494

相关文章

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设

OpenHarmony鸿蒙开发( Beta5.0)无感配网详解

1、简介 无感配网是指在设备联网过程中无需输入热点相关账号信息,即可快速实现设备配网,是一种兼顾高效性、可靠性和安全性的配网方式。 2、配网原理 2.1 通信原理 手机和智能设备之间的信息传递,利用特有的NAN协议实现。利用手机和智能设备之间的WiFi 感知订阅、发布能力,实现了数字管家应用和设备之间的发现。在完成设备间的认证和响应后,即可发送相关配网数据。同时还支持与常规Sof

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

Retrieval-based-Voice-Conversion-WebUI模型构建指南

一、模型介绍 Retrieval-based-Voice-Conversion-WebUI(简称 RVC)模型是一个基于 VITS(Variational Inference with adversarial learning for end-to-end Text-to-Speech)的简单易用的语音转换框架。 具有以下特点 简单易用:RVC 模型通过简单易用的网页界面,使得用户无需深入了

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta