导航

    蓝鲸ROS机器人论坛

    • 注册
    • 登录
    • 搜索
    • 版块
    • 话题
    • 热门
    1. 主页
    2. weijiz
    3. 帖子
    ROS交流群
    ROS Group
    产品服务
    Product Service
    开源代码库
    Github
    官网
    Official website
    技术交流
    Technological exchanges
    激光雷达
    LIDAR
    ROS教程
    ROS Tourials
    深度学习
    Deep Learning
    机器视觉
    Computer Vision
    • 资料
    • 关注 0
    • 粉丝 11
    • 主题 248
    • 帖子 705
    • 最佳 11
    • 群组 1

    weijiz 发布的帖子

    • cmake的简单使用

      在用别人写的c或者c++程序的时候。最经常见到的就是cmakelist.txt这个文件了。通常想要编译程序的时候需要执行

      cmake
      make
      make install
      

      这里cmake就是根据cmakelist.txt文件生成编译时使用的makefile文件
      一个程序的编译过程需要经过两个主要的过程。一个是把各个文件编译成机械码,另一个是把编译出的各个文件的机械码链接成一个文件。而cmakelist.txt的作用就是告诉编译软件头文件和链接库在什么地方,以及添加一些编译的特殊参数。下面就简单介绍一下cmakelist.txt应该怎么写。这里只介绍基本的功能,目的是快速上手,所以算是一个 cmakelist.txt quick start guide.

      以下面这个文件为例

      cmake_minimum_required(VERSION 2.8.3)
      
      project(orb_slam2)
      find_package(catkin REQUIRED COMPONENTS
        roscpp
        sensor_msgs
        image_transport
        message_filters
        cv_bridge
        cmake_modules)
      
      set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}  -Wall  -O3 -march=native ")
      set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall  -O3 -march=native")
      
      # Check C++11 or C++0x support
      include(CheckCXXCompilerFlag)
      CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
      CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
      if(COMPILER_SUPPORTS_CXX11)
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
         add_definitions(-DCOMPILEDWITHC11)
         message(STATUS "Using flag -std=c++11.")
      elseif(COMPILER_SUPPORTS_CXX0X)
         set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
         add_definitions(-DCOMPILEDWITHC0X)
         message(STATUS "Using flag -std=c++0x.")
      else()
         message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
      endif()
      
      LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/../../../cmake_modules)
      
      find_package(OpenCV 2.4.3 REQUIRED)
      find_package(Eigen3 3.1.0 REQUIRED)
      find_package(Pangolin REQUIRED)
      find_package(libmongocxx REQUIRED)
      find_package(libbsoncxx REQUIRED)
      
      
      catkin_package()
      
      include_directories(
      ${PROJECT_SOURCE_DIR}
      ${PROJECT_SOURCE_DIR}/../../../
      ${PROJECT_SOURCE_DIR}/../../../include
      ${Pangolin_INCLUDE_DIRS}
      ${LIBMONGOCXX_INCLUDE_DIRS}
      ${LIBBSONCXX_INCLUDE_DIRS}
      )
      
      set(LIBS
      ${catkin_LIBRARIES}
      ${OpenCV_LIBS}
      ${EIGEN3_LIBS}
      ${Pangolin_LIBRARIES}
      ${PROJECT_SOURCE_DIR}/../../../Thirdparty/DBoW2/lib/libDBoW2.so
      ${PROJECT_SOURCE_DIR}/../../../Thirdparty/g2o/lib/libg2o.so
      ${PROJECT_SOURCE_DIR}/../../../lib/libORB_SLAM2.so
      ${LIBMONGOCXX_LIBRARY_DIRS}/libmongocxx.so
      ${LIBBSONCXX_LIBRARY_DIRS}/libbsoncxx.so
      )
      
      # Node for monocular camera
      add_executable(mono
      src/ros_mono.cc
      )
      
      target_link_libraries(mono
      ${LIBS}
      )
      
      # Node for RGB-D camera
      add_executable(rgbd
      src/ros_rgbd.cc
      )
      
      target_link_libraries(rgbd
      ${LIBS}
      )
      
      # Node for stereo camera
      add_executable(stereo
      src/ros_stereo.cc
      )
      
      target_link_libraries(stereo
      ${LIBS}
      )
      

      首先是指定cmake的版本
      然后是工程的名字
      然后是find_package. 软件一般都是有依赖关系的,如果你依赖别的软件,就可以通过find_package来载入依赖的软件的相关信息,比如软件的头文件,软件的链接库位置。find_package会在特定的目录里去找对应的软件config文件。在cmake的安装路径下里面有各种已安装的软件包的cmake文件。find_package实际上就是在找这些文件,然后执行一遍。有时自己依赖的软件包并不提供这样的文件,这时候就要自己去写。
      alt text

      上图的libbsoncxx-config.cmake就是libbsoncxx这个软件包的cmake文件。在cmake文件中的CMAKE_MODULE_PATH变量就是find_package找的路径。可以在里面添加上自定义的路径。find_package还可以添加上 REQUIRED标记,表明这个软件包是必须的。如果find_package没有找到这个软件包,那么cmake就出报出没有找到这个软件包的错误。
      Set 可以用来设置环境变量的。
      然后在cmake文件里面是有简单的判断分支结构可以用的,简单的语法就是

      If(xxxx)
      elseif(xxxx)
      endif(xxxx)
      

      需要注意的是elseif里面并不是另一种条件,这里要和if里面写的一样。表示当if的条件未被满足时应该执行的语句。如果想要实现更加复杂的判断,就需要嵌套的if语句。
      最后就是 include_directories和 target_link_libraries。这两个的意义很明确,就是设置头文件的地址和链接库的位置。还有就是生成可执行程序的命令 add_executable, 第一个变量是生成的文件名字,之后是对应的源文件。如果不想生成可执行文件,只是想生成一个链接库供别人使用,那么可以用add_library这个命令。使用方法和 add_executable基本一致。下面是一个例子

          add_library(${PROJECT_NAME} SHARED
      src/System.cc
      src/Tracking.cc
      src/LocalMapping.cc
      src/LoopClosing.cc
      src/ORBextractor.cc
      src/ORBmatcher.cc
      src/FrameDrawer.cc
      src/Converter.cc
      src/MapPoint.cc
      src/KeyFrame.cc
      src/Map.cc
      src/MapDrawer.cc
      src/Optimizer.cc
      src/PnPsolver.cc
      src/Frame.cc
      src/KeyFrameDatabase.cc
      src/Sim3Solver.cc
      src/Initializer.cc
      src/Viewer.cc
      )
      

      SHARED是这个库的类型。动态链接库还是静态链接库。
      到这里基本上简单的cmakelist文件已经可以自己写了。下面说说软件库的cmake文件怎么写。就是find_package那个命令会用到的那个文件。

      我们还是以一个例子来做说明。

          # - Find MongoDB
      #  Find the MongoDB includes and client library
      #  This module defines
      #  MongoDB_INCLUDE_DIR, where to find mongo/client/dbclient.h
      #  MongoDB_LIBRARIES, the libraries needed to use MongoDB.
      #  MongoDB_FOUND, If false, do not try to use MongoDB.
      
      if(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
         set(MongoDB_FOUND TRUE)
      
      else(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
      
        find_path(MongoDB_INCLUDE_DIR bsoncxx/builder/basic/document.hpp
            /usr/local/include/mongocxx/v_noabi
            /usr/local/include/libbson-1.0
            /usr/local/include/libmongoc-1.0
            /usr/local/include/bsoncxx/v_noabi
            )
      
      if(WIN32)
        find_library(MongoDB_LIBRARIES NAMES mongoclient
            PATHS
            $ENV{ProgramFiles}/Mongo/*/lib
            $ENV{SystemDrive}/Mongo/*/lib
            )
      else(WIN32)
        find_library(MongoDB_LIBRARIES NAMES mongocxx bsoncxx
            PATHS
            /usr/lib
                /usr/lib64
            /usr/lib/mongo
            /usr/lib64/mongo
            /usr/local/lib
            /usr/local/lib64
            /usr/local/lib/mongo
            /usr/local/lib64/mongo
            /opt/mongo/lib
            /opt/mongo/lib64
            )
      endif(WIN32)
      
        if(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
          set(MongoDB_FOUND TRUE)
          message(STATUS "Found MongoDB: ${MongoDB_INCLUDE_DIR}, ${MongoDB_LIBRARIES}")
        else(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
          set(MongoDB_FOUND FALSE)
          if (MongoDB_FIND_REQUIRED)
      		message(FATAL_ERROR "MongoDB not found.")
      	else (MongoDB_FIND_REQUIRED)
      		message(STATUS "MongoDB not found.")
      	endif (MongoDB_FIND_REQUIRED)
        endif(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
      
        mark_as_advanced(MongoDB_INCLUDE_DIR MongoDB_LIBRARIES)
      
      endif(MongoDB_INCLUDE_DIR AND MongoDB_LIBRARIES)
      

      这是一个叫做MongoDB的软件包的cmake文件。
      这个文件会通过设置MongoDB_FOUND变量来告诉cmake这个库有没有找到。这里需要注意的就是find_path这个指令。这个就是用来判断软件是否存在的关键指令。find_path的第一个参数接的是变量名字,之后是文件的名字。后面接一系列这个文件可能存在的路径。也就是软件的可能安装路径。如果在以下路径成功找到这个文件。第一个变量就会被赋值。反之如果找不到,那么这个变量就会被设成False。之后可以用if来判断不同条件下需要执行的语句。大致上就是如此。

      这里只是一些简单的介绍,如果想要更全面的更准确的了解cmake那么可以去看看cmake的官方文档。虽然我觉得那个并不是写出来给人看的。

      发布在 技术交流
      weijiz
      weijiz
    • AlphaGo对李世石目前3:1

      AlphaGo经过三连胜后,李世石显然在第四局已经找到了它的弱点。正如之前大家说的一样,AlphaGo不擅长打劫。利用这个弱点李世石成功扳回一城,而且逼得AlphaGo下出好几步臭棋。让原来寄予厚望的人们非常失望。

      发布在 行业动态
      weijiz
      weijiz
    • 分布式程序数据同步问题分析

      对于分布式程序,甚至更一般的并行式程序,数据同步都是一个很头疼的问题。首先分析一下为什么这个问题很头疼。
      对于一般的并行程序,在一个线程读取数据的时候,别的线程不能对同一个数据进行修改。否则就会导致数据不一致。所以一般的方法是加锁。在读取数据前先申请数据的锁,读取前把数据锁住,不让别人更改。读取完成后再释放这个锁。同样写入也是一样的。这样就保证了读取和写入不会同时发生。对于分布式程序,虽然原理上差不多,但是情况要复杂很多。首先是节点本身不稳定。随时都有节点加入和退出网络。可能一个节点正在操作关键数据,接着就意外掉线了。其次还有效率的问题,数据的更改最终一定会传遍整个网络。采用什么样的策略去传递更改直接影响网络的效率。如果采用独占锁的方式,那么在一个节点访问数据到时候,其他节点的资源实际上是一种浪费。如何避免这些问题呢?这都是同步算法所要考虑的。

      这里就总结一下我所看到的数据同步方法。

      1. Ceph的主节点同步法
        Ceph是一种分布式文件存储程序。这个算法就是其中的文件同步算法。Ceph的节点具有动态性。也就是说随时都有节点的加入和退出发生。所以相对于MIT的算法应用环境要更广。
        算法的主要过程如下。首先节点分为控制节点和内容节点。控制节点监控所有内容节点的状态。比如是不是掉线了,是不是出现读写错误了。并且维护一份当前内容节点的列表。列表的第一个有效内容节点作为主内容节点。如果这个节点掉线,就依次往下找。所以在同一时刻内会有唯一的一个主节点。所有的写入操作只能发生在主节点。主节点写入完成后向其他节点扩散更改。当所有更改完成后主节点通知客户端写入完成。这里可以看出来主节点的负担相对要重很多。

      2. Mit的Cpu同步法
        首先说一下这种算法的应用环境特点。这个算法是我在MIT News里面看到的。是MIT研究出的用处多核处理器各核之间数据同步的算法。所以是应用在处理器中的。这样就保证了节点的结构是稳定的,不会突然有节点掉线之类的问题。
        这个算法和Ceph的主节点法比较类似。但是主节点是动态的。每一个核相当于一个节点。每个核都有自己的数据缓存。每份数据都有一个主节点。当某个核想要更改数据的时候先要通知当前的主节点,自己想要成为主节点。主节点确认数据是最新的后,这个核就成为新的主节点可以开始更新数据了。(这个算法我不太确定和原文是不是一致,我找不到原文了)

      3. Zeronet的随机同步法
        ZeroNet是一个分布式网站程序。这个是算法就是其中的同步算法。由于作者设计的时候并不要求严格的数据一致性。所以这个算法也比较简单。每个节点都可以对数据进行更改。更改后把更改后的文件对随机的几个和自己相连的节点进行广播。同时在更改上标记上更改发生的时间。其他节点接收到这个更改的时候。把更改和自己当前的文件进行比较。如果更改比自己的文件要新,就用更改后的文件替换自己当前的文件。同时继续把更改推送到随机的几个和自己相连的节点。反之如果更改没有自己当前的文件新。就把自己的文件推送给发给自己这个更改的节点。
        这种算法很容易出现数据丢失和错误的情况。比如A节点先对文件进行了更改。在A的更改同步到所有节点之前。B节点也对文件进行了更改。这样B的更改就会把A的更改覆盖掉。导致A更改的数据丢失。但是对于网页中的评论这样的应用来说,少一两条评论也是无所谓的事情。同时由于指数式扩散和简单的原则,这个的效率应该是不错的。

      4. 我的mongomanager同步法
        这个是我用在mongodb分布式数据库中的算法。算是从上面的几种算法里面变出来的吧。网络节点也是不稳定的。有节点加入和退出网络发生。就目前使用情况来说还不错。
        基本结构由控制节点和客户端节点组成。所有的客户端节点都和控制节点相连。控制节点选取其中一个客户端节点作为主节点。主节点保存着最新的数据库数据。如果某一个客户端节点想要更改数据库,那么它就要先向控制节点申请成为主节点。控制节点把这个节点和当前主节点进行比较。如果此节点已经同步到最新数据就把当前主节点设置成这个节点。成为主节点后这个节点就可以进行数据库操作了。此时所有的数据库更改操作都会被推送到控制节点,由控制节点向其他节点进行广播。其他节点收到请求后执行相应的数据库操作。由此保证各个节点的数据同步。
        实际上目前没有完全的做到去中心化。因为控制节点是固定的。当然也可以改成控制节点也是动态的。这种算法保证读取数据一定是正确地,但不一定是最新的。就好像看网页一样。你用浏览器打开的网页可能不是现在最新的网页,但一定是曾经出现的。刷新一下才能确定获得最新的页面。

      发布在 技术交流
      weijiz
      weijiz
    • 艺术的本质

      前一段时间在看乐理方面的东西时有了些意外的发现,让我似乎明白了到底什么是艺术什么是美。
      还是从音乐说起。说到音乐那么首先就必须要有音阶。音阶的构成离不开五度相生律。假如现在我们以任意一个频率f作为1。实验发现当f和2f的声音同时发出的时候,我们实际上只能感受到频率为f的声音。这个很容易理解,周期为T和2T的两个周期函数,以随意的方式做线性叠加得到的肯定是个周期为2T的周期函数。实验发现当频率为f和1.5f的声音同时发出的时候我们会感觉听到了频率为0.5f的声音。这里f和1.5f合成的声音也让人觉得比较舒服。这个就是五度相生律。f和1.5f的声音间我们认为差了五度。利用这种关系我们就构造出了音阶(这里说的比较粗略,因为本文的重点不在于此,如果想更多的了解请搜索基础乐理知识)。

      有了音阶,就好像是有了画画的笔一样,我们就能利用音乐来表达情感了。为什么能用音乐来表达情感呢?因为音阶之间不同的音程差会让我们有不同的感觉。比如从1到5我们会感觉很舒服,但是从1到4就会感觉不舒服。这样音乐就会引起人的感情变化。
      还是根据音程的关系,可以构造出和声。和声就是不同音调的声音同时发出时所构成的声音。这样有的和声听起来很舒服,有的听起来就不舒服。现代的音乐都是建立在和声的基础上的。通过不断摸索音乐家们建立了比较完备的和声理论。音乐不仅听起来很有美感,由于其内在的数学结构,谱子本身也具有结构的美感。
      然而完备的理论就意味着可能性的减少。人们可以按照现在的理论写出很多听起来不错的曲子,但是同时又断绝了那些不符合现有理论曲子存在的可能性。由于能够写出的不同曲子越来越少,甚至有人悲观的说我们会最终用尽所有音乐。
      事情到这里就变得非常有趣了。我们从什么都没有,根据人的感觉创造出了音乐。音乐从源头上说是具有无限的可能性的,而断送这些可能性的原因在于人们创建的规则。规则的本身的目标是更方便的找到好听的音乐。音乐的本质就是好听就行了。不符合当前理论的好听的音乐肯定是存在的。所以当我们发现几乎已经穷尽了所有可能的音乐了的时候,需要改变的是音乐理论本身。我们需要拥有更大可能性的音乐理论。
      然而事情又不是那么简单。即使是同一种音乐不同人听起来感受也不相同,有的认为好听,有的就认为很难听。比如按照和声理论设计的古典乐很多人实际上并不喜欢。即使是同一个人在不同时候听同一首音乐感受也不同。比如把现在你很喜欢的一首曲子作为你的闹铃声音,过不了多久你就会彻底厌烦这首曲子。所以感觉音乐是否好听这件事情不具有客观性。

      先总结一下上面的观点我们再继续向下走。首先我们天生的对声音的不同喜好造就了现在的音乐。然而发展到后来我们的喜好反过来受到了人类自己创建的规则的限制。
      推而广之,我们就能理解艺术到底是怎么回事了。从绘画的角度说,我们天生的就认为某些颜色在一起会更加和谐。某些图形结构也会让人感觉很舒服。然后由此就发展出了很多绘画的理论,各种构图的方法。而这些理论本身又影响了我们对美的判断。
      到底什么是美呢?我看到有人认为让感官直接体验到的愉悦的感受的东西并不能成为美。美必须是从感官中抽象出的理性的一层。我表达的好像不是很清楚。举个例子来说你看到一幅画,这幅画让你感觉很美。颜色的和谐,图形的比例等等,这些是你的直接感官感受。同时这幅画本身表达着一些思想。在理解了其中的内涵之后你会感受到另一种美。有人认为前一种感受就不能成为美的感受。以前我还是比较赞同这种观点的。但是现在我却不这么认为,美就是这种直接的感受,不能因为人自己创建的规则去否定这种感受的存在。规则是为了更好的发现美,而不是根据规则去否定其存在。

      0_1457943186705_e850352ac65c10385b7eac67b0119313b07e8916.jpg
      天空之城的简谱,可以看到第一个音符和最后一个音符是一样的

      0_1457943520222_Screenshot from 2016-03-14 16:15:18.png
      0_1457943531702_Screenshot from 2016-03-14 16:17:53.png
      采用呼应方式的配色和不采用呼应方式的配色, 哪一个感觉更舒服呢?

      其实原本我想说的并不是这些,而是想说在不同的艺术领域中我所观察到的共同现象。比如音乐、文学和绘画中的结束感。当你听音乐的时候,把曲子的最后一段给认为取掉,你就会有一种音乐还没结束的感觉。对你没听过的曲子也是如此。这时人的一种天生的感觉。在作曲的理论中。比如你以Do作为第一个音符,那么最终结束的时候你也要回到这个音符,否则就会给人乐曲还没结束的感觉。在写作中以前语文老师经常说的就是首尾呼应的手法,这种写法也会给人较强的结束感。绘画我就不太了解了,但由于经常作网页,关于网页配色方面也有一些了解。现在的网页基本上最上面是导航栏,最下面是页脚。导航栏和页脚的颜色大部分都是保持一致的。同样这也是首位呼应的原则,给人一种结束感。所以这里就更体现出了对美的感觉的同行。因为感受美的对象都是人,这里体现出的是人对感官的更深层次的喜好。同样无论音乐还是文学,在进行的结构上都要求起承转结。

      文章已经行至尾处,还有很多话没有说清楚。如果在上一段出结束,这篇文章就没有结束感。但是此处我来个首位呼应感觉就不同了。什么是艺术和美呢?你所感受到的那种能让你感受到愉悦的东西,就是美的。而艺术相关的理论是为了更容易的发现和创造出这种美。

      发布在 杂谈
      weijiz
      weijiz
    • Ros环境配置

      本文的目标是在Ubuntu 14.04 的基础上搭建起ROS环境,同时把rtabmap给跑起来。

      什么是ROS

      ROS 是Robot Operating System的缩写,是专门为机器人控制开发的系统。和一般的操作系统的区别在于增加了包管理和信息控制等系统,提供了对硬件进行抽象的方法,同时也使得程序间的通信更为方便。

      ROS安装 官方文档

      系统为Ubuntu 14.04 64位。以下文档在原文档的基础上作出可更符合我们使用条件的修改。

      添加软件源

      sudo sh -c '. /etc/lsb-release && echo "deb http://ros.exbot.net/rospackage/ros/ubuntu/ $DISTRIB_CODENAME main" > /etc/apt/sources.list.d/ros-latest.list'
      

      添加公钥

      sudo apt-key adv --keyserver hkp://pool.sks-keyservers.net:80 --recv-key 0xB01FA116
      

      安装

      sudo apt-get update
      sudo apt-get install ros-jade-desktop-full
      

      初始化rosdep

      sudo rosdep init
      rosdep update
      

      环境变量配置

      这会在你的path里添加ros对应的指令

      echo "source /opt/ros/jade/setup.bash" >> ~/.bashrc
      source ~/.bashrc
      source /opt/ros/jade/setup.bash
      

      安装rosinstall

      sudo apt-get install python-rosinstall
      

      至此ROS安装完成

      发布在 技术交流
      weijiz
      weijiz
    • 1
    • 2
    • 32
    • 33
    • 34
    • 35
    • 36
    • 36 / 36