精华内容
下载资源
问答
  • 【前言】本篇还没有完,还剩摆放小物件啥的,那都是次要的事情,都是体力活,随后再添加,诸君且先看吧。个人觉得UE4世界大纲的选择隐藏模式可以向Blender好好学学,参见本文第节和第十节,这样直接在UE4中建模...

    198a782530cd26c243572a988ae46696.png

    【前言】

    本篇还没有做完,还剩摆放小物件啥的,那都是次要的事情,都是体力活,随后再添加,诸君且先看吧。

    个人觉得UE4世界大纲的选择隐藏模式可以向Blender好好学学,参见本文第五节和第十节,这样直接在UE4中建模也不是没有可能。

    【导图】

    0e404e2ba368274635a1ce5b7026e14c.png

    87f34981c048e685f4e01d97786d0d2c.png

    一、导出DXF格式图纸

    • 从Revit中直接导出DXF格式的图纸
    • CAD的话,直接W write block写块导出DXF

    64276c1337d7befd7be7f6df08676753.png

    如下,这是要导出的图纸

    bf3c83d1d33ce4d877aec6ac6db6583a.png

    7cb95c1ee64884ec4b82f7c2d8b75d94.png

    二、Blender中勾选自带DXF插件

    Ctrl+N新建项目,General。

    这里也是直接可以访问到偏好设置的,不至于每次老到Edit中去找。

    2cc7abbef8008bf450ce1e082a2dbe24.png

    勾选导入导出DXF格式插件

    096515ca139f6317bcebf35d92ad0839.png

    可以看到支持导入啦

    1870827dd9e8d1c8855b173f09f0ea36.png

    我们还可以直接在其上右键自定义导入DXF图纸快捷键,不至于每回都得跑到偏好设置中去改,很方便哒~

    0877615682b0734866e80e360a1f92e3.png

    a5c5dc8d5a8e9c4ea8e7990730a1288f.png

    三、导入图纸

    1. 先A X 删除默认Cube和Camera
    2. 然后Ctrl+E 导入

    3.可以复制文件夹路径后,添加路径到喜爱中,就跟Windows的Quick Access一样,可以实现快速访问啦~

    ce1dfac5d1a737a8b04d3a47049176db.png

    4.导入,默认选项,灯光文字啥的,全部默认。

    ef5541ad26cc25310e911e4cf044c0e4.png

    5.可以看到,导入进来就只有两种类型,文字和Curve,正好。

    cdcdce9a4f54a0c5a2e3a120e7ab3aa6.png
    12

    6.导入进来后,我们可能看不见图纸,那是因为Curve/Text的距离太远了,我们可以改动Clip Start /End调节视野范围 或者是更改项目单位

    7d3174cd014185d081c7fff2767a5c68.png

    7d0541856eaea11c75b1f8f95fc7ee52.png

    ~ 切换到顶视图,更多Blender快捷键可以看这篇文章。

    X Tesla:【Blender】快捷键大全(超级详细,应有尽有,不断更新)zhuanlan.zhihu.com
    1d4f9a16366fd8ff89f64b0162d6122a.png

    或者是直接改项目单位,公制,缩放0.1倍,这样clip 就不需要改动了。

    b8a803fe25da393a44103ca37d93319a.png

    d14dad52f37e8e7f1499a2fc7ca97436.png

    四、文字/Curve调试

    由于Blender本身不支持中文字体,当然可以从外面复制粘贴进去,所以只会有英文字体显示

    75c7ca121ce592751752422877785c25.png

    复制粘贴的话,别忘了是要Tab进Edit Mode 从Edit这里点击粘贴,或Ctrl+V粘贴。

    260dfb74b3f7ec89e77ffae8ed8a16bf.png

    而且还要更改字体,如微软雅黑,否则字体显示不出来。

    d6d0a4d2ef15952f504431bf2cfbd3de.png

    其实说白了,文字和Curve都是一种曲线,我们都可以对图纸中的文字或Curve进行挤出或Bevel操作。

    3db0c85f0711fcddeade774041a9a2b2.png

    我们甚至可以直接选中外墙体曲线,通过挤出和倒角的协同配合,来制造墙体(厚度图纸已经画好了,所以不用管),之后Curve To Mesh转化为三维模型即可

    cb44b187a13860ca5369e3019cbbf5f2.png

    6670558192c618c2480f05d05910a56a.png

    五、显示选择相关

    Z切换渲染模式,固态、渲染、材质、网格。固态可选法线Shading,这样在旋转相机视角的时候,可以很清楚地看到哪些面是垂直、倾斜的。

    a4bcabb2481479b3a7c8a9e10eee8faf.png

    世界大纲中默认的只有小眼睛来控制Visibility的。

    0e4885d740c74eaed4109c5074a59b92.png

    我们还可以选其他的,如选择、显示、渲染等

    79f11b0c98dd7f717fbdc9587daec01d.png

    这样在顶视图中的话,可以只框选我们想要的模型,其他设置为不能被选择。

    18841c1e3618713b4faaa221bf0d3046.png
    • H 隐藏
    • Alt+H 取消全部隐藏(后面的那个小电脑如果是灰显的话,就一直是隐藏状态,Alt+H针对小眼睛的)
    • Shift+H 隐藏没有选中的
    • / 分隔单个物体
    • . 是聚焦,周围物体都还存在,分隔是周围物体都暂时消失

    e88f9eef11a2fb14696e6ba3c479723c.png

    六、整理分类模型

    我们可以先A选中全部模型,Set Origin To Geometry,设置枢轴点到模型处,要不然枢轴点非常乱。

    80466c8f596e8584d95dbf8edc59cbe6.png
    • M新建文件夹分类,Shift加选模型
    • 可Alt+H 显示所有模型后,用数字 1 2 3 来切换不同的Collection

    分类好之后,剩下的就只有外边缘了,我们需要对顶点进行一些操作:

    • Tab 进入Edit Mode中,选中曲线后,P Seperate 可将当前曲线分离为一个单个的曲线
    • Tab 在Object Mode中,选中两曲线后,Ctrl+J 可将两曲线合并到一个曲线中
    • X 删除曲线点
    • F连接两曲线点

    5bdbfdfcd9c4aaf510fefbc0120f03a1.png

    2e26c029b1b87bccc834703843235094.png

    差不多之后我们Shift+D备份一份外墙曲线,然后将曲线转换为Mesh,可以进行点线面的操作。

    076c7254931722fd19bbd1d2ebbe848a.png

    8266e1f74603ad45280fb8e55b723da2.png

    七、制作外墙体(Snapping+Solidify)

    制作外墙体总共有多种方式:

    【1.】可以将曲线分割开,然后用一个小长方体+Array Modifier+Curve Modifier

    参见:

    X Tesla:【Blender】如何用 8 种 Modifier 快速制作各种摩天大楼(建模提升工作效率必看!)zhuanlan.zhihu.com
    2090e231b2609302166479e1dd1395ef.png

    【2.】也可以删减曲线点,转化为Mesh后两点成线,四点成面,然后挤出面即可。

    Alt+M Merge By Distances 删除多余挤出来的点

    【3.】还可以通过Snapping工具来挤出平面+Solidify加厚Modifier生成墙体

    这个其实就类似上面第四节中讲到过的调节Curve曲线的Extrude值,只不过有些DXF图纸比较复杂,我们可能需要重新手动添加。

    我们这里着重讲解第三种。

    • Shift+Tab 开启Snapping 对齐工具
    • Ctrl+Tab 是切换Mode(Object、Vertex这些)
    • Ctrl+Shift+Tab是切换Snap的对象,比如捕捉到点、线、面等(可以Shift加选)

    2ccd331490673707cc4c6d792114ada8.png

    【7.1】Shift+A 添加Plane(Size =30m,即高度为3m,乘10是因为我们的场景单位Unit Scale=0.1)

    fb5aa42c0502d5cbd13cdf2d228bc7c6.png

    【7.2】开启面朝向(Face Orientation)

    开启这个面 就是只有红绿蓝三种颜色。如果用的是Solid Normal Shading的话,那么会被红绿蓝三色覆盖掉。

    a535090ee558373dd89bb551b01200b9.png

    【7.3】把Plane Snap 到图纸上

    Ctrl+Shift+Tab选择Vertex 捕捉。

    5792030e4da434880d5e215c8cc43259.png

    【7.4】Tab Edit Mode 选中两点G挪动(挪动的顶点就是左边那两个)/E挤出(挤出就直接成面了)

    外墙体挤出完毕:

    c5839c38363c65b398a7b4847fc6a17c.png
    1. 内墙体需要先随便选两个垂直地面的顶点,Shift+D复制到里面。
    2. 然后P 分离成单个的模型

    忘了也没关系,Blender的选择功能也非常强大,循环边、指定面、相同长度的面、相同材质的面等等。

    1. 选中外围墙的单根边
    2. Select 内部边
    3. Ctrl+I反选
    4. P Seperate By selection(Loose Part是分离成好多个碎块模型)

    18a56e6fe755899042bb7a8120854444.png

    内墙体挤出完毕:

    32a706ceedee9d54bf59358e52d1af42.png

    【7.5】使用Solidify Modifier 加粗墙体

    • 外围 3(30cm)
    • 内侧 1(10cm)

    调整Offset可以偏移墙体位置,如果缝隙过大的话。

    fd46bc6607b4efcc9c8c541075ff913a.png

    bdaa71b106df1caf295e3323045aab85.png

    可以关掉Face Orientation,这下墙体是处理好了

    6ba5b6628bb8d16f6b1da0fa9feb1efa.png

    b469e86c7caf25d1d4f2ca6a83c866a3.png

    八、制作地板

    1. 选中外墙体
    2. ~ 切换到左视图
    3. Shift+Z X-Ray(可以选中后面看不见的顶点)
    4. 框选下方顶点
    5. F 成面

    5c5e1aa94f70a166ade85e357fb4b5b3.png

    910d2b16896b7424673bf1b44c047bf0.png

    九、启用自带Archimesh和Archipack插件(做建筑小物件非常方便)

    6a613975612feebd06a35e8086b82fc1.png

    39138fdc6e4c5f589bdda146122b5190.png

    十、添加各式各样的门

    • 门宽
    • 门高
    • 门厚
    • 门Inset
    • 门旋转角度
    • 开门方向(右开门、双开门、左开门)
    • 门的类型(普通、玻璃等等)
    • 扶手的类型(圆的、把儿的、推的)

    fb598ad20b1abbab27f274a244877cae.png

    三开门:

    111e26adb65a34322fe2c34fae9b39c5.png

    门的种类:

    13b797b07085e375e175ad19c68aaa40.png

    门把手:

    3e1561f0d2841b17a74ba3c9b1120819.png

    Shift加选设置可见、但是不能被选中,这样A全选就选中门的全部组件了,G好移动。

    3ac8bdb16153a83341ed0cd3010a733b.png

    然后添加完一个门就在世界大纲中Shift加选 设置这个门的所有组件不能被选中,之后再添加下一个门的时候,A全选就是这个新门了。

    或者是在世界大纲中选中父层,然后Shift G Select Group Chirdren即可。

    好了,门体添加完毕

    cc1e927867d1aa4dc87e961575f99c87.png

    df7f080d7ceb1b264ec628f094703f3b.png

    十一、添加窗户

    Rail Window小窗户

    827517d5cb75eb6b11a6e5f33c0f8414.png

    Panel Window落地窗

    ac2bd07c9cf6a0940975d4bfef0decff.png

    在移动位置的时候,可以打勾Align Rotaion to Target,这样物体就会自动地根据点线面位置进行旋转啦。(如果垂直于表面,可以把Rotate也打上勾,然后R X/Y/Z就可以自动转向了)

    55d5f356047cf671cd0e001cee3b951b.png

    落地窗可以Snap To Edge Center。

    • < 可切换 Transform Orientation
    • > 可切换Transform Pivot Point

    0b6a902fde4d81af178a79cf63e07c76.png

    55e534543415c6a6f6ba7ab93e4c78a4.png

    十二、添加小物件

    我们先把它这里能添加的先添加上,其他的我们就不添加了,时间有限。

    8f96817b1035509f4dacabe00039b997.png
    • 楼梯和屋顶
    • 窗帘
    • 书架和书
    • 灯泡
    • 小柜子(cabinets)

    【书架和书:】

    91cdbfd91bd1b84558fb1281809e79cb.png

    bb44a743386ff7b03bc91da1865d7dfa.png

    小物件就不再放了,大概就是这样子。

    其他随后再进行深化添加,可能还有很多的问题。

    要睡觉了。。。。

    展开全文
  • Python-字符版gif

    2019-07-12 07:37:41
    上一篇文章我们讲了怎么做自己的炫酷二维码,需要的移驾Python-炫酷二,本片文章我们讲述下怎么把一张图片处理成字符版图片,就是说使用字符替代每个像素的颜色,形成一个由字符组成的图片,并且字符的颜色是由...


    原文链接:Python-字符版gif图

    一、背景

    上一篇文章我们讲了怎么做自己的炫酷二维码,需要的移驾Python-炫酷二维,本片文章我们讲述下怎么把一张图片处理成字符版图片,就是说使用字符替代每个像素的颜色,形成一个由字符组成的图片,并且字符的颜色是由原始的图片像素决定

    二、准备环境

    对图片的操作我们可以使用PIL、imageio和image2gif库,处理像素我们选择使用opencv-python这个库。NumPy是Python语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。

    因此我们需要安装以下几个包:PIL、imageio、numpy、cv2、images2gif

    • pip install pillow
    • pip install imageio
    • pip install numpy
    • pip install opencv-python
    • pip install images2gif

    以上扩展包安装时应该都可以顺利安装,但使用的时候有几个坑

    1、导入cv2时,如果发生找不到dll的情况,大多数的原因都是当前的python版本和opencv版本不匹配,pip安装时默认选择了最新的版本,因此我们安装时需要制定安装的版本pip install opencv-python==3.4.1.15

    2、使用images2gif这个库时,可能会出现无法导入writeGif接口的情况这个时候需要改下源码,把images2gif.py文件中的两个from 后边加上英文点号,修改如下

    from .images2gif import readGif as readGif
    from .images2gif import writeGif as writeGif
    

    三、字符版动态图

    首先我们需要搞清楚gif是个什么玩意儿,其实gif是将多幅图像保存为一个图像文件,从而形成动画,最常见的就是通过一帧帧的动画串联起来的搞笑gif图,所以归根到底gif仍然是图片文件格式。

    什么?原来gif就是一帧一帧的图片,那么字符版动态图其实也就是字符版图片的连续播放,思考到这儿,我们有了如下思路:

    1、拿到一张gif图

    2、把fig图拆分成多张png图片,或者其他格式的图片

    3、循环遍历拆分后的图片,并处理成字符版图片

    4、把处理后的字符版图片在连接成一个guf文件

    5、保存gif文件

    通过以上5个步骤,我们即可实现我们的需求,是不是很简单,下边我们分布来讲解实现过程

    四、gif和png转换

    1、要想获得静态图片,我们需要有一个gif图,然后把gif图拆分成多张png图片,以下是3中处理gif图片的方式

    方式1

    def Gif2Png():
        gif = Image.open(gifpath)
        try:
            while True:
                current = gif.tell()
                gif.save(saveFloder + "/%d.png" % current)
                gif.seek(current + 1)
        except:
            pass
    

    方式2

    def Gif2Png_2():
        try:
            im = Image.open(gifpath)
        except IOError:
            print ("Cant load", gifpath)
            sys.exit(1)
        i = 0
        mypalette = im.getpalette()
    
        try:
            while 1:
                im.putpalette(mypalette)
                frame = im.convert('RGBA')
                new_im = Image.new("RGBA", im.size)
                #new_im.paste(im)
                new_im.paste(frame)
                new_im.save(saveFloder + "\\%d.png" % i)
    
                i += 1
                im.seek(im.tell() + 1)
    
        except EOFError:
            pass # end of sequence
    

    方式3

    #使用imageio处理gif图
    def Gif2Png_3():
        images = imageio.mimread(gifpath)
        #把上面的每帧图片进行保存
        for i, img in enumerate(images):
            img = np.asarray(img)
            imageio.imwrite(saveFloder + "\\%d.png" % i, img)
    

    2、把图片处理成gif图,以下是处理的两种方式

    方式1

    def Png2Gif():
        fileOrder = sorted([int(os.path.splitext(x)[0]) for x in os.listdir(savePath)])
        frames = []
        for order in fileOrder:
            filename = str(order)+ '.png'
            filePath = savePath + "/" + filename
            frames.append(imageio.imread(filePath))
        
        imageio.mimsave(newFilePath, frames, 'GIF', duration = 0.1)
    

    **方式2 **

    def Png2Gif_2():
        fileOrder = sorted([int(os.path.splitext(x)[0]) for x in os.listdir(savePath)])
        filenames = []         # 存储所需要读取的图片名称
        for order in fileOrder:
            filename = str(order)+ '.png'
            filePath = savePath + "/" + filename
            filenames.append(filePath)              # 将使用的读取图片汇总
            
        frames = []
        for image_name in filenames:                # 索引各自目录
            im = Image.open(image_name)             # 将图片打开,本文图片读取的结果是RGBA格式,如果直接读取的RGB则不需要下面那一步
            im = im.convert("RGB")                  # 通过convert将RGBA格式转化为RGB格式,以便后续处理 
            im = np.array(im)                       # im还不是数组格式,通过此方法将im转化为数组
            frames.append(im)                       # 批量化
        writeGif(newFilePath, frames, duration=0.1, subRectangles=False) # 生成GIF,其中durantion是延迟,这里是1ms
        
    

    测试生成效果如下图所示

    五、处理动态图片

    生成字符版gif图时,如果把拆分开来的图片先进行保存硬盘,然后在进行图片处理在合成最终gif效率会比较慢,因此我们把整个过程都放在内容中处理,即拆分开来的png图片不进行存盘,而是直接处理,然后在合成gif图

    def Gif2Gif(gifpath):
        A = []
        images = imageio.mimread(gifpath)
        #把上面的每帧图片进行保存
        for img in images:
            u, v, channels = img.shape
            c = img * 0 + 255
            gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
            for i in range(0, u, 6):
                for j in range(0, v, 6):
                    pix = gray[i, j]
                    b, g, r, a = img[i, j]
                    zifu = string[int(((len(string) - 1) * pix) / 256)]
                    if a != 0:
                        cv2.putText(c, zifu, (j, i), cv2.FONT_HERSHEY_COMPLEX, 0.3, (int(b), int(g), int(r), int(a)))
                    
            A.append(c)
    
        oldFileName = os.path.splitext(os.path.basename(gifpath))[0]
        newFilePath = os.getcwd() + '/{}/'.format(saveFloder) + oldFileName +"_new.gif"
        imageio.mimsave(newFilePath, A, 'GIF', duration=0.1) 
    

    测试生成效果如下图所示

    六、字符版动态二维码

    有了普通的gif图生成动态二维码的方式,字符版gif图也就顺理成章的可以。
    测试生成效果如下图所示

    七、源码下载

    需要全部代码的到csdn直接下载:Python-字符版gif图


    如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!!




    很重要–转载声明

    1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords

    2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。


    展开全文
  • 在webots中,怎样建立一个铰链呢,我了一个简单的例子,小区门口的那种可以控制的栏杆,效果如下。  那每一个杆件,它们的关系在怎么定义呢?其实关系是在ODE中定义的,我们只需要建立一些没有约束关系的...

          在一些三维制图软件或仿真软件里,都有运动副的概念,webots的节点里好像没有,不要担心,在物理插件里可以做到,不过要学习有关于ODE(开源动力学引擎的)一些内容。在webots中,怎样建立一个铰链呢,我做了一个简单的例子,小区门口的那种可以控制的栏杆,效果图如下。

          那每一个杆件,它们的关系在怎么定义呢?其实关系是在ODE中定义的,我们只需要建立一些没有约束关系的杆件就行。场景树贴出在下面,虽然这些节点是以servo定义的,但是在不需要约束关系的杆件,例如连杆3,将type改成none,那么,杆件3与gan Robot的关系就不是servo关系了,在仿真中可以看成两个零件。模型就不介绍怎么建立了,后面会给出整个仿真的文件。

             

     

         建立完模型之后,点击菜单栏的  向导 —>新物理插件,代码如下:

      1 //来自“博客园,_阿龙clliu” http://www.cnblogs.com/clliu/
      2 #include <ode/ode.h>
      3 #include <plugins/physics.h>
      4 
      5 
      6 
      7 dBodyID getBody(const char *def) {
      8   dBodyID body = dWebotsGetBodyFromDEF(def);
      9   if (! body) dWebotsConsolePrintf("Warning: did not find body with DEF name: %s", def);
     10   return body;
     11 }
     12 
     13 
     14 void webots_physics_init(dWorldID world, dSpaceID space, dJointGroupID contactJointGroup) {
     15 
     16    //得到杆件的ID
     17    dBodyID link1 = getBody("link1");
     18    dBodyID link2 = getBody("link2");
     19    dBodyID link3 = getBody("link3");
     20    dBodyID link4 = getBody("link4");
     21    dBodyID link5 = getBody("link5");
     22    dBodyID link6 = getBody("link6");
     23    
     24    //创建一个铰链副
     25    dJointID hingeJoint = dJointCreateHinge(world, 0);
     26    //定义铰链副约束的两个零件,link1和link3
     27    dJointAttach(hingeJoint, link1, link3);
     28    
     29    //定义铰链的作用点
     30    dVector3 hinge_interface;
     31    //将link1零件自身坐标系的(0,0,0)点转为全局坐标系坐标,赋给hinge_interface
     32    dBodyGetRelPointPos(link1, 0, 0, 0, hinge_interface);
     33    
     34    //设置铰链作用点
     35    dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]);
     36    //设置铰链作用轴(作用方向)
     37    dJointSetHingeAxis(hingeJoint, 0, 0, 1);
     38    
     39    //link4?link3??
     40    hingeJoint = dJointCreateHinge(world, 0);
     41    dJointAttach(hingeJoint, link4, link3);
     42    
     43    dBodyGetRelPointPos(link4, 0, -0.05, 0, hinge_interface);
     44    
     45    dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]);
     46    dJointSetHingeAxis(hingeJoint, 0, 0, 1);
     47    
     48    //link5?link3??
     49    hingeJoint = dJointCreateHinge(world, 0);
     50    dJointAttach(hingeJoint, link5, link3);
     51    
     52    dBodyGetRelPointPos(link5, 0, -0.05, 0, hinge_interface);
     53    
     54    dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]);
     55    dJointSetHingeAxis(hingeJoint, 0, 0, 1);
     56    
     57    //link6?link3??
     58    hingeJoint = dJointCreateHinge(world, 0);
     59    dJointAttach(hingeJoint, link6, link3);
     60    
     61    dBodyGetRelPointPos(link6, 0, -0.05, 0, hinge_interface);
     62    
     63    dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]);
     64    dJointSetHingeAxis(hingeJoint, 0, 0, 1);
     65    
     66    //link4?link2??
     67    hingeJoint = dJointCreateHinge(world, 0);
     68    dJointAttach(hingeJoint, link4, link2);
     69    
     70    dBodyGetRelPointPos(link4, 0, 0.05, 0, hinge_interface);
     71    
     72    dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]);
     73    dJointSetHingeAxis(hingeJoint, 0, 0, 1);
     74    
     75    //link5?link2??
     76    hingeJoint = dJointCreateHinge(world, 0);
     77    dJointAttach(hingeJoint, link5, link2);
     78    
     79    dBodyGetRelPointPos(link5, 0, 0.05, 0, hinge_interface);
     80    
     81    dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]);
     82    dJointSetHingeAxis(hingeJoint, 0, 0, 1);
     83    
     84    //link6?link2??
     85    hingeJoint = dJointCreateHinge(world, 0);
     86    dJointAttach(hingeJoint, link6, link2);
     87    
     88    dBodyGetRelPointPos(link6, 0, 0.05, 0, hinge_interface);
     89    
     90    dJointSetHingeAnchor(hingeJoint, hinge_interface[0], hinge_interface[1], hinge_interface[2]);
     91    dJointSetHingeAxis(hingeJoint, 0, 0, 1);
     92 }
     93 
     94 void webots_physics_step() {
     95 
     96 }
     97 
     98 void webots_physics_draw() {
     99   
    100 }
    101 
    102 int webots_physics_collide(dGeomID g1, dGeomID g2) {
    103 
    104   return 0;
    105 }
    106 
    107 void webots_physics_cleanup() {
    108 
    109 }

         设置完成物理引擎,在worldInfo节点下physics节点下选择该物理插件。控制器代码如下:

     1 //来自“博客园,_阿龙clliu” http://www.cnblogs.com/clliu/
     2 #include <webots/robot.h>
     3 #include <webots/servo.h>
     4 #include <assert.h>
     5 #include <math.h>
     6 
     7 #define TIME_STEP 32
     8 #define rad_2_deg(X) ( X / pi * 180.0 )
     9 #define deg_2_rad(X) ( X / 180.0 * pi )
    10 #define pi 3.1415926
    11 #define frep 1
    12 
    13 int main(int argc, char **argv)
    14 {
    15 
    16   double t = 0;
    17   double servo_pos;
    18   
    19   
    20   wb_robot_init();
    21   
    22   WbDeviceTag servo;
    23   servo = wb_robot_get_device("link2");
    24   assert(servo);
    25   
    26   while (wb_robot_step(TIME_STEP) != -1) {
    27   
    28     
    29     servo_pos = 45 + 45 * sin(frep * t + pi);
    30     wb_servo_set_position(servo,deg_2_rad(servo_pos));
    31     
    32     t += (double)TIME_STEP / 1000.0;
    33   };
    34   
    35 
    36   wb_robot_cleanup();
    37   
    38   return 0;
    39 }

          如果没有什么错误,就能实现之前GIF的效果了,如果没做出来,也没关系,给出原文件,仿真文件下载地址

         如果有什么疑问,欢迎再下方提问。

    展开全文
  • :exclamation:怎么刷 LeetCode? 我是如何刷 LeetCode 的 算法小白如何高效、快速刷 leetcode? 刷题效率低?或许你就差这么一个插件 力扣刷题插件 《91 天学算法》限时活动 第一期讲义-二分法 第一期讲义-双...
  • MakeSrcTrgDataset函数产生的种张量如下(全部为张量) src_input: 编码器输入(源数据) src_size : 输入大小 trg_input:解码器输入(目标数据) trg_label:解码器输出(目标数据) trg_size: ...
  • 先从一个例子出发,我们现在要一个一的回归分析,资料中有个点,然后输出一个实数。 资料:,N = 5 目标函数f:f是一个二次函数(中为蓝色曲线) label:,由f产生再加一点点很小的噪音 解决方案1:4次...

    上节课讲了如何解决非线性问题:通过特征变换,将非线性模型映射到另一个空间,转换为线性模型,再来进行分类。我们说这样会增加额外的模型复杂度。今天我们说这个额外的复杂度会造成机器学习过拟合(overfitting)现象。今天讲困难怎么产生的以及如何解决它。

    一、什么是过拟合?

    先从一个例子出发,我们现在要做一个一维的回归分析,资料中有五个点,然后输出一个实数。

    资料:x \in \mathbb{R},N = 5

    目标函数f:f是一个二次函数(图中为蓝色曲线)

    label:y_n=f(x_n)+\text{small noise},由f产生再加一点点很小的噪音

    解决方案1:4次多项式做回归分析,即用四次多项式把x空间中的点转换到z空间,再进行线性回归。

    我们知道,四次多项式通过五个点,会有一个唯一解。所以E_{in}(g)=0,图中为红色曲线。

    我们发现红色曲线和真实的蓝色曲线一点都不像,实际上的E_{out}(g)很大,因为除了那五个点,其他未知点的效果都不是很好。

    所以E_{in}(g)很小,而E_{out}(g)很大,这是一种坏的泛化性。

    我们回过头来看一下VC曲线:

    就像上次说的,如果d_{VC}=1126,那么实际上的E_{out}E_{in}差距越来越大(E_{out}很大,E_{in}很小)

    可以看到随着vc维越来越大,E_{in}越来越小,in-sample error曲线一直下降,model complexity曲线就上升;

    所以造成E_{out}先下后上。

    从最好的vc维d_{VC}^*往右看,E_{in}一直下降,E_{out}一直上升。我们看样子是把fitting做好了,但其实过头了(over)。所以E_{in}变小,E_{out}变高这个过程叫做overfitting,过拟合。(常见,不容易解决)

    从最好的vc维d_{VC}^*往左看,E_{in}处于高位,E_{out}也比较大,我们做的fitting不够好,所以导致E_{out}也不够好(under),所以叫做underfitting,欠拟合。

    给出一个比喻来描述overfitting,把overfitting比作出了车祸,那么我们分析产生的原因:

    • 开太快,油门太重,即使用了太大的vc dimension。
    • 道路崎岖,也就是有太多noise。
    • 对路况不熟悉,在机器学习中就是资料太少。

    二、noise与资料

    我们从问题出发

    资料:x \in \mathbb{R}(图中为黑色圆圈)

    目标函数f:f是一个十次函数(图中为蓝色曲线)

    label:y_n=f(x_n)+\text{small noise},由f产生再加一点点很小的噪音

    可以看到由于加了噪音,数据并非全部落在蓝色曲线上

     

    另一个问题:

    资料:x \in \mathbb{R}(图中为黑色圆圈)

    目标函数f:f是一个50次函数(图中为蓝色曲线)

    label:y_n=f(x_n)

    此时,无噪音,数据全部落在蓝色曲线上

    我们知道上面两个问题了,现在来看看我们选用的两个模型,一个是2阶多项式g_2,另一个是10阶多项式g_{10},分别对上面两个问题进行建模。

    对于第一个问题来说,(目标函数f是一个十次多项式)

    首先要明确E_{in}是在已知样本上的err,是看线与圆圈的重合程度,重合越多,E_{in}越小。

    E_{out}是在未知样本上的err,是看我们模型的线与真实的线是否相同,模型的线越接近蓝色线,E_{out}越小。

    可以看到,线与圆圈的重合程度方面,红线赢了,在模型的线与真实的线是否相同方面,在图像的左端和右端,红线和蓝线十分的不接近。于是通过计算有:

    虽然10阶模型的E_{in}比2阶的小,但是它的E_{out}要比2阶的大得多,而2阶的E_{in}E_{out}相差不大,显然地,从二次切换到十次,发生了overfitting。

    同样对于另一个高维问题:

    可以看到,线与圆圈的重合程度方面,红线再一次赢了,也就是说10阶模型的E_{in}比2阶的小;在模型的线与真实的线是否相同方面,红线和蓝线十分的不接近。也就是说g_{10}E_{out}非常糟糕。

    但是我们想,比如目标函数是十次的情况,用二阶多项式g_2就是选择了放弃完美解(因为真实f是十次,只有选择十次多项式g_{10}有可能找到一模一样的或者几乎接近的线)。实际上却常常是“以退为进”,意思是就算你知道真正的f是十次多项式,你也选择一个看起来好的十次多项式作为g,那么最终结果也不一定好。

    来看看为什么会这样?

    从learning curve来分析一下具体的原因,learning curve描述的是E_{in}E_{out}随着数据量N的变化趋势。下图中左边是2阶学习模型的learning curve,右边是10阶学习模型的learning curve。我们首先要认识一个事实:如果你选择我们已知的点靠近一点点,那么在已知err上会小一点点,就是E_{in}会小一点,在图中E_{in}的线会往下一点,但是在未知err会远离一点点(因为可能向noise靠近了一点点),E_{out}会大一点,在图中E_{out}的线会往上一点。之前讲过有noise的情况的公式,之前讲过d为多项式次数,所以可以发现10阶的偏移量更大(g_{10}受到noise的影响大)。

    在左边区域,左右两张图比较,E_{in}一定是右边的比较低,E_{out}则是右边比较高,那么在左边区域(资料量不够多的时候),高阶的多项式表现都不会好,都会overfitting。所以资料量不够多的时候,千万不要选择过于复杂的多项式作为g。

    上面讲了资料,下面就讲noise。

    另一个例子中,目标函数是50阶多项式,且没有加入noise。这种情况下,我们发现仍然是2阶的模型拟合的效果更好一些,明明没有noise,为什么是这样的结果呢?

    刚才我们说,对于f是50阶的情况,g_2g_{10}都做不好,但g_2会稍微好一点。灵魂一问:真的没有noise吗?今天学的事情很复杂,无论g_2g_{10}都做不好,这个复杂的行为就和noise一样。即复杂度造成了类似noise的影响。下一节会具体讲解这个问题。

    三、什么时候要小心overfit可能发生?

    我们把产生资料的过程分为两个步骤,一个是用目标函数f,Q_f阶多项式,但要注意的是我们是产生真正的这么多阶的多项式,而不是伪装的Q_f阶多项式;再加上noise,noise服从高斯分布。接下来我们讨论Gaussian分布的noise强度不一样的时候(\sigma ^2),对我们的overfitting的影响是什么?(资料数设置为N),我们现在有三个变数,\sigma ^2(影响noise强度)、N、Q_f。于是我们研究这三个变数对overfit的影响。

    还是之前的两个模型g_2g_{10}

    g_2 \in H_2g_{10} \in H_{10},  以及显然有$E_{\text {in }}\left(g_{10}\right) \leq E_{\text {in }}\left(g_{2}\right)$

    我们用$E_{\text {out}}\left(g_{10}\right)- E_{\text {out}}\left(g_{2}\right)$来度量过拟合的程度。

    • 情况一

    下面展示了在Q_f固定为20时候,横坐标为样本数量N,纵坐标为噪声水平\sigma ^2的图像,图里的颜色代表有多么overfit,越靠近红色,过拟合程度越大,越靠近蓝色,则过拟合没有那么严重。可以发现,好的情况一般发生在N大,noise水平小的情况。

    • 情况二

    下面展示了噪声水平\sigma ^2在固定为0.1时候,横坐标为样本数量N,纵坐标为阶数Q_f的图像。图里的颜色代表有多么overfit,越靠近红色,过拟合程度越大,越靠近蓝色,则过拟合没有那么严重。大部分情况下,和上面的图比较接近,坏的情况都发生在左上角,好的情况都发生在右下角,也就是说目标越复杂。

    我们把上面情况一中的noise叫做stochastic noise,随机噪声;第二节中我们说了,模型复杂度也是一种噪声,于是把情况二中的这种noise叫做deterministic noise,可以计算出来的噪声。

    总之,在给出定以后,我们从上面两个情况来看看发生过拟合的时间点有:

    • 资料太少
    • stochastic noise太多
    • deterministic noise太多(目标函数f很复杂,目标函数一旦很复杂,那么它一定存在某个地方无法被任何一个h很完美的描述,这个地方也就产生了噪音,这些噪音如图中灰色的部分,在实际中也比较常见比如电脑生成伪随机。)
    • vc维太多

    overfitting其实很容易发生。如果教一个小朋友数数字,我们不会从实数的完备性开始讲起,我们只会举一些简单例子。同样,在学hypothesis也不用学太复杂,这样deterministic noise会小一些。

    四、如何避免overfitting呢?

    之前把overfitting比作出了车祸,我们分析了产生的原因,现在给出解决方法:

    • 油门太重,即使用了太大的vc dimension。解决方法:开慢点,即从简单的模型开始学起。
    • 道路崎岖,也就是有太多noise。解决方法:把这些崎岖的地方搞清楚,即数据清洗。数据提纯(data cleaning/pruning)。
    • 对路况不熟悉,在机器学习中就是资料太少。解决方法:增加路况资料,即现有的资料或对这个问题的了解中产生新的、多的资料(data hinting)。
    • 开太快。解决方法:适时地踩刹车,即添加正则项。
    • 其他。解决方法:时时刻刻看看仪表板,即validation 验证/交叉验证。

    本节课主要介绍简单的data cleaning/pruning和data hinting两种方法。

    比如对于手写数字问题,如果有人字写得不好看,比如图中左上角,我们看不出它为什么是“5”.若是现在有一个方法,我们可以检测出它不是真的‘5’(比如是不是靠近不同的类,而与相同的类离得远;或者是这个点err很大),这样我们有理由相信这个点是noise,接下来怎么做?

    data cleaning:把这个noise的label改过来。

    data pruning:把这个noise丢掉。

    这就是说如果知道那些点是noise,用上面两个方法做就行,难点是如何找到这个noise(现在还没有比较完美的找法)。

    如果手写字稍微转了转角度,那么这些字也是属于同一个字的。比如现在我们一共就这么多资料,当我们没有更多的资料却想告诉电脑更多的知识,那么我们可以把手上的资料转一转角度,变成新资料,然后再学习。所以,data hinting是针对N不够大的情况,如果没有办法获得更多的训练集,那么data hinting就可以对已知的样本进行简单的处理、变换,从而获得更多的样本。但是加进来的这些资料要有道理,不要和原来的差太远,不然会偏离原来的资料的分布,导致学习效果不好。

    总结:

    ​​​​​​​

    展开全文
  • 5. 测试的六条基本法则是什么:一功(功能)二可(可靠性)三效(效率)四易(易用性)五维(可维护性)六移(可移植性) 6. 回答不上来:这一块我不是很熟悉,确实学过,但是很久以前我过,但是好长时间没用了,我...
  • excel的使用

    2012-11-25 17:06:01
    以便编辑修改,可以这样:用鼠标左键单击“工具”菜单,选取“选项”命令,出现“选项”对话框,单击“视图”选项卡,接着设置“窗口选项”栏下的“公式”项有效,单击“确定”按钮(如2)。这时每个单元格中的...
  • MAPGIS地质制图工具

    2013-05-06 16:15:30
    1、 首先用Section打开工程文件,把所有文件设为编辑状态,然后对地形等高线文件进行高程赋值——新建线属性高程字段(原MapGis需要这样,用Section剖面菜单下的自动赋高程不需新建此字段(拖动操作))。...
  • A) 系统流程和模块 B) DFD、数据词典、加工说明 C) 软件结构、加工说明 D) 功能结构、加工说明 5. 画分层DFD的基本原则有(A C D)。 A) 数据守恒原则 B) 分解的可靠性原则 C) 子、父...
  • 但是刚才那个中虽然展示了四的信息,但是各个维度都叠加在一起,不利于观察,这个时候我们就可以使用一些特别的技巧了,其中一个技巧叫分面。它可以将原来的一个图形按照某种分类规则...

空空如也

空空如也

1 2 3
收藏数 50
精华内容 20
热门标签
关键字:

五维图怎么做