CoppeliaSim(Vrep)与VS使用多线程交互
Posted Norach
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CoppeliaSim(Vrep)与VS使用多线程交互相关的知识,希望对你有一定的参考价值。
CoppeliaSim(Vrep)与VS使用多线程交互
一. 前言
本文主要内容为在VS中以C++调用Windows提供的API,来实现Vrep与VS交互过程中的多线程效果。详细实现思路及步骤在第三部分中。
二.为什么想使用多线程
实际工程中往往都是多任务的,同时进行外设驱动,定位,PID控制器等,使用UCOS或者FreeRTOS的实时操作系统进行协调处理。而在学习Vrep这一仿真软件到目前为止,都是使用的线性结构程序代码,无法满足后续的实际需求。就开始学习有什么方法能够实现这一点。
三. 具体内容
1. 关于Vrep的thread scirpt
感觉使用Vrep的Lua语言脚本并不是特别方便,之前用过的也只是non-threaded。讲究父子结构树关系,包括设置优先级时也要注意这些限制。搜索了相关资料作些了解吧。对于Lua的“多线程”用协程来描述更妥些。
《vrep中thread scirpt以及simRemoteApi.start()的一点点微小的认识》
至于里面提及的API,官方文档API表单中都能查询到,只需要注意一些输入输出参数的信息并不是很详细全面。
2. 关于在VS中使用多线程
自C++11标准之后,已经提供了"thread.h"专门的线程文件,相关使用介绍,可以看下面两篇博客的介绍。
《C++ 多线程编程之在类中使用多线程(thread)的方法》
这边还有一个C++11标准之前,通过“process.h”,自写仿java的Thread类实现多线程的方法。
而本次使用的则是Windows系统提供的相关API。
《C++ 实现多线程编程(通过Windows提供的API)》
3. 具体步骤详解
3.1 搭建好Vrep三轮小车模型
这里具体步骤就不细说了,熟悉Vrep操作之后算是很简单的操作了。详细可以参考这一篇,我初学时看的《Vrep小车建模——前进和转向》。
稍有不同的就是添加了两侧驱动轮的转速,并通过框图表显示出来。如何添加可以参考同一作者的这一篇《Vrep小车建模——Lua内嵌脚本》。
3.2 VS上编写相应测试代码
#include<iostream>
#include<Windows.h>
using namespace std;
extern "C"
#include "extApi.h"
int clientID;
int leftvalue;
int rightvalue;
int countLeft = 0;
int countRight = 0;
simxInt LeftMotor;
simxInt RightMotor;
DWORD WINAPI myfun1(LPVOID lpparm);
DWORD WINAPI myfun2(LPVOID lpparm);
int main()
clientID = simxStart("127.0.0.1", 19997, true, true, 5000, 5);
if (clientID != -1)
cout << "Success!" << endl;
else
cerr << "error" << endl;
leftvalue = 3;
rightvalue= 3;
simxStartSimulation(clientID, simx_opmode_oneshot_wait);
simxGetObjectHandle(clientID, "LeftMotor", &LeftMotor, simx_opmode_blocking);
simxGetObjectHandle(clientID, "RightMotor", &RightMotor, simx_opmode_blocking);
HANDLE h1, h2;
h1 = CreateThread(NULL, 0, myfun1, NULL, 0, NULL);
cout << "线程1开始运行\\n" << endl;
h2 = CreateThread(NULL, 0, myfun2, NULL, 0, NULL);
cout << "线程2开始运行" << endl;
CloseHandle(h1);
CloseHandle(h2);
while (1)
if (getchar() == 'q')
simxStopSimulation(clientID, simx_opmode_oneshot);
simxFinish(clientID);
return 0;
else
Sleep(100);
DWORD WINAPI myfun1(LPVOID lpparm)
while (clientID != -1)
simxSetJointTargetVelocity(clientID, LeftMotor, leftvalue, simx_opmode_oneshot);
Sleep(10);
countLeft++;
if(countLeft == 300)
rightvalue = -rightvalue;
countLeft = 0;
return 0;
DWORD WINAPI myfun2(LPVOID lpparm)
while (clientID != -1)
simxSetJointTargetVelocity(clientID, RightMotor, rightvalue, simx_opmode_oneshot);
Sleep(10);
countRight++;
if (countRight == 300)
leftvalue = -leftvalue;
countRight = 0;
return 0;
3.3 运行测试效果
可以看到小车如同代码程序一样。
DWORD WINAPI myfun1(LPVOID lpparm)
while (clientID != -1)
simxSetJointTargetVelocity(clientID, LeftMotor, leftvalue, simx_opmode_oneshot);
Sleep(10);
countLeft++;
if(countLeft == 300)
rightvalue = -rightvalue;
countLeft = 0;
return 0;
每间隔3000ms,电机转速取反,这边为了测试,能否线程之间对同一数据修改,如同上面代码缩写,在控制左轮的线程中,给右轮转速取反。同样,在控制右轮的线程中,给左轮转速取反。
上面大图中的轮速数据表图不太清楚,下面给一个清晰的。
可以看到两条红线的变化,基本实现了3000ms同时换向一次。
四.总结
以下面的框架结构,即可实现多任务的效果。
...
int main()
...
HANDLE h1, h2;
h1 = CreateThread(NULL, 0, myfun1, NULL, 0, NULL);
...
CloseHandle(h1);
...
while (1)
return 0;
...
DWORD WINAPI myfun1(LPVOID lpparm)
while (1)
...
Sleep(10);
...
需要注意的就是目前的设立方法,并没有注重线程的同步和优先级的考虑。意味着,多线程的资源是随机分配的。若想在这两点上也加以限制,可以参考下面两篇博文:
以上是关于CoppeliaSim(Vrep)与VS使用多线程交互的主要内容,如果未能解决你的问题,请参考以下文章