无人机/无人车仿真软件学习与实践---CoppeliaSim教程2---无人机的仿真与外部控制

本文介绍了如何使用Python连接CoppeliaSim进行无人机的仿真和外部控制。首先,详细阐述了Python连接CoppeliaSim的步骤,接着展示了如何在仿真环境中加入无人机模型。然后,讲解了如何通过Python代码控制单台和多台无人机,以及如何通过多进程避免控制多台无人机时的卡顿问题。最后,提到了参考资料。
摘要由CSDN通过智能技术生成

在正式介绍怎么用CoppeliaSim进行无人机的仿真和外部控制之前,我们先看看Python连接CoppeliaSim需要作什么操作。

Python连接CoppeliaSim

CoppeliaSim在“C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\programming”文件夹下放置了一系列与其连接所需要的库。

针对python语言的连接库在“C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\programming\remoteApiBindings\python\python”和“C:\Program Files\CoppeliaRobotics\CoppeliaSimEdu\programming\remoteApiBindings\lib\lib\Windows\”路径下可以找到。

实现python与CoppeliaSim连接的具体操作如下:

  1. 从第一个文件夹中找到sim.py和simConst.py两个文件,从第二个文件夹中找到remoteApi.dll文件,然后复制到一个新的文件夹中。
  2. 在创建的文件夹中新建一个.py文件,写入如下内容:
import sim
sim.simxFinish(-1) # 断开一切可能的连接
clientID=sim.simxStart('127.0.0.1',19997,True,True,5000,5) # 连接到CoppeliaSim场景中
if clientID !=-1:
    print ('Connected to remote API server')
else:
    print ('Failed connecting to remote API server')
sim.simxGetPingTime(clientID) # 在断开之前连接确保之前的命令已经被执行完成
sim.simxFinish(clientID) # 断开与CoppeliaSim场景的连接
  1. 点击CoppeliaSim的运行按钮,进入仿真:
    请添加图片描述

  2. 运行第2步的文件,如无意外将输出“Connected to remote API server”。

无人机模型加入

完成python和CoppeliaSim的简单连接之后,可以往仿真器中加入无人机模型。(如果之前的仿真没关,记得把它关了)
在这里插入图片描述

在左边的模型中,选择“robots”→“mobile”可以看到里面有名为“Quadcoper.ttm”的无人机
在这里插入图片描述
在这里插入图片描述

选中该无人机并将其往右边拉,便成功添加了一台无人机到仿真平台中:
在这里插入图片描述

Python控制CoppeliaSim中的无人机

点开左边的Quadcoper无人机对象,可以看到其组成部分。其中,target是中央的那个小绿球,无人机会跟着该球移动,因此可以通过移动该球的位置来控制无人机的移动。代码如下:

import sim
import time

sim.simxFinish(-1) # 断开一切可能的连接
# 开启一个与服务器(V-REP)的一个通信线程。返回一个ClientID,这个ClientID后续的API基本都需要用到,可以理解为用这个ID来进行通信。
clientID=sim.simxStart('127.0.0.1',19997,True,True,5000,5) # 连接到CoppeliaSim场景中

if clientID !=-1:
    print ('Connected to remote API server')
    # 用名字来检索一个对象句柄。仿真环境里任何添加的object都会有一个自己的句柄(一个int,比如85,102),然后这个句柄跟object的名字对应,也就是我们有了名字就能对应到句柄。
    ret1, targetObj = sim.simxGetObjectHandle(clientID, './target', sim.simx_opmode_oneshot_wait)
    # 获取无人机对象信息
    ret2, arr = sim.simxGetObjectPosition(clientID, targetObj, -1, sim.simx_opmode_oneshot_wait)
    if ret2 == sim.simx_return_ok:
        print(targetObj)
    for i in range(20):
        arr[1]=arr[1]+0.1
        sim.simxSetObjectPosition(clientID, targetObj, -1, (arr[0], arr[1], arr[2]), sim.simx_opmode_oneshot_wait)
else:
    print ('Failed connecting to remote API server')

sim.simxGetPingTime(clientID) # 在断开之前连接确保之前的命令已经被执行完成
sim.simxFinish(clientID) # 断开与CoppeliaSim场景的连接

需要注意,CoppeliaSim V4.3.0版本在控制对像的时候需要加上’./‘如’./target’,这个与老版本有区别。本人之前看着老版本的教程一直控制不了无人机,差点直接放弃了CoppeliaSim 。。。

Python控制多台无人机

和上面的操作一样,往仿真器中拖入多台无人机如下:请添加图片描述

修改双击无人机的target对象,对其重命名:

