Webots建模指南2 – 机器人建模

3396
10
2020年5月18日 10时05分

嗨伙计们,月更侠罗伯特祥又来和大家见面了!今天我们来聊一聊Webots中关于机器人建模的那点事儿,相信有了前面的基础,今天的文章对你来说So easy!话不多说,我们来看看怎么玩儿吧~

1.四轮差速小车建模

环境建模我们就略过去了,直接上图:

 

1.环境建模

 

HingeJoint节点的使用:

首先添加一个Robot节点,在子节点children下新建一个Shape作为车身,重命名为car-body,然后在boundingObject下添加car-body节点作为碰撞边界。

车体有了,接下来我们就来添加它的旋转关节,这需要使用HingeJoint节点实现,先来看下它的建模结构:

2.HingeJoint建模结构

 

从上图中我们可以清楚的看到HingeJoint的子节点结构,其中HingeJointParameters用来设置关节的一些属性参数,device用来添加驱动电机、关节角度传感器以及刹车,endPoint用来对关节进行形状建模以及下一个串联关节的建模。

具体细节就不展示了,我们直接来看第一个轮子的建模效果(调整完的效果):

 

3.车轮建模

 

 

关节调试:

为了方便建模,我们直接调好这个轮子的参数,然后直接使用Ctrl+C大法。把车体调整成方便调试的姿态(下图为调整完的效果):

 

4.查看旋转轴

 

小提示:轮子的操作是以Robot坐标系来操作的,点击Robot节点可以看到坐标系朝向。

写一个简单的控制器程序,来测试一下车轮转向:

 

5.调车轮方向

 

哎哎哎?这是什么情况?轮子咋还绕车体了,这也不是我要的结果啊!!!

 

表情包-黑人疑问

 

别着急,jointParameters下的anchor看到没,它就是用来设置旋转中心的,通过它可以设置一个与父节点同向的坐标系定义。通常情况,我们将它的值和endPoint下的translation设置成相同即可。

 

6.调车轮方向1

 

嗯这次确实不饶车体旋转了,可是这个旋转轴是不是有点问题啊~

jointParameters下的axis看到没,直接盘它!再来看看效果:

 

7.调车轮方向2

 

这次倒是正常了,就是旋转方向不太对啊~那咱就来给他换个方向,axis直接添个负号就完事儿了。

 

8.调车轮方向3

 

然后就是一段复制粘贴,完成了四个轮子的建模。这里要注意啦,别忘了修改旋转中心anchor和电机传感器的name啊,不然要出问题的~

 

摩擦力设置:

给它个速度,让它没事儿走两步:

 

9.直线测试

 

嗯不错不错,能走了,可是怎么又出问题了,给它差速的时候为啥旋转不了啊!

 

四轮差速嘛,摩擦力很关键的。来来来,我们继续盘它!WorldInfo下面有个contactProperties节点,给它添加一个ContactProperties子节点,在这个子节点下面,我们把库伦摩擦coulombFriction改为0.5,再来测试一下,是不是发现问题解决了~

 

10.摩擦力修改

 

继续画蛇添足

给它添个摄像头,再添个机械臂~

 

11.摄像头12.机械臂节点

 

为了方便大家复现建模过程,下面直接给出建模过程中的参数设置:

Robot位置

0,0.2,0

Car-body尺寸

0.6,0.2,0.35

endJoint中车轮尺寸

半径0.1,宽0.05

endJoint中车轮姿态

1,0,0,1.5707

车轮wheel1位置和旋转中心anchor

0.2,-0.1,-0.205

车轮wheel2位置和旋转中心anchor

0.2,-0.1,0.205

车轮wheel3位置和旋转中心anchor

-0.2,-0.1,0.205

车轮wheel4位置和旋转中心anchor

-0.2,-0.1,-0.205

Kinect位置姿态

位置:0.2,0.1,0    姿态:0,1,0,-1.5707

IprHd6m90位置姿态

位置:-0.1,0.1,0    姿态:0,1,0,0

 


嗯,有nei味儿了,来看下整体效果:

 

13.整体建模

 

