精华内容
下载资源
问答
  • 首先,我无法重现与您在我的Linux机器上看到的几乎一样大的性能差异。我一直看到线程版本大约20-25秒,...这意味着可能有两个或线程可以同时打印,尽管在实践中这种情况可能不会经常发生,而且可能不会对性能产...

    首先,我无法重现与您在我的Linux机器上看到的几乎一样大的性能差异。我一直看到线程版本大约20-25秒,而asyncio版本大约24-34秒。

    现在,为什么asyncio要慢?这其中有一些原因。首先,asyncio版本必须按顺序打印,但线程版本不按顺序打印。打印是I/O,因此GIL可以在发生时释放。这意味着可能有两个或多个线程可以同时打印,尽管在实践中这种情况可能不会经常发生,而且可能不会对性能产生太大的影响。

    其次,更重要的是,getaddrinfo的asyncio版本实际上是just calling ^{} in a ^{}:def getaddrinfo(self, host, port, *,

    family=0, type=0, proto=0, flags=0):

    if self._debug:

    return self.run_in_executor(None, self._getaddrinfo_debug,

    host, port, family, type, proto, flags)

    else:

    return self.run_in_executor(None, socket.getaddrinfo,

    host, port, family, type, proto, flags)

    它使用默认的ThreadPoolExecutor作为这个,which only has five threads:# Argument for default thread pool executor creation.

    _MAX_WORKERS = 5

    对于这个用例,这几乎不是您想要的那么多并行性。要使其行为更像threading版本,您需要对1000个线程使用ThreadPoolExecutor,方法是通过loop.set_default_executor将其设置为默认执行器:loop = asyncio.get_event_loop()

    loop.set_default_executor(ThreadPoolExecutor(1000))

    coroutines = asyncio.wait([getaddr(loop, i+site) for i in create_host(char)])

    loop.run_until_complete(coroutines)

    现在,这将使行为更等价于threading,但这里的实际情况是您实际上没有使用异步I/O—您只是将threading与不同的API结合使用。因此,您在这里所能做的最好的事情就是与threading示例的性能相同。

    最后,您并没有在每个示例中真正运行等效代码,threading版本使用一个工作池,它共享一个queue.Queue,而asyncio版本则为url列表中的每个项生成一个协程。如果我将asyncio版本设置为使用asyncio.Queue和协程池,除了删除print语句和设置更大的默认执行器之外,这两个版本的性能基本相同。这是新的asyncio代码:import asyncio

    import string

    import time

    from concurrent.futures import ThreadPoolExecutor

    start = time.time()

    def create_host(char):

    for i in char:

    yield i

    for i in create_host(char):

    if len(i)>1:

    return False

    for c in char:

    yield c + i

    char = string.digits + string.ascii_lowercase

    site = '.google.com'

    @asyncio.coroutine

    def getaddr(loop, q):

    while True:

    url = yield from q.get()

    if not url:

    break

    try:

    res = yield from loop.getaddrinfo(url,80)

    except:

    pass

    @asyncio.coroutine

    def load_q(loop, q):

    for host in create_host(char):

    yield from q.put(host+site)

    for _ in range(NUM):

    yield from q.put(None)

    NUM = 1000

    q = asyncio.Queue()

    loop = asyncio.get_event_loop()

    loop.set_default_executor(ThreadPoolExecutor(NUM))

    coros = [asyncio.async(getaddr(loop, q)) for i in range(NUM)]

    loop.run_until_complete(load_q(loop, q))

    loop.run_until_complete(asyncio.wait(coros))

    end = time.time()

    print(end-start)

    以及每种产品的产量:dan@dandesk:~$ python3 threaded_example.py

    20.409344911575317

    dan@dandesk:~$ python3 asyncio_example.py

    20.39924192428589

    不过,请注意,由于网络的原因,有些变化。他们两个有时都会比这慢几秒。

    展开全文
  • 首先,我无法重现与我在Linux机器上看到的性能差异几乎一样大的性能差异.对于线程版本,我一直看到大约20-25秒,对于...这意味着潜在的两个或更线程可以在同一时间打印,但实际上它可能不会经常发生,并且可能不会...

    首先,我无法重现与我在Linux机器上看到的性能差异几乎一样大的性能差异.对于线程版本,我一直看到大约20-25秒,对于asyncio版本在24-34秒之间.

    现在为什么asyncio慢了?有一些事情有助于此.首先,asyncio版本必须顺序打印,但线程版本不会.打印是I / O,所以GIL可以在发生时被释放.这意味着潜在的两个或更多的线程可以在同一时间打印,但实际上它可能不会经常发生,并且可能不会在性能上产生太大的差异.

    def getaddrinfo(self, host, port, *,

    family=0, type=0, proto=0, flags=0):

    if self._debug:

    return self.run_in_executor(None, self._getaddrinfo_debug,

    host, port, family, type, proto, flags)

    else:

    return self.run_in_executor(None, socket.getaddrinfo,

    host, port, family, type, proto, flags)

    它使用默认的ThreadPoolExecutor为这个,which only has five threads:

    # Argument for default thread pool executor creation.

    _MAX_WORKERS = 5

    这不是这个用例所需的并行几何.为了使其更像线程版本,您需要使用具有1000个线程的ThreadPoolExecutor,通过loop.set_default_executor将其设置为默认执行程序:

    loop = asyncio.get_event_loop()

    loop.set_default_executor(ThreadPoolExecutor(1000))

    coroutines = asyncio.wait([getaddr(loop, i+site) for i in create_host(char)])

    loop.run_until_complete(coroutines)

    现在,这将使行为更相当于线程,但这里的现实是您真的不使用异步I / O – 您只是使用不同的API线程.所以在这里你可以做的最好的是与线程示例相同的性能.

    最后,在每个示例中,你并没有真正运行等效的代码 – 线程版本正在使用一个工作池,它们共享一个queue.Queue,而asyncio版本为url列表中的每个项目生成一个协同程序.如果我使asyncio版本使用asyncio.Queue和协同池池,除了删除打印语句和制作更大的默认执行程序之外,我的两个版本的性能基本相同.这是新的asyncio代码:

    import asyncio

    import string

    import time

    from concurrent.futures import ThreadPoolExecutor

    start = time.time()

    def create_host(char):

    for i in char:

    yield i

    for i in create_host(char):

    if len(i)>1:

    return False

    for c in char:

    yield c + i

    char = string.digits + string.ascii_lowercase

    site = '.google.com'

    @asyncio.coroutine

    def getaddr(loop, q):

    while True:

    url = yield from q.get()

    if not url:

    break

    try:

    res = yield from loop.getaddrinfo(url,80)

    except:

    pass

    @asyncio.coroutine

    def load_q(loop, q):

    for host in create_host(char):

    yield from q.put(host+site)

    for _ in range(NUM):

    yield from q.put(None)

    NUM = 1000

    q = asyncio.Queue()

    loop = asyncio.get_event_loop()

    loop.set_default_executor(ThreadPoolExecutor(NUM))

    coros = [asyncio.async(getaddr(loop, q)) for i in range(NUM)]

    loop.run_until_complete(load_q(loop, q))

    loop.run_until_complete(asyncio.wait(coros))

    end = time.time()

    print(end-start)

    并输出:

    dan@dandesk:~$python3 threaded_example.py

    20.409344911575317

    dan@dandesk:~$python3 asyncio_example.py

    20.39924192428589

    注意,由于网络有一些变异性.他们都有时比这慢几秒钟.

    展开全文
  • 常见的3D绘图的程序库有很MATLAB、Python的Matplotlib、OpenGL。在Linux上常用的一个3D绘图库是Pangolin,它是基于OpenGL完成的,它不但支持OpenGL的基本操作,还提供了一些GUI的功能。对于在SLAM的学习中,它是...

    1. Pangolin介绍

    常见的3D绘图的程序库有很多,MATLAB、Python的Matplotlib、OpenGL。在Linux上常用的一个3D绘图库是Pangolin,它是基于OpenGL完成的,它不但支持OpenGL的基本操作,还提供了一些GUI的功能。对于在SLAM的学习中,它是必不可少的3D显示工具。

    2.安装

    (1) 安装依赖库

    sudo apt install libgl1-mesa-dev
    sudo apt install libglew-dev
    sudo apt install cmake
    
    #建议安装的库
    sudo apt install libpython2.7-dev
    sudo apt install pkg-config
    sudo apt install libegl1-mesa-dev libwayland-dev libxkbcommon-dev wayland-protocols
    

    另外还有一些可选的库,包括视频输入CUDA相关,根据自己的需求选择安装。

    (2)安装源文件

    git clone https://github.com/stevenlovegrove/Pangolin.git
    cd Pangolin
    mkdir build
    cd build
    cmake ..
    cmake --build .
    

    3.使用方法

    以下使用的所有代码,编译时对应的CMakeLists.txt文件如下:

    cmake_minimum_required(VERSION 3.16)
    project(generate_test)
    
    set(CMAKE_CXX_STANDARD 11)
    set(CMAKE_BUILD_TYPE "release")
    find_package(Pangolin REQUIRED)
    include_directories(${Pangolin_INCLUDE_DIRS})
    
    add_executable(generate_test main.cpp)
    target_link_libraries(
        ${Pangolin_LIBRARIES}
    )
    

    3.1 常见的使用形式

    Pangolin常用代码形式如下,为了避免注释都写在代码中看起来很乱,我先贴出代码,然后逐行解释。

    #include <pangolin/pangolin.h>
    int main()
    {
        pangolin::CreateWindowAndBind("Main",640,480);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        
        pangolin::OpenGlRenderState s_cam(
            pangolin::ProjectionMatrix(640,480,420,420,320,320,0.2,100),
            pangolin::ModelViewLookAt(2,0,2, 0,0,0, pangolin::AxisY)
        );
        
        pangolin::Handler3D handler(s_cam); 
        pangolin::View& d_cam = pangolin::CreateDisplay()
                .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f)
                .SetHandler(&handler);
    
        while( !pangolin::ShouldQuit() )
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            d_cam.Activate(s_cam);
            
           //需要绘制的东西写在这里
           ..................
           //
           
            pangolin::FinishFrame();
        }
    
        return 0;
    }
    

    下面逐行介绍代码的意思:

    (1) pangolin::CreateWindowAndBind("Main",640,480);
    创建一个名叫"Main"的GUI窗口用于显示,窗口的大小是640x480像素。

    (2)glEnable(GL_DEPTH_TEST);
    启动深度测试,开启这个功能之后,窗口中只会绘制面朝相机的那一面像素。一般如果你使用的3D可视化,就要打开这个功能。

    (3)glEnable(GL_BLEND);
    打开颜色混合,把某一像素位置原来的颜色和将要画上去的颜色,通过某种方式混在一起,从而实现特殊的效果。这个有点儿类似你透过红色玻璃看绿色物体的效果。

    (4)glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    使用glEnable(GL_BLEND);之后,后面紧跟着这行代码,表示两种颜色以怎么样的方式进行混合。我默认情况下就是使用这种方法,目前使用上没有碰到问题。如果你感兴趣更进一步的使用,可以参考这个博客

    (5)

    pangolin::OpenGlRenderState s_cam(
    	pangolin::ProjectionMatrix(640,480,420,420,320,320,0.2,100),
    	pangolin::ModelViewLookAt(2,0,2, 0,0,0, pangolin::AxisY)
    );
    

    该行代码表示创建一个相机的观察视图,相当于是模拟一个真实的相机去观测虚拟的三维世界。既然是模拟相机观测,那就得有相机的一些配置参数:

    • ProjectMatrix(int h, int w, int fu, int fv, int cu, int cv, int znear, int zfar)是用来配置相机的内参,参数依次为相机的图像高度、宽度、4个内参以及最近和最远视距
    • ModelViewLookAt(double x, double y, double z,double lx, double ly, double lz, AxisDirection Up)
      前三个参数依次为相机所在的位置,第四到第六个参数相机所看的视点位置(一般会设置在原点),最后是相机轴的方向,最终在GUI中呈现的图像就是通过这个设置的相机内外参得到的。你可以用自己的脑袋当做例子,前三个参数告诉你脑袋在哪里,然后再告诉你看的东西在哪里,最后告诉你的头顶朝着哪里。

    (6)pangolin::Handler3D handler(s_cam);
    创建相机视图句柄,需要使用它来显示前面设置的相机所“拍摄”到的内容

    (7)

    pangolin::View& d_cam = pangolin::CreateDisplay()
                .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f)
                .SetHandler(&handler);
    

    进行显示设置。SetBounds函数前四个参数依次表示视图在视窗中的范围(下、上、左、右),最后一个参数是显示的长宽比。(0.0, 1.0, 0.0, 1.0)第一个参数0.0表示显示的拍摄窗口的下边在整个GUI中最下面,第二个参数1.0表示上边在GUI的最上面,以此类推。如果在中间就用0.5表示。

    (9)pangolin::ShouldQuit()
    检测你是否关闭OpenGL窗口

    (10)glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    清空颜色和深度缓存。这样每次都会刷新显示,不至于前后帧的颜信息相互干扰。

    (11)d_cam.Activate(s_cam);
    激活显示并设置状态矩阵。

    (12)pangolin::FinishFrame();
    执行后期渲染,事件处理和帧交换,相当于前面设置了那么多现在可以进行最终的显示了。

    以上就是一个完整的Pangolin用法,其中你要显示的东西就可以写在代码中我标注的//需要绘制的东西写在这里

    是不是很简单的

    下面我要向你实际介绍一些用法,包括怎么绘制点、直线、轨迹等等,甚至还包括多线程显示、按钮操作等等。

    3.2 绘制点、直线、三角形等

    #include <pangolin/pangolin.h>
    
    int main() {
        pangolin::CreateWindowAndBind("Main",640,480);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        pangolin::OpenGlRenderState s_cam(
                pangolin::ProjectionMatrix(640,480,420,420,320,320,0.2,100),
                pangolin::ModelViewLookAt(2,0,2, 0,0,0, pangolin::AxisY)
        );
    
        pangolin::Handler3D handler(s_cam);
        pangolin::View& d_cam = pangolin::CreateDisplay()
                .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f)
                .SetHandler(&handler);
    
        while( !pangolin::ShouldQuit() )
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            d_cam.Activate(s_cam);
    
            //绘制点
            glBegin( GL_POINTS );//点设置的开始
            glColor3f(1.0,1.0,1.0);
            glVertex3f(0.0f,0.0f,0.0f);
            glVertex3f(1,0,0);
            glVertex3f(0,2,0);
            glEnd();//点设置的结束
    
    		//绘制直线
    		glBegin(GL_LINES);
            glLineWidth(2.0);
            glColor3f(1.0, 1.0, 1.0);
            glVertex3f(0,0,0);
            glVertex3f(1,1,1);
            glVertex3f(0,0,0);
            glVertex3f(0,1,1);
            glVertex3f(0,0,0);
            glVertex3f(1,0,1);
            glEnd();
    
           //绘制三角形
            glBegin(GL_TRIANGLES);
            glVertex3f(0,1,1);
            glVertex3f(0,0,0);
            glVertex3f(1,0,1);
            glEnd();
    
            pangolin::FinishFrame();
        }
    
        return 0;
    }
    
    

    可设置的形状还有

    • GL_POINTS:点
    • GL_LINES:线
    • GL_LINE_STRIP:折线
    • GL_LINE_LOOP:封闭折线
    • GL_TRIANGLES:三角形
    • GL_POLYGON:多边形

    总之你绘制的图形必须,以及图像的相关设置必须放在glBegin()glEnd()之间。这之间还有一些可用的配置如下:

    • glVertex(); 设置顶点坐标
    • glColor(); 设置当前颜色
    • glIndex(); 设置当前颜色表
    • glNormal(); 设置法向坐标
    • glEvalCoord(); 产生坐标
    • glCallList(),glCallLists(); 执行显示列表
    • glTexCoord(); 设置纹理坐标
    • glEdgeFlag(); 控制边界绘制
    • glMaterial(); 设置材质

    3.3 GUI交互按钮

    #include <pangolin/pangolin.h>
    
    void function(){
        std::cout << "Hello pangolin" << std::endl;
    }
    
    int main() {
        pangolin::CreateWindowAndBind("Main",640,480);
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        pangolin::OpenGlRenderState s_cam(
                pangolin::ProjectionMatrix(640,480,420,420,320,320,0.2,100),
                pangolin::ModelViewLookAt(2,0,2, 0,0,0, pangolin::AxisY)
        );
    
        pangolin::Handler3D handler(s_cam);
        pangolin::View& d_cam = pangolin::CreateDisplay()
                .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f)
                .SetHandler(&handler);
    
        pangolin::CreatePanel("ui").SetBounds(0.0, 1.0, 0.0, pangolin::Attach::Pix(180));//创建
    
        pangolin::Var<bool> a_button("ui.A_Button", false, false);//设置一个按钮,默认值为false,最后一个false表示按钮形式
        pangolin::Var<double> a_double("ui.A_Double", 3, 0, 5);//设置一个double的、可拖动变换值的玩意(不知道咋形容)!
        pangolin::Var<int> a_int("ui.A_Int", 2, 0, 5);//设置一个int的、可拖动变换值的玩意
        pangolin::Var<std::function<void(void)>> reset("ui.Reset", function);//设置一个按钮,用于调用function函数
    
        while( !pangolin::ShouldQuit() )
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            d_cam.Activate(s_cam);
    
            if (pangolin::Pushed(a_button)){//如果a_button按钮被点,就运行if里面的语句
                std::cout << "You tough a_buttom" << std::endl;
                a_double = 0;
                a_int = 0;
            }
    
            glColor3f(1.0, 1.0, 1.0);
            pangolin::glDrawColouredCube();
    
            pangolin::FinishFrame();
        }
    
        return 0;
    }
    

    运行上面的代码,你会获得如下图所示的界面,试着点击左边的按钮,看看你的终端出现了什么。
    在这里插入图片描述

    3.4 多窗口显示

    下面的代码,前面几乎都出现过了,就不在细致解释了。

    #include <iostream>
    #include <pangolin/pangolin.h>
    
    void setImageData(unsigned char * imageArray, int size){
        for(int i = 0 ; i < size;i++) {
            imageArray[i] = (unsigned char)(rand()/(RAND_MAX/255.0));
        }
    }
    
    int main(/*int argc, char* argv[]*/)
    {
        pangolin::CreateWindowAndBind("Main",640,480);
    
        glEnable(GL_DEPTH_TEST);
        glEnable (GL_BLEND);
        glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    
        pangolin::OpenGlMatrix proj = pangolin::ProjectionMatrix(640,480,420,420,320,240,0.1,1000);
        pangolin::OpenGlRenderState s_cam(proj, pangolin::ModelViewLookAt(1,0.5,-2,0,0,0, pangolin::AxisY) );
        pangolin::OpenGlRenderState s_cam2(proj, pangolin::ModelViewLookAt(0,0,-2,0,0,0, pangolin::AxisY) );
    
        pangolin::View& d_cam1 = pangolin::Display("cam1")
                .SetAspect(640.0f/480.0f)
                .SetHandler(new pangolin::Handler3D(s_cam));
    
        pangolin::View& d_cam2 = pangolin::Display("cam2")
                .SetAspect(640.0f/480.0f)
                .SetHandler(new pangolin::Handler3D(s_cam2));
    
        pangolin::View& d_cam3 = pangolin::Display("cam3")
                .SetAspect(640.0f/480.0f)
                .SetHandler(new pangolin::Handler3D(s_cam));
    
        pangolin::View& d_cam4 = pangolin::Display("cam4")
                .SetAspect(640.0f/480.0f)
                .SetHandler(new pangolin::Handler3D(s_cam2));
    
        pangolin::View& d_img1 = pangolin::Display("img1")
                .SetAspect(640.0f/480.0f);
    
        pangolin::View& d_img2 = pangolin::Display("img2")
                .SetAspect(640.0f/480.0f);
    
        pangolin::Display("multi")
                .SetBounds(0.0, 1.0, 0.0, 1.0)
                .SetLayout(pangolin::LayoutEqual)
                .AddDisplay(d_cam1)
                .AddDisplay(d_img1)
                .AddDisplay(d_cam2)
                .AddDisplay(d_img2)
                .AddDisplay(d_cam3)
                .AddDisplay(d_cam4);
    
        const int width =  64;
        const int height = 48;
        unsigned char* imageArray = new unsigned char[3*width*height];
        pangolin::GlTexture imageTexture(width,height,GL_RGB,false,0,GL_RGB,GL_UNSIGNED_BYTE);
    
        while( !pangolin::ShouldQuit() )
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
            setImageData(imageArray,3*width*height);
            imageTexture.Upload(imageArray,GL_RGB,GL_UNSIGNED_BYTE);
    
            glColor3f(1.0,1.0,1.0);
    
            d_cam1.Activate(s_cam);
            pangolin::glDrawColouredCube();
    
            d_cam2.Activate(s_cam2);
            pangolin::glDrawColouredCube();
    
            d_cam3.Activate(s_cam);
            pangolin::glDrawColouredCube();
    
            d_cam4.Activate(s_cam2);
            pangolin::glDrawColouredCube();
    
            d_img1.Activate();
            glColor4f(1.0f,1.0f,1.0f,1.0f);
            imageTexture.RenderToViewport();
    
            d_img2.Activate();
            glColor4f(1.0f,1.0f,1.0f,1.0f);
            imageTexture.RenderToViewport();
    
            pangolin::FinishFrame();
        }
    
        delete[] imageArray;
    
        return 0;
    }
    

    运行代码之后,可以获得如下效果。
    在这里插入图片描述

    3.5 多线程

    以下代码完成的任务是,新开一个线程,然后显示一个立方体。

    #include <pangolin/pangolin.h>
    #include <thread>
    
    static const std::string window_name = "HelloPangolinThreads";
    
    void setup() {
        pangolin::CreateWindowAndBind(window_name, 640, 480);
    
        glEnable(GL_DEPTH_TEST);
    
        pangolin::GetBoundWindow()->RemoveCurrent();
        //setup()函数是在主线程创建的,因此在主线程调用完之后,需要使用GetBoundWindow()->RemoveCurrent()对其解绑
    }
    
    void run() {
        pangolin::BindToContext(window_name);
        glEnable(GL_DEPTH_TEST);
    
        pangolin::OpenGlRenderState s_cam(
                pangolin::ProjectionMatrix(640,480,420,420,320,240,0.2,100),
                pangolin::ModelViewLookAt(-2,2,-2, 0,0,0, pangolin::AxisY)
        );
    
        pangolin::Handler3D handler(s_cam);
        pangolin::View& d_cam = pangolin::CreateDisplay()
                .SetBounds(0.0, 1.0, 0.0, 1.0, -640.0f/480.0f)
                .SetHandler(&handler);
    
        while( !pangolin::ShouldQuit() )
        {
            glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
            d_cam.Activate(s_cam);
    
            pangolin::glDrawColouredCube();
    
            pangolin::FinishFrame();
        }
    
        pangolin::GetBoundWindow()->RemoveCurrent();
    }
    
    int main()
    {
        setup();
    
        std::thread render_loop;//新建一个线程
        render_loop = std::thread(run);//然后将函数run加载到线程中
        render_loop.join();
    
        return 0;
    }
    

    4 总结

    Pangolin确实是一个很简单好用的3D显示库,加上GUI的一些交互操作简直飞起。如果你不会使用ROS或者闲ROS运行麻烦,使用Pangolin显示一些3D效果十分方便。

    我相信看完我上面的总结的一些代码和用法,你基本已经掌握了Pangolin编程的思路了。如果你还有别的要求,或者本文的内容不能满足你的要求,你可以参考Pangolin官方例程进行学习。

    Pangolin官方example:
    https://github.com/stevenlovegrove/Pangolin/tree/master/examples

    展开全文
  • MATLAB串口通信

    万次阅读 多人点赞 2015-05-20 16:28:36
    Matlab并不具备直接访问硬件的能力,但是支持面向对象技术,通过调用Instrument Control Toolbox中的serial类函数来创建串口对象,对串口对象操作就是对...Matlab多线程技术实现这种异步操作,通过异步读写设置,计
     Matlab并不具备直接访问硬件的能力,但是支持面向对象技术,通过调用Instrument Control Toolbox中的serial类函数来创建串口对象,对串口对象操作就是对串口操作,使用起非常方便。同时,Matlab封装的串口对象支持对串口的异步读写操作,使得计算机在读写串口时能同时进行其他处理工作,因而能大大提高计算机执行效率。Matlab用多线程技术实现这种异步操作,通过异步读写设置,计算机在执行读写串口函数时能立即返回不必等待串口把数据传输完毕,当指定的数据传输结束时就触发事件,执行事件回调函数,可以在事件回调函数中编程,进行数据处理,这样就不会造成因等待串口传输数据引起的时间浪费。
    

    MATLAB的Instrument Control Toolbox提供了 MATLAB与仪器仪表通信的功能 ,它支持 GPIB 通用接口总线 、VISA、TCP/ IP、UDP、RS2232等多个协议 ,具有同步和异步读写功能以及事件处理和回调操作功能,可读写和记录二进制和ASCII文本数据。与串口有关的主要函数如下[3]:

    1)建立串口对象函数:obj=seril(’port’,’property name’,propertyvalue……),其中主要的属性有:baudrate(波特率),databits(数据位),parity(校验方式),stopbits(终止位)等,可以在初始化时进行赋值或者使用set函数。
    (2)打开串口设备对象:fopen(obj)
    (3)串口读写操作:当matlab通信数据采用二进制格式时,读写串口设备的命令为fread()和fwrite();当通行数据采用文本(ASCII)格式时,读写串口设备的命令为fscanf()和fprintf()。
    (4)关闭并清除设备对象:
    Fclose(obj);%关闭串口设备对象
    Delete(obj);%删除内存中的串口设备对象

    基于本系统串口通信协议,对串口对象的读写部分程序如下(简单例程),查询方式

    Obj=serial(’com1’,’baudrate’,9600,’parity’,’none’,’databits’,8,’stopbits’,1);%初始化串口
    Fopen(obj);%打开串口对象
    Fwrite(obj,256);%向串口发送握手信号0xff
    TMP=fread(obj,3,’unit8’);%从串口读取3字节数据,后2个即是16bit温度数据
    If TMP(1)= =256   %判断第一个字节受否是握手信号
    For i = 13
    Dat(i)=TMP(i+1);%剔除第一个握手信号字节
    End
    End
    Fclose(obj);%关闭串口设备对象
    Delete(obj);%删除内存中的串口设备对象 

    2.中断方式通信
    参考:http://blog.sina.com.cn/s/blog_62de76a90100fhbw.html
    从Matlab6.0版本开始,Mathworks公司在软件中增加了设备控制箱(instrument control toolbox),提供了对RS-232/RS-485通信标准串口通信正式支持。利用该工具箱serial类及instrcallback()回调函数,能可靠地进行实时串地通信。为此,笔者充分结合单片机和Matlab优点,基于事件驱动中断通信机制,提出了一种Matlab环境下PC机与单片机实时串行通信数据处理方法,极大地简化开发流程,提高了系统开发效率。另外,与目前普遍采用基于Matlab查询方式下非实时串行通信技术相比,这种方法实用性也大大增强了
    在Matlab6.0中新增设备控制工具条(instrument control toolbox)用来负责上、下位机之间通信。该设备控制工具箱特色如下:

    ①支持基于串行接口(RS-232、RS-422、RS-485)、GPIB总线(IEEE2488、HPIB标准)、VISA总线通信;

    ②通信数据支持二进制和文本(ASCII)两种方式,文本方式支持SCPI(Standard Commands for Programmable Instruments)语言;

    ③支持异步通信和同步通信;

    ④支持基于事件驱动通信。

    从以上Matlab设备控制工具箱特点可以看到,Matlab完全可以满足我们实现串行通信要求。

    3.1 Matlab对串行口控制基础知识

    Matlab对串行口编程控制主要分为四个步骤。

    ①创建串口设备对象并设置其属性。

    scom=serial(‘com1’);%创建串口1设备对象scom

    scom.Terminator=’CR’;%设置终止符为CR(回车符),缺省为LF(换行符)

    scom.InputBufferSize=1024;%输入缓冲区为256B,缺省值为512B

    scom.OutputBufferSize=1024;%输出缓冲区为256B,缺省值为512B

    scom.Timeout=0.5;%Y设置一次读或写操作最大完成时间为0.5s,缺省值为10s

    s.ReadAsyncMode=’continuous’(缺省方式);%在异步通信模式方式下,读取串口数据采用连续接收数据(continuous)缺省方式,那么下位机返回数据会自动地存入输入缓冲区中.

    注意:在些属性只有在对象没有被打开时才能改变其值,如InputBufferSize、OutputBufferSize属性等。对于一个RS-232/RS-422/RS-485串口设备对象,其属性缺省值为波特率9 600b/s,异步方式,通信数据格式为8位数据位,无奇偶校验位,1位停止位。如果要设置串口设置对象属性值与缺省值属性值相同,用户可以不用另行设置。

    另外,设置串口设置对象属性也可以用一条指令完成,如:scom=serial(‘COM1’,’BaudRate’,38400,’Parity’,’none’,’DataBits’,8,’StopBits’,1)。也可以用set命令,如set(scom,’BaudRate’,19200,’Parity’,’even’)。创建了对象后可以在Matlab命令窗口直接敲对象名并回车,看到其基本属性和当前状态。若需要知道其全部属性,可以用get(scom)命令。

    ②打开串口设备对象。

    fopen(scom);

    ③读写串口操作。初始化并打开串口调协对象之后,现在可以对串口设备对象进行读写操作,串口读写操作支持二进制和文本(ASCII)两种方式。当Matlab通信数据采用西方(ASCII)方式时,读写串口设备命令分别是fscanf、fpritf;当Matlab通信数据采用二进制方式时,读写串口设备命令分别是fread、fwrite。下面以文本方式读写串口为例:

    a.读串口。A=fscanf(scom,’%d’,[10,100];%从串口设备对象scom中读入10*100个数据填充到数组A[10,100]中,并以整型数据格式存放。PCbfans.cn提示请看下图:Matlab环境下PC与单片机的串行通信及数据处理 - huzoy - mylearning

    h.写串口。Fprintf(scom,’%s’,’RS232’,’async’);%将字符串‘RS232?’以字符数据格式写入到串口设备scom,写操作以异步方式进行。

    ④关闭并清除设备对象。

    fclose(scom);%关闭串口设备对象

    delete(scom);%删除内存中串口设备对象

    clear scom; %清除工作空间中串口设备对象

    当不再使用该串口设备对象时,顺序使用以上3条命令,可以将所创建串口对象对象清除,以免占用系统资源。

    可以看出,在Matlab中进行串行通信是十分方便,编程较为简单。而且,在Matlab中串行通信失误率很低,通信较为可靠,也可以采用增加握手信号以及数据校验等方式进一步增加通信可靠性。

    3.2 Matlab实现串行通信软件设计

    在Matlab环境下,读取串口数据方式可以分为两种—查询和中断。以查询方式进行串行通信时,如下位单片机有大量数据分时分批传送给PC机,就需要不停查询串行口缓冲区,有数据就读取;虽然编程容易,但这样做不能对数据进行实时处理,系统实时性不高,而且会极大地占用系统资源。以中断方式对串口进行控制实现串行通信,就可以实时处理下位机传送数据;但编程相对复杂一些,需要采用Matlab事件和回调函数机制。

    (1)基于Matlab查询方式异步串行通信编程

    Matlab查询方式串行通信编程虽然简单,但这种方法在实际应用中实用价值不高,下面只作简单介绍。通信源程序如下:

    clc;%初始化串口设备对象,设置串口属性为:PC机com2口,输入缓冲区为1024,读写最大完成时间为0.6s,波特率为115 200b/s,1位停止位,遇到换行符中止,硬件流控制

    g=serial(‘com2’);

    g.InputBufferSize=4096;

    g.timeout=0.6;

    g.BaudRate=115200;

    g.Parity=’none’;

    g.StopBits=1;

    g.Terminator=’LF’;

    g.FlowControl=’hardware’;

    fopen(g);%打开串口设备对象s

    fwrite(g,255);%以二进制方式发送握手信号0xFF,缺省为异步通信方式

    out=fread(g,33,’uint8’)%接收单片机发送33个数据(8位),并存入out数组中

    %释放串口设备对象

    fclose(g);

    delete(g);

    clear g;

    (2)基于Matlab中断方式实时串行通信编程

    在Matlab环境下以中断方式进行串行通信,实际上是采用事件驱动方法实现。Matlab提供了instrcallback(obj,event)回调函数,用户根据需要可以自行设置具体串行通信事件。Matlab常用串行口通信中断事件有:缓冲区有指定字节数目数据可用事件(bytes-available event)、串口接收到数据长时间处于非激活状态事件(break-interrupt event)、串行口引脚状态改变事件(pin-status event)、输出缓冲区为空事件(output empty event)等。当串口上有监视事件发生时,Matlab会自动调用回调函数进行通信事件处理。因此,事件驱动实质上是一种中断机制,而回调函数实质上相当于一个中断服务子程序。Matlab端实时串行通信程序流程如图4所示。以下是具体编程步骤。

    ①建立一个串行通信主程序:serial.m文件,在主程序中进行串口设备初始化操作,并指定回调函数中串行通信事件。

    程序主要源代码如下(创建串口设备对象、设备串口设备属性及打开串口等初始化操作代码与前述查询方式下初始化代码相同):

    %设置回调函数触发事件—当串口缓冲区中有33字节数据时,触发中断事件,此后主程序自动调用instrcallback(obj,event)回调函数

    g.BytesAvaibleFcnMode=’byte’;%中断触发事件为‘bytes-available Event’

    g.BytesAvailableFcnCount=33;%接收缓冲区每收到33个字节时,触发回调函数

    g.BytesAvailableFcn=@instrcallback;%得到回调函数句柄

    fopen(g);%连接串口设备对象

    fwrite(g,255);%写串口,发送握手信号0xFF(等价于十进制下数值255)

    ②修改instrcallback(obj,event)回调函数,对所发生串口通信事件进行处理。

    Matlab缺省回调函数instrcallback(obj,event)存在于instrcallback.m文件中。该文件实际上是一个有待于用户修改程序模块。其中只有一些最基本程序代码,能够显示导致串口中断发生是哪一类事件,中断事件所发生时间以及导致事件发生对象名等信息(修改回调函数文件时,注意要取消文件中相应信息后分号,才能够在Matlab命令窗口(command window)中将这些信息显示出来)。中断发生后通信事件处理以及通信数据分析处理任务,需要用户自行添加相应服务程序代码。

    PCbfans.cn提示请看下图:Matlab环境下PC与单片机的串行通信及数据处理 - huzoy - mylearning

    Matlab安装目标下有两个instrcallback.m文件,我们只需要修改@instrument目录下instrcallback.m文件即可。当然,在修改instrcallback.m文件之前,最好对其做一个备份。另外,需要注意是:程序调试过程中如果再次修改了该回调函数,要重新启动Matlab配置该文件,才能使得新回调函数文件生效。

    修改后instrcallback.m文件见网站www.dpj.com.cn。该修改后回调函数能够完成如下任务:

    ①实时接收单片机实时5ms发送33个串行通信数据,其中包括1个握手信号和32个A/D转换数据(这些数据是PIC单片机系统采集到传感器信号,每个数据占1字节),并存储在out数组中;

    ②对接收到数据进行处理,由于PIC单片机A/D转换值为10位,占2字节,而单片机每次只能传送1个字节数据,故将收到每两个通信数据整合成为1个真实A/D转换数据,共16个A/D转换数据,并存储在Dataout数组中;

    ③将接收到串口数据存储到serialdata.txt文件中,将整合后单片机A/D转换数据存储到一个以中断事件发生时间为文件名txt文件中;

    ④根据A/D转换数据,利用Matlab求其最大值、最小值和平均值,并利用FIR滤波器对传感器信号A/D转换值作FIR滤波处理,得到窗格为5滑动滤波平均值;

    ⑤利用Matlab中plot()函数实时绘制单片机采集到传感器信号原始波形图和FIR滤波后波形图,如图5所示,可以看到经过FIR滤波后传感器动态信号值较为稳定,精度大幅提高。

    实验证明,基于Matlab中断方式PC机与单片机实时串行通信稳定可靠,处理数据方便,编程简单,开发效率大大提高。

    4 结论

    本文介绍基于Matlab环境下PC机与PIC单片机串行通信实现方法,利用MatlabInstrument Control Tollboxserial类及instrcallback()回调函数,实现基于事件驱动实时中断通信。使开发人员可以充分利用Matlab工具箱中现有函数,方便地实现串行通信、数据分析处理和图形显示,大大简化系统上位机软件编程工作量。

    1. matlab串口GUI实现
      参考:http://blog.sina.com.cn/s/blog_4b94ff130100e7wt.html
      http://blog.sina.com.cn/s/blog_62de76a90100fhbz.html
    展开全文
  • matlab 串口 代码

    2015-07-29 14:09:30
    Matlab多线程技术实现这种异步操作,通过异步读写设置,计算机在执行读写串口函数时能立即返回不必等待串口把数据传输完毕, 当指定的数据传输结束时就触发事件,执行事件回调函数,可以在事件回调函数中编程,...
  • 操作系统进程与线程L14 CPU调度策略 进程与线程 L14 CPU调度策略 就是next下面一个进程到底是谁 操作系统在调度的时候,关键是折中,需要综合考虑。 响应时间小,是切换次数,是因为要很快切回来。切换...
  • -利用BLAS调用,自定义C循环代码或OpenMP多线程C循环代码 -可以与MATLAB结果完全或近似匹配 -在大多数情况下可以达到或超越MATLAB以提高速度 MTIMESX具有六个基本操作模式: -BLAS:始终使用BLAS库调用-LOOPS :...
  • 我们知道MATLAB擅长矩阵计算,但对于跑for循环非常低效,因此在内存足够的情况下应尽量写成矩阵或者向量化操作的形式,善用更好的数据结构、算法,以及matlab自带的函数...方法2:多线程并发替代单循环 for i = 1 : 100
  • parfor —— matlab 下的并行循环

    千次阅读 2016-10-10 19:56:03
    1. parfor:parallel for 循环我们知道,matlab 更适合的处理对象是矩阵,...这就是 parfor 的用武之地了,既然是并行运算,就是一次可以执行多次 iterations 处理(类似于操作系统的多线程作业),以加快循环的速度。
  • VC_串口通信中多线程技术的应用研究.pdf VC_和COM的预测控制算法的仿真研究.pdf VC_和Excel对象接口的研究与应用.pdf VC_和Matlab混合编程的语音识别研究.pdf VC_实现Excel操作自动化的方法研究与应用.pdf VC_实现...
  • 用过几年MATLAB之后,开始逐渐转向...c++速度就要快很多,支持多线程,其他方面就挺繁琐的了。 整理一下两者发送邮件的程序,在计算完成后通知我,对我这样的懒人挺有用的。 MATLAB发邮件,写成一个函数比较方便。
  • VC_串口通信中多线程技术的应用研究.pdf VC_和COM的预测控制算法的仿真研究.pdf VC_和Excel对象接口的研究与应用.pdf VC_和Matlab混合编程的语音识别研究.pdf VC_实现Excel操作自动化的方法研究与应用.pdf VC_实现...
  • VC_串口通信中多线程技术的应用研究.pdf VC_和COM的预测控制算法的仿真研究.pdf VC_和Excel对象接口的研究与应用.pdf VC_和Matlab混合编程的语音识别研究.pdf VC_实现Excel操作自动化的方法研究与应用.pdf VC_实现...
  • VC_串口通信中多线程技术的应用研究.pdf VC_和COM的预测控制算法的仿真研究.pdf VC_和Excel对象接口的研究与应用.pdf VC_和Matlab混合编程的语音识别研究.pdf VC_实现Excel操作自动化的方法研究与应用.pdf VC_实现...
  • 语音识别的MATLAB实现

    热门讨论 2009-03-03 21:39:18
    语音识别的MATLAB实现 声控小车结题报告 小组成员:关世勇 吴庆林 一、 项目要求: 声控小车是科大华为科技制作竞赛命题组的项目,其要求是编写一个语言识别程序并适当改装一个小型机动车,使之在一个预先不知道...
  • 2012-05-26 09:09 14,937,205 POSIX多线程程序设计中文版.pdf 2012-05-26 09:25 15,681,441 模拟电子技术基础.第三版高等教育出版社.pdf 2012-05-26 09:05 17,897,848 [深入解析Windows操作系统.第5版].pdf 2012-05-...
  • python3多线程1. 简介NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。最主要的数据结构是ndarray数组。NumPy 通常与 SciPy...
  • 串口通讯

    2017-07-12 12:50:20
    Matlab并不具备直接访问硬件的能力,但是支持面向对象技术,通过调用Instrument Control Toolbox中的serial类函数来创建串口对象,对串口对象操作就是对串口...Matlab多线程技术实现这种异步操作,通过异步读写设置,
  • 为实现图像处理技术在冲压件表面缺陷在线检测...使用多线程技术实现高效的检测算法。经实验,系统能够对生产线上每一个冲压件进行快速检测,并检测出有缺陷的冲压件,整个过程耗时在100 ms以内,能够满足在线实时检测需求。
  • 涉及到到的知识点:二维数组与指针、结构体数组与指针、动态内存分配、函数指针、全局变量、多线程与线程锁、结构体与指针函数实现类、顺序循环队列读写操作、VS下使用OpenGL实时(双缓冲技术)绘制散点图等,以及...
  • lua图像库_libvips

    2020-12-21 11:08:53
    软件简介libvips 是一个需求驱动的多线程图像处理库。与类似的库相比,libvips运行速度快,占用的内存很少。它有大约300个操作,包括算术,直方图,卷积,形态学操作,频率滤波,颜色,重采样,统计等。它支持多种...
  • ECO(Efficient Convolution Operators for Tracking)解析

    千次阅读 热门讨论 2018-04-03 16:27:00
    前一段时间将ECO_HC使用C++重新实现了一下,使用多线程速度上达到原matlab版的4倍左右,电脑上能达到100帧,某些情况下能达到160帧。如果你也准备实现,使用Eigen进行矩阵操作是个很好的选择。未来有可能将我的实现...
  • libvips是一个多线程的高性能图片处理库,运行速度快,占用的内存很少,支持C,C ++,Ruby,Python,PHP,C#/ .NET,Go和Lua。可以用来对图片做算术,直方图,卷积,形态学操作,频率滤波,颜色,重采样,统计等...
  • 实例15 利用Java的多线程技术实现并行多任务的管理 实例16 在Win32系统中引导Java程序 实例17 利用Java实现一个非线性规划问题 实例18 实现Java中的JTable与Excel之间的数据交换 实例19 用Java实现CORBA服务...
  • 实例13 基于Java语言的多线程同步机制 实例14 Java程序中的多线程实现 实例15 利用Java的多线程技术实现并行多任务的管理 实例16 在Win32系统中引导Java程序 实例17 利用Java实现一个非线性规划问题 实例...
  • Matlab多线程工具Timer matlab与C联合编程 位反转算法 位运算的绝妙用法 数组的指针特性 整数转字符串的一种快速实现 找了几道研究生复试面试题 复习找工作之排序算法 Linux CentOS在Win7下的硬盘安装 CentOS...
  • vc代码合集

    2012-06-11 11:34:52
    2012-06-11 10:37 151,588 多线程Java Socket编程示例.html 2012-06-11 09:46 56,832 存储管理动态分区分配算法的模拟.doc 2012-06-11 09:45 32,389 完整的串口通信程序VC++源码.7z 2012-06-11 10:41 2,183,866 对...
  • 纸张计数显示装置基于RT-Thread实时操作系统,硬件平台采用STM32F407单片机为主控制器,以具有抗电磁干扰(EMI)架构的FDC2214模块作为电容采集传感器,通过屏蔽双绞线连接至两铜极板,读取采集的数据并进行相应判断...

空空如也

空空如也

1 2 3
收藏数 44
精华内容 17
关键字:

matlab多线程操作

matlab 订阅