PS:注意这里也可以不改,如果有多个对象时可以用target[x]这种格式进行索引,本人一开始不知道才写了后面那些。。。x的值和Quadcopter[x]中的x相对应。这里迷惑的地方在于点开Quadcopter[x]子项列表的时候里面的子项名称都是一样的,只有在运行仿真时才可以看到target[x]这种形式。—20220521补充。
在这里插入图片描述

然后修改无人机的对象描述代码(双击):
在这里插入图片描述

将里面的“targetObj=sim.getObject(‘./target’)”改为“targetObj=sim.getObject(‘./target1’)”或者自己命名的其他名称。

通过如下的命令就可以实现对无人机的分别控制了:

import sim
import time

sim.simxFinish(-1) # 断开一切可能的连接
# 开启一个与服务器(V-REP)的一个通信线程。返回一个ClientID,这个ClientID后续的API基本都需要用到,可以理解为用这个ID来进行通信。
clientID=sim.simxStart('127.0.0.1',19997,True,True,5000,5) # 连接到CoppeliaSim场景中

if clientID !=-1:
    print ('Connected to remote API server')
    # 用名字来检索一个对象句柄。仿真环境里任何添加的object都会有一个自己的句柄(一个int,比如85,102),然后这个句柄跟object的名字对应,也就是我们有了名字就能对应到句柄。
    _, targetObj1 = sim.simxGetObjectHandle(clientID, './target1', sim.simx_opmode_oneshot_wait)
    _, targetObj2 = sim.simxGetObjectHandle(clientID, './target2', sim.simx_opmode_oneshot_wait)
    # 获取无人机对象信息
    _, arr1 = sim.simxGetObjectPosition(clientID, targetObj1, -1, sim.simx_opmode_oneshot_wait)
    _, arr2 = sim.simxGetObjectPosition(clientID, targetObj2, -1, sim.simx_opmode_oneshot_wait)

    for i in range(20):
        arr1[1] = arr1[1] + 0.1
        arr2[1] = arr2[1] + 0.1
        sim.simxSetObjectPosition(clientID, targetObj1, -1, (arr1[0], arr1[1], arr1[2]), sim.simx_opmode_oneshot_wait)
        sim.simxSetObjectPosition(clientID, targetObj2, -1, (arr2[0], arr2[1], arr2[2]), sim.simx_opmode_oneshot_wait)
else:
    print ('Failed connecting to remote API server')

sim.simxGetPingTime(clientID) # 在断开之前连接确保之前的命令已经被执行完成
sim.simxFinish(clientID) # 断开与CoppeliaSim场景的连接

Python多进程控制多台无人机

在上面的操作中,如果控制的无人机数量很多,仿真的速度将变得非常卡,原因在于程序总是要等待执行完一台无人机的控制任务之后才继续执行另外一台。为了解决这个问题,可以使用Python的多进程接口对程序进行控制(这里不使用多线程是因为Python的多线程是伪多线程,实现上用的是一个CPU线程切片进行模拟的)。

首先,在模拟器的无人机target对象上右键,然后选择Add→Associated child script→Threaded→Lua
在这里插入图片描述

然后双击代码对象:
在这里插入图片描述

在sysCall_init()函数中添加如下代码:

repeat until (simRemoteApi.start(19901,1300,false,true)~=-1)
--注意19901为端口号,每一个对象都要设置不同的端口号,可以设置的端口号为19901~19999

随后,便可以通过如下的代码对无人机进行控制:

import sim
import multiprocessing

def worker_1(interval):
    client_id = sim.simxStart("127.0.0.1", 19900+interval, True, False, 10000, 5)
    while True:
        _, UAV = sim.simxGetObjectHandle(client_id,"./target" + str(interval), sim.simx_opmode_oneshot_wait)
        sim.simxSetObjectPosition(client_id, UAV, UAV,[-0.1,0.1,0.1], sim.simx_opmode_oneshot_wait)

if __name__ == '__main__':
    p1 = multiprocessing.Process(target = worker_1, args = (1,))
    p2 = multiprocessing.Process(target = worker_1, args = (2,))
    p3 = multiprocessing.Process(target = worker_1, args = (3,))
    p4 = multiprocessing.Process(target = worker_1, args = (4,))

    p1.start()
    p2.start()
    p3.start()
    p4.start()

    print("The number of CPU is:" + str(multiprocessing.cpu_count()))
    for p in multiprocessing.active_children():
        print("child   p.name:" + p.name + "\tp.id" + str(p.pid))

参考文章

https://blog.csdn.net/qq_37051669/article/details/115324851

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值