`

闵大荒之旅(九) ----- 源码初步“翻译”

阅读更多

上一回分析到,第一阶段的主要任务是改写detect函数,那么本次就是先将detect函数修改成C语言版本!

 

先上代码,下列代码仍有几个变量没进行修改,其中包括blockCacheFlags, blockCache,grad,qangle(Mat类型),这些mat类型的矩阵,考虑直接传入cuda PtrStep类型或者用二维数组传入

 

void mynormalizeBlockHistogram(float* _hist, size_t blockHistogramSize, double Threshold)
{
	    float* hist = &_hist[0];

    size_t i, sz = blockHistogramSize;

    float sum = 0;
    for( i = 0; i < sz; i++ )
        sum += hist[i]*hist[i];

    float scale = 1.f/(std::sqrt(sum)+sz*0.1f), thresh = (float)Threshold;

    for( i = 0, sum = 0; i < sz; i++ )
    {
        hist[i] = std::min(hist[i]*scale, thresh);
        sum += hist[i]*hist[i];
    }
    scale = 1.f/(std::sqrt(sum)+1e-3f);
    for( i = 0; i < sz; i++ )
        hist[i] *= scale;
}




const float* mygetBlock(int*ymaxCache, int blockHistogramSize, int blockCache_h, int cacheStride_w, int cacheStride_h, int pt_x, int pt_y, int imgoffset_x, int imgoffset_y, float* buf, bool useCache, Mat_<uchar> blockCacheFlags, Mat_<float> blockCache, int count1, int count2, int count4, Mat grad, Mat qangle,
						size_t* gradOf, size_t* qangleOf, int* histOf1, int* histOf2, int* histOf3, int* histOf4, 
						float* histWeights1, float* histWeights2, float* histWeights3, float* histWeights4, float* gradweight )
{//blockCacheFlags, blockCache待处理
	  float* blockHist = buf;
	  //int blockSize_w = 16, blockSize_h = 16;
	  pt_x += imgoffset_x;
	  pt_y += imgoffset_y;
	  //cout << "1" << endl; 
	   if( useCache )
	   {
		   //int cacheSize_w = (grad_w - blockSize_w)/cacheStride_w + 1;
		   //int cacheSize_h = (winSize_h/cacheStride_h) + 1; 
		   int cacheIdx_x = pt_x/cacheStride_w;
		   int cacheIdx_y = (pt_y/cacheStride_h) % blockCache_h;
		   if( pt_y != ymaxCache[cacheIdx_y] )
		   {
            Mat_<uchar> cacheRow = blockCacheFlags.row(cacheIdx_y);
			//cout << cacheIdx_y << endl;
            cacheRow = (uchar)0;
            ymaxCache[cacheIdx_y] = pt_y;
		    }
		   //cout << "2" << endl; 
        blockHist = &blockCache[cacheIdx_y][cacheIdx_x*blockHistogramSize];
        uchar& computedFlag = blockCacheFlags(cacheIdx_y, cacheIdx_x);
        if( computedFlag != 0 )
            return blockHist;
        computedFlag = (uchar)1; // set it at once, before actual computing
	   }

	    int k, C1 = count1, C2 = count2, C4 = count4;
		const float* gradPtr = (const float*)(grad.data + grad.step*pt_y) + pt_x*2;
		const uchar* qanglePtr = qangle.data + qangle.step*pt_y + pt_x*2;

	    for( k = 0; k < blockHistogramSize; k++ )
			 blockHist[k] = 0.f;
		for( k = 0; k < C1; k++ )
		{
			//const PixData& pk = _pixData[k];
			const float* a = gradPtr + gradOf[k];
			float w = gradweight[k]*histWeights1[k];
			const uchar* h = qanglePtr + qangleOf[k];
			int h0 = h[0], h1 = h[1];
			float* hist = blockHist + histOf1[k];
			float t0 = hist[h0] + a[0]*w;
			float t1 = hist[h1] + a[1]*w;
			hist[h0] = t0; hist[h1] = t1;
		}
		//cout << "3" << endl;
		
    for( ; k < C2; k++ )
    {
        //const PixData& pk = _pixData[k];
        const float* a = gradPtr + gradOf[k];
        float w, t0, t1, a0 = a[0], a1 = a[1];
        const uchar* h = qanglePtr + qangleOf[k];
        int h0 = h[0], h1 = h[1];

        float* hist = blockHist + histOf1[k];
        w = gradweight[k] * histWeights1[k];
        t0 = hist[h0] + a0*w;
        t1 = hist[h1] + a1*w;
        hist[h0] = t0; hist[h1] = t1;

        hist = blockHist + histOf2[k];
        w = gradweight[k]*histWeights2[k];
        t0 = hist[h0] + a0*w;
        t1 = hist[h1] + a1*w;
        hist[h0] = t0; hist[h1] = t1;
    }
	//cout << "4" << endl;
	for( ; k < C4; k++ )
    {
        //const PixData& pk = _pixData[k];
        const float* a = gradPtr + gradOf[k];
        float w, t0, t1, a0 = a[0], a1 = a[1];
        const uchar* h = qanglePtr + qangleOf[k];
        int h0 = h[0], h1 = h[1];

        float* hist = blockHist + histOf1[k];
        w = gradweight[k]*histWeights1[k];
        t0 = hist[h0] + a0*w;
        t1 = hist[h1] + a1*w;
        hist[h0] = t0; hist[h1] = t1;

        hist = blockHist + histOf2[k];
        w = gradweight[k]*histWeights2[k];
        t0 = hist[h0] + a0*w;
        t1 = hist[h1] + a1*w;
        hist[h0] = t0; hist[h1] = t1;

        hist = blockHist + histOf3[k];
        w = gradweight[k]*histWeights3[k];
        t0 = hist[h0] + a0*w;
        t1 = hist[h1] + a1*w;
        hist[h0] = t0; hist[h1] = t1;

        hist = blockHist + histOf4[k];
        w = gradweight[k]*histWeights4[k];
        t0 = hist[h0] + a0*w;
        t1 = hist[h1] + a1*w;
        hist[h0] = t0; hist[h1] = t1;
    }
	//cout << "5" << endl; 
	    mynormalizeBlockHistogram(blockHist, blockHistogramSize, 0.2);

	/*for(int i = 0; i < blockHistogramSize; i ++)
	{
		cout << blockHist[i] << " ";
	}
	cout << endl;
	*/

	  return blockHist;
}


void HOGDescriptor::detect(const Mat& img,
    vector<Point>& hits, vector<double>& weights, double hitThreshold,
    Size winStride, Size padding, const vector<Point>& locations) const
{
    hits.clear();
    if( svmDetector.empty() )
        return;

    if( winStride == Size() )
        winStride = cellSize;
    Size cacheStride(gcd(winStride.width, blockStride.width),
                     gcd(winStride.height, blockStride.height));
    size_t nwindows = locations.size();
    padding.width = (int)alignSize(std::max(padding.width, 0), cacheStride.width);
    padding.height = (int)alignSize(std::max(padding.height, 0), cacheStride.height);
    Size paddedImgSize(img.cols + padding.width*2, img.rows + padding.height*2);
	double start = (double)getTickCount();   //time!!!
    HOGCache cache(this, img, padding, padding, nwindows == 0, cacheStride);
	double t = ((double)getTickCount() - start)/getTickFrequency();  

    if( !nwindows )
        nwindows = cache.windowsInImage(paddedImgSize, winStride).area();

    const HOGCache::BlockData* blockData = &cache.blockData[0];

    int nblocks = cache.nblocks.area();
    int blockHistogramSize = cache.blockHistogramSize;
    size_t dsize = getDescriptorSize();

    double rho = svmDetector.size() > dsize ? svmDetector[dsize] : 0;
    vector<float> blockHist(blockHistogramSize);
	
	//*****define para*****
	int paddedImgSize_w = paddedImgSize.width, paddedImgSize_h = paddedImgSize.height;
	int winSize_w = winSize.width, winSize_h = winSize.height;
	int winStride_w = winStride.width, winStride_h = winStride.height;
	int count = svmDetector.size();
	float* svmDetect = (float*)malloc(sizeof(float) * count);
    for (int i = 0; i < count;i++)
    {
		svmDetect[i] = svmDetector[i];
    }
	count = cache.blockData.size();
	int* blockdata_histOfs = (int*)malloc(sizeof(int) * count);
	int* blockdata_imgOffsetx = (int*)malloc(sizeof(int) * count); 
	int* blockdata_imgOffsety = (int*)malloc(sizeof(int) * count);
    for (int i = 0; i < count;i++)
    {
		blockdata_histOfs[i] = cache.blockData[i].histOfs;
		blockdata_imgOffsetx[i] = cache.blockData[i].imgOffset.x;
		blockdata_imgOffsety[i] = cache.blockData[i].imgOffset.y;
    }
	count = cache.pixData.size();
	size_t* gradOf = (size_t*)malloc(sizeof(size_t) * count);
	size_t* qangleOf = (size_t*)malloc(sizeof(size_t) * count);
	int* histOf1 = (int*)malloc(sizeof(int) * count);
	int* histOf2 = (int*)malloc(sizeof(int) * count);
	int* histOf3 = (int*)malloc(sizeof(int) * count);
	int* histOf4 = (int*)malloc(sizeof(int) * count);
	float* histWeights1 = (float*)malloc(sizeof(float) * count);
	float* histWeights2 = (float*)malloc(sizeof(float) * count);
	float* histWeights3 = (float*)malloc(sizeof(float) * count);
	float* histWeights4 = (float*)malloc(sizeof(float) * count);
	float* gradweight = (float*)malloc(sizeof(float) * count);
	for(int i = 0; i < count; i ++)
	{
		gradOf[i] = cache.pixData[i].gradOfs;
		qangleOf[i] = cache.pixData[i].qangleOfs;
		histOf1[i] = cache.pixData[i].histOfs[0];
		histOf2[i] = cache.pixData[i].histOfs[1];
		histOf3[i] = cache.pixData[i].histOfs[2];
		histOf4[i] = cache.pixData[i].histOfs[3];
		histWeights1[i] = cache.pixData[i].histWeights[0];
		histWeights2[i] = cache.pixData[i].histWeights[1];
		histWeights3[i] = cache.pixData[i].histWeights[2];
		histWeights4[i] = cache.pixData[i].histWeights[3];
		gradweight[i] = cache.pixData[i].gradWeight;
	}



	count = nwindows * nblocks;
	float* myweights = (float*)malloc(sizeof(float) * count);
	int* hits_x = (int*)malloc(sizeof(int) * count);
	int* hits_y = (int*)malloc(sizeof(int) * count); 
	count = cache.ymaxCached.size();
	int* ymaxCache = (int*)malloc(sizeof(int) * count);
	for(int i = 0; i < count; i ++)
	{
		ymaxCache[i] = cache.ymaxCached[i];
	}
	count = blockHistogramSize;
	float* block_Hist = (float*)malloc(sizeof(float) * count);
	for(int i = 0; i < count; i ++)
	{
		block_Hist[i] = blockHist[i];
	}
	//*********************


    for( size_t i = 0; i < nwindows; i++ )
    {
		
		//****************************改*****************************
		 int pt0_x, pt0_y;
		//***getwindows***
		 int nwindowsX = (paddedImgSize_w - winSize_w)/winStride_w + 1;
		 int y = (int)i / nwindowsX;
		 int x = (int)i - nwindowsX*y;
		 pt0_x = x*winStride_w;
		 pt0_y = y*winStride_h;
		//****************
		 double s = rho;
         const float* svmVec = &svmDetect[0];
         int j, k;
		 for( j = 0; j < nblocks; j++, svmVec += blockHistogramSize )
		 {
			 int pt_x = pt0_x + blockdata_imgOffsetx[j];
			 int pt_y = pt0_y + blockdata_imgOffsety[j];
			 if(pt_x < 0 || pt_y < 0)
			 {
				//cout << pt_x << endl;
				//cout << pt_y << endl;
			 }

			 const float* vec = mygetBlock(ymaxCache, blockHistogramSize, cache.blockCache.rows, cache.cacheStride.width, cache.cacheStride.height, pt_x, pt_y, cache.imgoffset.x, cache.imgoffset.y, block_Hist, true, cache.blockCacheFlags, cache.blockCache, cache.count1, cache.count2, cache.count4, cache.grad, cache.qangle,
				 gradOf, qangleOf, histOf1, histOf2, histOf3, histOf4, histWeights1, histWeights2, histWeights3, histWeights4, gradweight);
			
			  for( k = 0; k <= blockHistogramSize - 4; k += 4 )
                s += vec[k]*svmVec[k] + vec[k+1]*svmVec[k+1] +
                    vec[k+2]*svmVec[k+2] + vec[k+3]*svmVec[k+3];
              for( ; k < blockHistogramSize; k++ )
                s += vec[k]*svmVec[k];
		  }
			  //cout << s << endl;
			  if( s >= hitThreshold )
			    {
					Point pt0;
					pt0.x = pt0_x;
					pt0.y = pt0_y;
					 hits.push_back(pt0);
					 weights.push_back(s);
					hits_x[i] = pt0_x;
					hits_y[i] = pt0_y;
					myweights[i] = s;
					//cout << pt0_x << "+" << pt0_y << "+" << s << endl;
				}
			  else
				{
					hits_x[i] = -1;
					hits_y[i] = -1;
					myweights[i] = -1;
					//cout << "pass" << endl;
				}
		 }
}

 

 

跟源码进行比对,不难发现,主要改变的原因来自于mygetBlock函数不再是HOGCache的成员函数了,而是自己定义的普通函数,所以cache对象中的成员变量mygetBlock是没办法直接获得的,所以要通过传参的形式传入函数。这就是detect函数中有了很多malloc的原因。

 

这里注意几个地方:

(1).  const float* gradPtr = (const float*)(grad.data + grad.step*pt_y) + pt_x*2;
            const uchar* qanglePtr = qangle.data + qangle.step*pt_y + pt_x*2;

这里实际上返回的是一个通道指针,是第pt_y行第pt_x*2列的元素,若gradPtr[0]则为第一通道元素,[1]则为第二通道元素,因为grad和qangle均为两通道矩阵!

(2).这里有一个bug,至今没有想得非常清楚,因为malloc了往往是要free的,但是这里前面有提到过,使用了parallel_for_函数,利用了CPU的并行计算,就是同时又很多个detect在进行,当第一个detect完成后,若free了变量,那么其他detect将无法运行,这里将出现内存错误!如何解决这个问题,还有待研究!

2
3
分享到:
评论

相关推荐

    C2000系列DSP芯片串口读写方案与FlashPro2000编程器应用详解

    内容概要:本文详细介绍了基于TMS320F系列芯片的C2000串口读写方案及其编程器——FlashPro2000的功能特点和支持的接口模式。文中不仅涵盖了硬件连接的具体步骤,还提供了代码实例来展示Flash擦除操作,并对比了JTAG和SCI-BOOT两种模式的优缺点。此外,针对不同型号的C2000系列芯片,给出了详细的适配指导以及避免烧录过程中可能出现的问题的方法。 适合人群:从事DSP开发的技术人员,尤其是对TI公司C2000系列芯片有一定了解并希望深入了解其编程和烧录细节的人群。 使用场景及目标:适用于实验室环境下的程序调试阶段,以及生产线上的批量烧录任务。主要目的是帮助开发者选择合适的编程工具和技术手段,提高工作效率,减少因误操作导致设备损坏的风险。 其他说明:文中提供的代码片段和命令行指令可以直接用于实际项目中,同时附带了一些实用技巧,如防止芯片变砖的小贴士和自动化重试脚本,有助于解决常见的烧录难题。

    汉字字库存储芯片扩展实验通常是为了学习和理解如何在嵌入式系统或计算机硬件中增加或管理存储资源,特别是针对需要处理中文字符的应用 这类实验对于想要深入了解计算机体系结构、嵌入式开发以及汉字编码的学生和工

    汉字字库存储芯片扩展实验 # 汉字字库存储芯片扩展实验 ## 实验目的 1. 了解汉字字库的存储原理和结构 2. 掌握存储芯片扩展技术 3. 学习如何通过硬件扩展实现大容量汉字字库存储 ## 实验原理 ### 汉字字库存储基础 - 汉字通常采用点阵方式存储(如16×16、24×24、32×32点阵) - 每个汉字需要占用32字节(16×16)到128字节(32×32)不等的存储空间 - 国标GB2312-80包含6763个汉字,需要较大存储容量 ### 存储芯片扩展方法 1. **位扩展**:增加数据总线宽度 2. **字扩展**:增加存储单元数量 3. **混合扩展**:同时进行位扩展和字扩展 ## 实验设备 - 单片机开发板(如STC89C52) - 存储芯片(如27C256、29C040等) - 逻辑门电路芯片(如74HC138、74HC373等) - 示波器、万用表等测试设备 - 连接线若干 ## 实验步骤 ### 1. 单芯片汉字存储实验 1. 连接27C256 EPROM芯片到单片机系统 2. 将16×16点阵汉字字库写入芯片 3. 编写程序读取并显示汉字 ### 2. 存储芯片字扩展实验 1. 使用地址译码器(如74HC138)扩展多片27C256 2. 将完整GB2312字库分布到各芯片中 3. 编写程序实现跨芯片汉字读取 ### 3. 存储芯片位扩展实验 1. 连接两片27C256实现16位数据总线扩展 2. 优化字库存储结构,提高读取速度 3. 测试并比较扩展前后的性能差异 ## 实验代码示例(单片机部分) ```c #include <reg52.h> #include <intrins.h> // 定义存储芯片控制引脚 sbit CE = P2^7; // 片选 sbit OE = P2^6; // 输出使能 sbit

    测控装备干扰源快速侦测系统设计研究.pdf

    测控装备干扰源快速侦测系统设计研究.pdf

    嵌入式八股文面试题库资料知识宝典-【开发】嵌入式开源项目&库&资料.zip

    嵌入式八股文面试题库资料知识宝典-【开发】嵌入式开源项目&库&资料.zip

    嵌入式八股文面试题库资料知识宝典-百度2022年嵌入式面试题.zip

    嵌入式八股文面试题库资料知识宝典-百度2022年嵌入式面试题.zip

    少儿编程scratch项目源代码文件案例素材-空间站.zip

    少儿编程scratch项目源代码文件案例素材-空间站.zip

    基于关联规则的商业银行个性化产品推荐.pdf

    基于关联规则的商业银行个性化产品推荐.pdf

    嵌入式八股文面试题库资料知识宝典-Linux基础使用.zip

    嵌入式八股文面试题库资料知识宝典-Linux基础使用.zip

    MATLAB仿真轴棱锥生成贝塞尔高斯光束及环形光束光强图像分析

    内容概要:本文详细介绍了利用MATLAB进行轴棱锥生成贝塞尔高斯光束及环形光束光强图像的仿真研究。首先阐述了实验的背景与目标,强调了MATLAB在光学和计算科学领域的广泛应用。接着,具体描述了实验的方法与步骤,包括材料准备、仿真过程中的参数设定和光束生成代码编写。最后,对实验结果进行了深入分析,展示了贝塞尔高斯光束和环形光束的光强分布特点,验证了其光学性能的预期表现。文章还对未来的研究方向和技术改进提出了展望。 适合人群:从事光学、物理学及相关领域研究的专业人士,特别是对光束生成和光学性能分析感兴趣的科研工作者。 使用场景及目标:适用于需要进行光束生成和性能分析的实验室环境,旨在帮助研究人员更好地理解和优化光束特性和传播行为。 其他说明:本文不仅提供了详细的实验方法和步骤,还附有丰富的实验结果和数据分析,为后续研究提供了宝贵的参考资料。

    三电平NPC型APF模型预测控制中滞环控制模块的应用与开关频率优化研究

    内容概要:本文探讨了三电平NPC型有源电力滤波器(APF)的模型预测控制(MPC)中存在的开关频率过高问题及其解决方案。传统MPC方法会导致极高的开关频率,增加了系统的能耗和热量。通过引入滞环控制模块,可以在不大幅牺牲性能的情况下有效降低开关频率。具体来说,滞环控制通过在价值函数计算后增加一个判断条件,对状态切换进行惩罚,从而减少不必要的开关动作。实验结果显示,开关频率从4392Hz降至3242Hz,降幅达26.2%,虽然电流总谐波畸变率(THD)略有上升,但仍符合国家标准。此外,文中还提出了动态调整滞环宽度的方法,以进一步优化不同负载条件下的表现。 适合人群:从事电力电子、电力系统控制领域的研究人员和技术人员,特别是关注APF和MPC技术的人群。 使用场景及目标:适用于需要优化APF系统开关频率的研究和工程项目,旨在提高系统效率并降低成本。目标是在不影响系统性能的前提下,显著降低开关频率,减少能量损失和热管理难度。 其他说明:文章不仅提供了理论分析,还包括具体的实现代码片段,有助于读者理解和实践。同时,强调了在实际应用中需要注意的问题,如中点电位漂移等。

    计算流体力学中三维POD DMD程序的原网格处理方法及应用

    内容概要:本文介绍了三维POD DMD程序在处理原网格数据方面的独特优势和技术细节。首先阐述了该程序能读取结构化和非结构化网格数据及其拓扑关系,在生成模态数据过程中保持原始网格形态而不需要进行网格插值操作。接着展示了简化版本的Python代码片段,揭示了读取网格数据和生成模态数据的核心逻辑。最后提到提供的辅助学习资料如代码、视频教程、Word教程和实例数据,帮助用户深入理解并掌握该程序的应用。 适合人群:从事计算流体力学领域的研究人员和技术爱好者,尤其是那些希望提高数据处理效率的人群。 使用场景及目标:适用于需要处理复杂网格数据的研究项目,旨在简化数据处理流程,提升工作效率,同时保持数据的原始特性。 其他说明:文中不仅提供了理论性的讲解,还有具体的代码示例和丰富的学习资源,使读者可以边学边练,快速上手。

    融合双向路由注意力的多尺度X光违禁品检测.pdf

    融合双向路由注意力的多尺度X光违禁品检测.pdf

    嵌入式八股文面试题库资料知识宝典-Linux_Shell基础使用.zip

    嵌入式八股文面试题库资料知识宝典-Linux_Shell基础使用.zip

    嵌入式八股文面试题库资料知识宝典-联发科2021武汉嵌入式软件开发.zip

    嵌入式八股文面试题库资料知识宝典-联发科2021武汉嵌入式软件开发.zip

    基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf

    基于有限体积法Godunov格式的管道泄漏检测模型研究.pdf

    嵌入式八股文面试题库资料知识宝典-ARM常见面试题目.zip

    嵌入式八股文面试题库资料知识宝典-ARM常见面试题目.zip

    基于LWR问题的无证书全同态加密方案.pdf

    基于LWR问题的无证书全同态加密方案.pdf

    嵌入式八股文面试题库资料知识宝典-符坤面试经验.zip

    嵌入式八股文面试题库资料知识宝典-符坤面试经验.zip

    三电平逆变器带不平衡负载的DSC与双闭环PI控制策略仿真研究

    内容概要:本文详细探讨了三电平逆变器在带不平衡负载条件下的仿真研究。主要内容包括仿真环境的搭建、不同拓扑结构的选择(如T型、I型NPC和ANPC)、延时相消法(DSC)和双二阶广义积分器(DSOGI)的正负序分离控制策略、SVPWM或SPWM调制技术的应用、双闭环PI控制以及直流均压控制。文中通过具体的参数设置(交流电压220V,直流侧电压750V)进行了详细的仿真实验,并展示了各个控制策略的效果。最终,通过仿真实验验证了所提出方法的有效性,确保了交流侧三相电压波形的对称性和电流波形的自适应调节。 适合人群:从事电力电子、电机驱动、新能源发电等领域研究的技术人员和研究人员。 使用场景及目标:适用于需要理解和掌握三电平逆变器在复杂负载条件下控制策略的研究人员和技术人员。目标是提高对三电平逆变器及其控制策略的理解,优化实际应用中的性能。 其他说明:本文不仅提供了理论分析,还包含了具体的仿真步骤和代码实现,有助于读者更好地理解和应用相关技术。

    汽车工程中4WID-4WIS 14自由度整车动力学模型的Matlab/Simulink建模及应用

    内容概要:本文介绍了如何使用Matlab/Simulink软件构建一个14自由度的四轮驱动-四轮转向(4WID-4WIS)整车动力学模型。该模型涵盖了整车纵向、横向、横摆、车身俯仰、侧倾、垂向跳动及四轮旋转和垂向自由度等多个方面,旨在全面反映车辆在不同工况下的动态行为。文中详细描述了各子系统的建模方法,包括转向系统、整车系统、悬架系统、魔术轮胎pac2002、车轮系统和PI驾驶员模块。同时,提供了Simulink源码文件、建模说明文档及相关参考资料,便于用户理解和应用。 适用人群:主要面向汽车工程师、研究人员以及对汽车动力学和Simulink建模感兴趣的学习者。 使用场景及目标:①帮助用户深入了解车辆在各种工况下的动态行为;②为车辆控制策略的制定提供理论支持和技术手段;③作为学习和研究整车动力学建模的有效工具。 其他说明:该模型采用模块化建模方法,提高了模型的清晰度和可维护性,同时也提升了建模效率。

Global site tag (gtag.js) - Google Analytics