注意,我们车轮的建模顺序是从左前轮开始,顺时针进行的,如下图所示:

 

14.车轮序号

 

2. 运动学建模

假设S为轴距,L为轮距,r为车轮半径,左前轮为1号轮,右前轮为2号轮,左后轮为3号轮,右后轮为4号轮,参数如下:

S = 0.4m

L = 0.41m

R = 0.1m

根据叠加原理,将小车运动分解为绕小车中心的转动和运动方向的平动。同一侧轮子转速相同,假设左侧为v1,右侧为v2,于是可以得到:

① 直线运动速度为  v=(v1+v2)/2

② 旋转速度为  w=(v1-v2)sin(alpha/2)

 

15.运动分析

 

最终得到四轮小车运动学模型如下:

运动学公式

3. 控制器

控制器中,我们实现键盘控制小车的运动,并且获取RGB图像和深度图像。

懒的封装类了,话不多说,简单粗暴点儿直接上代码!

"""my_first_controller controller."""
# -*- coding: UTF-8 -*-
# author:罗伯特祥
# Created on:2020-05-13

from controller import Robot,Keyboard

def main():
    # 实例化机器人
    robot = Robot()
    
    # 获取当前世界的基本时间步长
    timestep = int(robot.getBasicTimeStep())
    
    # 实例化keyboard类
    keyboard = Keyboard()
    keyboard.enable(10*timestep )
    
    # 关联电机设备
    wheel1 = robot.getMotor('wheel1')
    wheel2 = robot.getMotor('wheel2')
    wheel3 = robot.getMotor('wheel3')
    wheel4 = robot.getMotor('wheel4')
    
    # 关联并使能传感器设备
    camera = robot.getCamera('kinect color')
    cameraRange = robot.getRangeFinder('kinect range')
    camera.enable(4*timestep)
    cameraRange.enable(4*timestep)
    
    # 设置电机运行模式
    wheel1.setPosition(float('inf'))
    wheel2.setPosition(float('inf'))
    wheel3.setPosition(float('inf'))
    wheel4.setPosition(float('inf'))
    
    # 设置初始速度
    wheel1.setVelocity(0)
    wheel2.setVelocity(0)
    wheel3.setVelocity(0)
    wheel4.setVelocity(0)
    
    R_ = 0.1  # 车轮半径
    S_ = 0.4  # 轴距
    L_ = 0.41 # 轮距
    # Main loop:
    while robot.step(timestep) != -1:
        # 运动学模型
        v1 = wheel1.getVelocity() * R_
        v2 = wheel2.getVelocity() * R_
        vel = (v1+v2)/2
        
        # 逆时针为正
        temp_ = L_ * L_ + S_ * S_
        omega = (v2 - v1) * L_ / temp_
        print("小车速度:v = " + str(vel) + ", omega = " + str(omega))
    
        # 获取键盘操作
        key = keyboard.getKey()
        if key == ord('Q'):
            wheel1.setVelocity(1)
            wheel2.setVelocity(3)
            wheel3.setVelocity(3)
            wheel4.setVelocity(1)
        elif key == ord('E'):
            wheel1.setVelocity(3)
            wheel2.setVelocity(1)
            wheel3.setVelocity(1)
            wheel4.setVelocity(3)
        elif key == Keyboard.UP:
            wheel1.setVelocity(2)
            wheel2.setVelocity(2)
            wheel3.setVelocity(2)
            wheel4.setVelocity(2)
        elif key == Keyboard.DOWN:
            wheel1.setVelocity(-2)
            wheel2.setVelocity(-2)
            wheel3.setVelocity(-2)
            wheel4.setVelocity(-2)
        elif key == Keyboard.LEFT:
            wheel1.setVelocity(-2)
            wheel2.setVelocity(2)
            wheel3.setVelocity(2)
            wheel4.setVelocity(-2)
        elif key == Keyboard.RIGHT:
            wheel1.setVelocity(2)
            wheel2.setVelocity(-2)
            wheel3.setVelocity(-2)
            wheel4.setVelocity(2)
        else:
            wheel1.setVelocity(0)
            wheel2.setVelocity(0)
            wheel3.setVelocity(0)
            wheel4.setVelocity(0)
        
