• 自动驾驶仿真:python和carsim联合仿真案例



    前言

    carsim内部有许多相关联合仿真的demo,simulink、labview等等都有涉及,这里简单介绍下python和carsim联合仿真的方法,虽然carsim官方有个Steer_Control.py相关的案例,但是感觉比较冗余,这里抽出重点部分和大家交流探讨下。


    提示:以下是本篇文章正文内容,下面案例可供参考

    一、Carsim官方案例

    在carsim项目文件夹路径下,例:C:\Program Files (x86)\CarSim2022.1_Data\Extensions\Custom_Py,里面有几个案例可以参考下。
    在这里插入图片描述

    二、Carsim配置

    1、车辆模型

    1)这里的车辆模型随便选一个就行了
    在这里插入图片描述

    在这里插入图片描述

    2、procedure配置

    1)开环的节气门开度控制-油门
    2)开环的制动主缸压力控制-刹车
    3)开环的方向盘角度控制
    4)运行条件选择Run forver
    在这里插入图片描述

    3、Run Control配置

    1)选择运行模型为:Self-Contained Solvers
    在这里插入图片描述
    2)选择类型为C Wrapper,64-bit
    在这里插入图片描述
    3)按照默认选择外部的解释器
    在这里插入图片描述
    4)配置输入分别为:节气门开度,制动主缸压力,方向盘角度
    在这里插入图片描述
    5)配置输出
    在这里插入图片描述

    三、python编写

    1)第一步先找到vs_solver.py,用于调用simfile获取相关carsim dll的引用。vs_solver.py路径在C:\Program Files (x86)\CarSim2022.1_Data\Extensions\Custom_Py,我们在下面代码中会引用vs_solver.py。

    2)代码部分都很简单,一个是import vs_solver,另外一个比较重要的是simfile的路径需要填写,一般在你创建项目目录下如:C:\Program Files (x86)\CarSim2022.1_Data\simfile.sim,这个一定要根据你项目路径来填写。

    import os
    import keyboard
    import ctypes
    import vs_solver
    
    class carsim_simulation():
        def __init__(self):
            self.simfile_path = r'C:\Program Files (x86)\CarSim2022.1_Data\simfile.sim'
            self.vs = vs_solver.vs_solver()
            self.vs_dll_exist_flag = self.vs_dll_is_exist()
            self.configuration = self.vs.read_configuration(self.simfile_path)
    
        def vs_dll_is_exist(self):
            dll_path = self.vs.get_dll_path(self.simfile_path)
            if dll_path is not None and os.path.exists(dll_path):
                vs_dll = ctypes.cdll.LoadLibrary(dll_path)
                if self.vs.get_api(vs_dll):
                    exist_flag = True
                else:
                    exist_flag = False
                    print(f'can not get dll api, please check the dll {dll_path}')
            else:
                exist_flag = False
                print(f'please check dll_path or simfile_path existence or not')
            return exist_flag
    
        def get_export_array(self):
            return self.vs.copy_export_vars(carsim_sim.configuration.get('n_export'))
    
        def get_time_step(self):
            return self.configuration.get('t_step')
    
        def stop(self, t_current):
            self.vs.terminate_run(t_current)
    
    if __name__ == '__main__':
        carsim_sim = carsim_simulation()
        t_current = carsim_sim.get_time_step()
        export_array = carsim_sim.get_export_array()
        status = 0
        while status == 0:
            #更新当前时间
            t_current = t_current + carsim_sim.get_time_step()
            import_array = [0.1, 0, 0]
    3        status, export_array = carsim_sim.vs.integrate_io(t_current, import_array, export_array)
            print(f'current_x: {export_array[0]}, current_y: {export_array[6]}')
            if keyboard.is_pressed('q'):
                carsim_sim.stop(t_current)
                break
    

    四、运行carsim

    1)运行carsim等待几秒会出现黑窗,然后关掉黑窗即可。
    在这里插入图片描述

    五、运行python

    1)运行python脚本之后结果哗啦啦就出来了,就很简单。

    在这里插入图片描述

    六、补充vs_solver.py代码

    #  Copyright (c) 2019-2020, Mechanical Simulation Corporation
    # All rights reserved.
    #
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    # THE SOFTWARE.
    
    import ctypes
    import sys,string,os,re
    
    
    class vs_solver:
        def __init__(self):
            self.dll_handle = None
    
        def get_api(self, dll_handle):
            self.dll_handle = dll_handle
    
            if dll_handle.vs_run is not None and \
                            dll_handle.vs_initialize is not None and \
                            dll_handle.vs_read_configuration is not None and \
                            dll_handle.vs_integrate_io is not None and \
                            dll_handle.vs_copy_export_vars is not None and \
                            dll_handle.vs_terminate_run is not None and \
                            dll_handle.vs_error_occurred is not None and \
                            dll_handle.vs_set_opt_error_dialog is not None and \
                            dll_handle.vs_get_error_message is not None and \
                            dll_handle.vs_road_l is not None:
                dll_handle.vs_road_l.restype = ctypes.c_double
                #vsimports = (ctypes.c_double*1)()
                #vsexports = (ctypes.c_double*1)()
                #dll_handle.vs_integrate_io.argtypes = [ctypes.c_double, ctypes.byref(vsimports), ctypes.byref(vsexports)]
                ##dll_handle.vs.integrate_io.argtypes = [ctypes.c_double, ctypes.c_int]
                return True
            else:
                return False
    
        def get_char_pointer(self, python_string):
            # python version is greater or equal to 3.0 then we need to define the encoding when converting a string to
            # bytes. Once that is done we can convert the the python string to a char*.
            if sys.version_info >= (3, 0):
                char_pointer = ctypes.c_char_p(bytes(python_string, 'UTF-8'))
            else:
                char_pointer = ctypes.c_char_p(bytes(python_string))
            return char_pointer
    
        def get_parameter_value(self, line):
            index = line.find(' ')
            if index >= 0:
                return line[index:].strip()
            else:
                return None
    
        def get_dll_path(self, path_to_sim_file):
            dll_path = None
            prog_dir = None
            veh_code = None
            product_name = None
            product_ver = None
            library_name = None
            bitness_suffix = '_64' if ctypes.sizeof(ctypes.c_voidp) == 8 else '_32'
            platform = sys.platform
    
            sim_file = open(path_to_sim_file, 'r')
    
            if (platform == 'linux'):
                libfiletype = 'SOFILE'
            else:
                libfiletype = 'DLLFILE'
    
            for line in sim_file:
                if line.lstrip().startswith('PROGDIR'):
                    prog_dir = self.get_parameter_value(line)
                    if prog_dir == '.':
                      prog_dir = os.getcwd()
                elif line.lstrip().startswith(libfiletype):
                    dll_path = self.get_parameter_value(line)
                elif line.lstrip().startswith('VEHICLE_CODE'):
                    veh_code = self.get_parameter_value(line)
                elif line.lstrip().startswith('PRODUCT_ID'):
                    product_name = self.get_parameter_value(line)
                elif line.lstrip().startswith('PRODUCT_VER'):
                    product_ver = self.get_parameter_value(line)
    
            sim_file.close()
    
            if "tire" in veh_code:
                if platform == 'linux':
                  library_name = 'libtire.so.%s'%(product_ver)
                else:
                  library_name = "tire" + bitness_suffix
            elif product_name == "CarSim":
                if platform == 'linux':
                  library_name = 'libcarsim.so.%s'%(product_ver)
                else:
                  library_name = "carsim" + bitness_suffix
            elif product_name == "TruckSim":
                if platform == 'linux':
                  library_name = 'libtrucksim.so.%s'%(product_ver)
                else:
                  library_name = "trucksim" + bitness_suffix
            elif product_name == "BikeSim":
                if platform == 'linux':
                  library_name = 'libbikesim.so.%s'%(product_ver)
                else:
                  library_name = "bikesim" + bitness_suffix
            else:
                if platform == 'linux':
                  library_name = 'libcarsim.so.%s'%(product_ver)
                else:
                  library_name = veh_code + bitness_suffix
    
            if dll_path is None:
                if sys.platform == 'linux':
                  dll_path = os.path.join(prog_dir, library_name); 
                else:
                  dll_path = os.path.join(prog_dir, "Programs", "Solvers", library_name + ".dll")
            return dll_path
    
        def run(self, path_to_sim_file):
            error_occurred = 1
            path_to_sim_file_ptr = self.get_char_pointer(path_to_sim_file)
    
            if path_to_sim_file_ptr is not None:
                error_occurred = self.dll_handle.vs_run(path_to_sim_file_ptr)
    
            return error_occurred
            
        def print_error(self):
          error_string = ctypes.c_char_p(self.dll_handle.vs_get_error_message())
          print(error_string.value.decode('ascii'))
    
        def read_configuration(self, path_to_sim_file):
            path_to_sim_file_ptr = self.get_char_pointer(path_to_sim_file)
            platform = sys.platform
            if path_to_sim_file_ptr is not None:
                if platform == 'linux':
                  ref_n_import = ctypes.c_long()
                  ref_n_export = ctypes.c_longlong()
                else:
                  ref_n_import = ctypes.c_int32()
                  ref_n_export = ctypes.c_int64()
                ref_t_start = ctypes.c_double()
                ref_t_stop = ctypes.c_double()
                ref_t_step = ctypes.c_double()
                self.dll_handle.vs_read_configuration(path_to_sim_file_ptr,
                                                      ctypes.byref(ref_n_import),
                                                      ctypes.byref(ref_n_export),
                                                      ctypes.byref(ref_t_start),
                                                      ctypes.byref(ref_t_stop),
                                                      ctypes.byref(ref_t_step))
                configuration = {'n_import': ref_n_import.value,
                                 'n_export': ref_n_export.value,
                                 't_start': ref_t_start.value,
                                 't_stop': ref_t_stop.value,
                                 't_step': ref_t_step.value}
                return configuration
    
        def copy_export_vars(self, n_export):
            export_array = (ctypes.c_double * n_export)()
            self.dll_handle.vs_copy_export_vars(ctypes.cast(export_array, ctypes.POINTER(ctypes.c_double)))
            export_list = [export_array[i] for i in range(n_export)]
            return export_list
    
        def get_road_l(self, x, y):
            x_c_double = ctypes.c_double(x)
            y_c_double = ctypes.c_double(y)
            c_double_return = self.dll_handle.vs_road_l(x_c_double, y_c_double)
            return float(c_double_return)
    
        def integrate_io(self, t_current, import_array, export_array):
            t_current_c_double = ctypes.c_double(t_current)
            import_c_double_array = (ctypes.c_double * len(import_array))(*import_array)
            export_c_double_array = (ctypes.c_double * len(export_array))(*export_array)
    
            c_integer_return = self.dll_handle.vs_integrate_io(t_current_c_double,
                                                               ctypes.byref(import_c_double_array),
                                                               ctypes.byref(export_c_double_array))
    
            export_array = [export_c_double_array[i] for i in range(len(export_array))]
            return c_integer_return, export_array
    
        def initialize(self, t):
            t_c_double = ctypes.c_double(t)
            self.dll_handle.vs_initialize(t_c_double)
    
        def terminate_run(self, t):
            t_c_double = ctypes.c_double(t)
            self.dll_handle.vs_terminate_run(t_c_double)
    

    总结

    1、这里关于solvers的细节其实都没说,因为里面确实也没什么内容好讲的,本质就是调用carsim.dll,如果你需要更多的函数解析其实可以看vs_api.h,路径在C:\Program Files (x86)\CarSim2022.1_Data\Extensions\Custom_C\common,具体内容如下图所示。

    在这里插入图片描述


  • 相关阅读:
    10、正则表达式 (笔试题、语法规则、正则对象方法、正则实例属性、支持正则表达式的String对象的方法、贪婪匹配与非贪婪匹配)
    [dx12]Flip, VSync 和 GSync
    [附源码]计算机毕业设计JAVA基于web旅游网站的设计与实现
    Linux学习7—软件管理
    嵌入式学习笔记(42)SD卡的编程接口
    编译安装apache
    超强视频超分AI算法,从此只看高清视频
    Gstreamer应用开发实战指南(五)
    Linux 配置Tomcat
    图像语义分割 pytorch复现U2Net图像分割网络详解
  • 原文地址:https://blog.csdn.net/zataji/article/details/139455960