main()

 

操作如下:

Q:左转弯

E:右转弯

↑:前进

↓:后退

←:左旋转

→:右旋转

这操作,我竟然有种当年玩QQ飞车的感觉~

来看看最终效果:

 

16.整体效果

 

 

妥妥的一个youBot,具体怎么玩儿,剩下的就交给屏幕前的你了!下次我们来讲讲Webots在ROS中是怎么玩儿的~

表情包-完美

 

 

总结

① 旋转关节HingeJoint中,HingeJointParameters用来设置关节的一些属性参数,device用来添加驱动电机、关节角度传感器以及刹车,endPoint用来对关节进行形状建模以及下一个串联关节的建模;

② 旋转关节的旋转是参考其父节点Robot坐标系的;

WorldInfo下的contactProperties节点可以设置摩擦力;

④ 复制粘贴实现的建模,最后不要忘记修改旋转中心anchor和电机传感器的name

Robot节点是可以包含Robot节点的,这有利于复合机器人建模,提高机器人的复用率;

KeyBoard、相机、深度图像等节点的使用,其中Kinect是RGB相机和深度相机的一个集合,RGB相机设备namekinect color,深度设备namekinect range,云台电机nametilt motor,具体操作见控制器代码;

 

本文设计的项目文件:https://share.weiyun.com/xkLYeC2S

 

读万卷书也要行万里路,我是罗伯特祥,下次见!

 


 

最后附上几张机器人建模的思维导图,想要高清图?古月居公众号回复“建模仿真518”获取吧!

 

17.小车建模脑图

18.机械臂建模脑图

19.并联机器人建模脑图

20.无人机建模脑图

发表评论

后才能评论

评论列表(10条)

  • h5sl2_7950 2020年9月16日 上午11:52

    请问你有没有尝试过自己导入机器人模型?我自己导入的机器人模型后,那个boundingobject也设置了,可是还是出现了运行仿真后,一直在地面浮沉。请问我该怎么简化我的模型呢?我看官方模型都比我的复杂啊

    • 罗伯特祥 回复 h5sl2_7950 2020年9月17日 下午8:24

      没有遇到过你说的问题,还得根据你的实际情况来看看

  • u3oey_0531 2020年7月23日 上午11:01

    请问能不能将SolidWorks等三位软件上画的机械臂等导入到webots中能?并且怎嘛用C++、python等进行控制呢?

    • 罗伯特祥 回复 u3oey_0531 2020年9月17日 下午8:10

      嗨老铁,R2020b以后的版本可以直接导入stl等格式的模型

  • 北京网友 2020年5月22日 下午2:35

    快点出机械臂的教学吧,等不及了!

  • じ習慣有你 2020年5月22日 上午1:09

    作者您好,请问机械臂要怎么使用呢?
    base = robot.getMotor(‘base’)
    base.setPosition(float(‘inf’))
    以上代码出现以下错误:
    Warning: “base” device not found.
    AttributeError: ‘NoneType’ object has no attribute ‘setPosition’

    • 罗伯特祥 回复 じ習慣有你 2020年5月22日 下午7:48

      需要根据具体的项目来看,getMotor对应的参数应该是base中device的name,错误提示说没找到这个节点,所以你应该检查’base’是否为base中的电机name

    • 翡冷翠 回复 罗伯特祥 2020年6月23日 上午10:37

      你好,我也遇到了相同的问题,就拿您这个项目来说,是4轮小车作为夫节点,机械臂作为他的子节点,如果我想使机械臂中的电机(电机名为base)运动我该如何写代码呢。如果像上面的同学写的那样,我也是报错的,好像这样写只能查询到父节点的设备,如何能查询到其子节点的设备呢?困扰许久,求解答

    • 罗伯特祥 回复 翡冷翠 2020年6月26日 下午4:55

      方便发送你的项目吗,可以发送到robert.h.x.s@foxmail.com,我需要根据实际情况来看,getMotor会直接搜索对应的节点名称