├── .dockerignore ├── .github └── ISSUE_TEMPLATE │ └── bug-report.md ├── .gitignore ├── README.md ├── doc └── development-environment.png ├── docker-compose.yml ├── docker ├── .dockerignore ├── README.md ├── cpu.Dockerfile ├── doc │ ├── 01-launch-instance.png │ ├── 02-service-health-check.png │ ├── 03-access-workspace.png │ └── 04-mount-native-workspace-into-docker.png ├── environment │ └── requirements.txt ├── image │ ├── etc │ │ ├── apt-fast.conf │ │ ├── apt │ │ │ ├── sources.list │ │ │ └── sources.list.d │ │ │ │ └── ros-latest.list │ │ ├── default │ │ │ └── keyboard │ │ ├── hosts │ │ ├── nginx │ │ │ └── sites-enabled │ │ │ │ └── default │ │ ├── pip.conf │ │ ├── resolv.conf │ │ └── supervisor │ │ │ ├── conf.d │ │ │ ├── lxde.conf │ │ │ └── webportal.conf │ │ │ └── supervisord.conf │ ├── root │ │ ├── .gtkrc-2.0 │ │ └── Desktop │ │ │ └── terminator.desktop │ ├── startup.sh │ ├── usr │ │ ├── lib │ │ │ └── webportal │ │ │ │ ├── .gitignore │ │ │ │ ├── README.md │ │ │ │ ├── app.ini │ │ │ │ ├── app.py │ │ │ │ ├── application │ │ │ │ ├── __init__.py │ │ │ │ ├── main │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── views.py │ │ │ │ ├── static │ │ │ │ │ └── tic.jpg │ │ │ │ ├── templates │ │ │ │ │ ├── aboutus.html │ │ │ │ │ ├── index.html │ │ │ │ │ └── redirect.html │ │ │ │ └── utils │ │ │ │ │ ├── __init__.py │ │ │ │ │ └── log.py │ │ │ │ ├── config.py │ │ │ │ └── requirements.txt │ │ └── share │ │ │ └── doro-lxde-wallpapers │ │ │ ├── desktop-items-0.conf │ │ │ └── theme.jpeg │ └── workspace │ │ ├── data │ │ └── nginx │ │ │ └── noVNC.log │ │ └── requirements.txt └── installers │ └── download-tini.sh ├── ubuntu-setup ├── README.md └── doc │ ├── external-disk │ ├── README.md │ └── images │ │ ├── 00-cleanup-a-installer-disk.jpg │ │ ├── 00-cleanup-b-ubuntu-disk.jpg │ │ ├── 00-cleanup-format-disks.png │ │ ├── 01-startup-disk-create--confirm.png │ │ ├── 01-startup-disk-create--existing-ubuntu.png │ │ ├── 01-startup-disk-create--select-device.png │ │ ├── 02-BIOS-boot-config.jpg │ │ ├── 02-BIOS-boot-sequence.jpg │ │ ├── 02-BIOS-enter.jpg │ │ ├── 02-BIOS-setup.jpg │ │ ├── 02-BIOS-start-installation.jpg │ │ ├── 03-install-ubuntu-a-keyboard.png │ │ ├── 03-install-ubuntu-a-language.png │ │ ├── 03-install-ubuntu-c-network.png │ │ ├── 03-install-ubuntu-d-option.png │ │ ├── 03-install-ubuntu-e-type.png │ │ ├── 03-install-ubuntu-f-create-new-partition-confirm.png │ │ ├── 03-install-ubuntu-f-create-new-partition-result.png │ │ ├── 03-install-ubuntu-f-create-new-partition.png │ │ ├── 03-install-ubuntu-g-02-boot.png │ │ ├── 03-install-ubuntu-g-03-root.png │ │ ├── 03-install-ubuntu-g-result.png │ │ ├── 03-install-ubuntu-h-confirm.png │ │ ├── 03-install-ubuntu-i-region.png │ │ ├── 03-install-ubuntu-k-config.png │ │ └── 03-install-ubuntu-l-finish.png │ └── ubuntu-windows │ └── Ubuntu双系统.pdf └── workspace ├── .gitignore ├── README.md ├── assignments ├── .gitignore ├── 01-introduction │ ├── .gitignore │ ├── README.md │ ├── doc │ │ ├── demo.png │ │ └── terminator.png │ └── src │ │ ├── CMakeLists.txt │ │ └── lidar_localization │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── cmake │ │ ├── PCL.cmake │ │ ├── geographic.cmake │ │ ├── global_defination.cmake │ │ └── glog.cmake │ │ ├── include │ │ └── lidar_localization │ │ │ ├── global_defination │ │ │ └── global_defination.h.in │ │ │ ├── publisher │ │ │ ├── cloud_publisher.hpp │ │ │ ├── odometry_publisher.hpp │ │ │ └── tf_broadcaster.hpp │ │ │ ├── sensor_data │ │ │ ├── cloud_data.hpp │ │ │ ├── gnss_data.hpp │ │ │ └── imu_data.hpp │ │ │ └── subscriber │ │ │ ├── cloud_subscriber.hpp │ │ │ ├── gnss_subscriber.hpp │ │ │ ├── imu_subscriber.hpp │ │ │ └── tf_listener.hpp │ │ ├── launch │ │ └── hello_kitti.launch │ │ ├── package.xml │ │ ├── rviz │ │ └── hello_kitti.rviz │ │ ├── slam_data │ │ └── .gitignore │ │ └── src │ │ ├── hello_kitti_node.cpp │ │ ├── publisher │ │ ├── cloud_publisher.cpp │ │ ├── odometry_publisher.cpp │ │ └── tf_broadcaster.cpp │ │ ├── sensor_data │ │ ├── gnss_data.cpp │ │ └── imu_data.cpp │ │ └── subscriber │ │ ├── cloud_subscriber.cpp │ │ ├── gnss_subscriber.cpp │ │ ├── imu_subscriber.cpp │ │ └── tf_lisener.cpp └── README.md └── data └── kitti ├── .gitignore └── README.md /.dockerignore: -------------------------------------------------------------------------------- 1 | doc 2 | ubuntu-setup 3 | workspace -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Create a report to help the framework improve 4 | title: "[BUG]-[WEEK]-[CONCISE_DESCRIPTION]" 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Please provide the info below to ensure the bug can be reproduced: 15 | * **Week / Assignment Name** 16 | * **Relative Path to File** 17 | * **Line Number** 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. 21 | 22 | **Screenshots** 23 | If applicable, add screenshots to help explain your problem. 24 | 25 | **Additional context** 26 | Add any other context about the problem here. 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Multi-Sensor Fusion for Localization & Mapping -- 多传感器融合定位与建图 2 | 3 | 深蓝学院[多传感器融合定位与建图/Multi-Sensor Fusion for Localization & Mapping](https://www.shenlanxueyuan.com/course/324)学习环境. 4 | 5 | Maintained by **Ge Yao**, alexgecontrol@qq.com 6 | 7 | --- 8 | 9 | ## 先修课程与准备知识检查 10 | 11 | 我在学习这门课程时,已经完成如下深蓝学院课程的学习: 12 | 13 | * [机器人学中的状态估计](https://www.shenlanxueyuan.com/course/421) 14 | * [视觉SLAM理论与实践](https://www.shenlanxueyuan.com/course/433) 15 | * [视觉SLAM进阶-从零开始手写VIO](https://www.shenlanxueyuan.com/course/388) 16 | * [激光SLAM理论与实践](https://www.shenlanxueyuan.com/course/348) 17 | 18 | 且有多年的机器人系统开发经验, 熟悉以下的基础理论, 开发语言/框架/工具: 19 | 20 | * **State Estimation for Robotics** [Reference Book](https://www.amazon.com/State-Estimation-Robotics-Timothy-Barfoot/dp/1107159393/ref=sr_1_1?crid=3A1AU9FS3OA4U&keywords=state+estimation+for+robotics&qid=1639835747&sprefix=state+estimation+for+robotic%2Caps%2C501&sr=8-1) 21 | * **Modern C++ (11 and above)** [Reference Book](https://www.amazon.com/Effective-Modern-Specific-Ways-Improve/dp/1491903996/ref=sr_1_1?crid=3FBSOVE5S7DG2&keywords=effective+modern+c%2B%2B&qid=1639809190&sprefix=effective+modern+c%2B%2Caps%2C573&sr=8-1) 22 | * Python [Reference Book](https://www.amazon.com/Fluent-Python-Concise-Effective-Programming/dp/1491946008/ref=sr_1_2?crid=1N4TWSFVKTSUC&keywords=fluent+python+2nd+edition&qid=1639911762&sprefix=fluent+python%27%2Caps%2C332&sr=8-2) 23 | * **ROS** [深蓝学院参考课程](https://www.shenlanxueyuan.com/course/364) 24 | * **Git/GitHub, Markdown**与LaTeX [Coursera参考课程](https://www.coursera.org/professional-certificates/google-it-automation#courses) 25 | 26 | --- 27 | 28 | ## Before You Start... 29 | 30 | 在开始前, 请自行通过百度, 或者我推荐的[Coursera参考课程](https://www.coursera.org/professional-certificates/google-it-automation#courses), 自行学习, 熟悉以下工具的基本概念与操作. **否则你可能连这篇文档都读得稀里糊涂** 31 | 32 | 1. git 33 | 2. GitHub 34 | 3. MarkDown语法与README.md的书写 35 | 4. VSCode使用 36 | 37 | 当且仅当你完成上述基本工具的学习后,再继续阅读,**否则你可能连这篇文档都读得稀里糊涂** 38 | 39 | --- 40 | 41 | ## Docker Env - Up & Running 42 | 43 | ### WARNING - About Environment 44 | 45 | **若您坚持在Native Ubuntu上进行开发**, 此处**将默认您有足够的定位&建图开发环境运维经验, 能够自定义开发环境, 并且自主解决由于环境依赖冲突导致的各种问题**. 课程的重点在多传感融合定位算法, 并非基于Docker的环境搭建. 如果感兴趣, 请根据以下提示, 自行学习.**本框架只确保Docker环境的开箱即用, 不提供任何本地环境配置冲突解决的帮助**. 46 | 47 | * 确保熟悉Docker与Docker-Compose的开发使用 48 | * 根据Dockerfile [Click Here](docker/cpu.Dockerfile)自行准备开发环境 49 | * 熟悉其中的各个依赖库, 有能力在出现依赖问题时, 自行搜索, 查询相关资料, 修复依赖冲突 50 | 51 | ### WARNING - On This Guide 52 | 53 | **请您务必按照本指南, 一步一步操作, 当且仅当您在对本环境足够熟悉的情况下,再自由发挥** 54 | 55 | ### Overview 56 | 57 | 本Repo为基于**ROS melodic** @ **Ubuntu 18.04**的[多传感器融合定位与建图/Multi-Sensor Fusion for Localization & Mapping](https://www.shenlanxueyuan.com/course/324)学习环境. 58 | 59 | 定位与建图是一个复杂的工程. **每一个解决方案, 都有较为复杂的环境依赖**. 然而: 60 | 61 | * 部分依赖项由于网络原因(Great Fire Wall & Server IP Block)难以直接获得 62 | 63 | * 由于课程依赖项的版本, 与本地现有依赖项的版本, 可能有所不同, 直接冒然安装, 可能会导致本地开发环境被破坏 64 | 65 | 故: 本课程的学习环境将以**Docker Image**的形式提供, 以实现与Native PC环境的隔离. 66 | 67 | * 本项目Native PC的操作系统选择**Ubuntu**. Windows与Mac不推荐使用, 若有意尝试, 请自行搜索相关解决方案. 68 | 69 | --- 70 | 71 | ### 安装Ubuntu 72 | 73 | 首先请确保您可以访问**Ubuntu**开发环境. 如果没有**Ubuntu**环境, 请按照[点击链接进入](ubuntu-setup/README.md)指南, 在本地PC上安装配置**Ubuntu**环境. 74 | 75 | --- 76 | 77 | ### **针对国内同学** 将Ubuntu APT源换为阿里云源 78 | 79 | 为了保证本地Native环境APT安装速度, 请根据[This CSDN Post](https://blog.csdn.net/zhangjiahao14/article/details/80554616), 将Ubuntu上默认的APT源切换为阿里云源. 80 | 81 | --- 82 | 83 | ### Fetch This Git Repo. 84 | 85 | **感谢第5期同学的分享** 如果在国内, 因DNS污染等原因, 导致GitHub访问受限, 可以通过[GitHub Proxy代理](https://ghproxy.com/)进行加速 86 | 87 | ```bash 88 | # 1. direct clone: 89 | git clone https://github.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware 90 | # 2. use GitHub proxy for acceleration: 91 | git clone https://ghproxy.com/https://github.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware 92 | ``` 93 | 94 | --- 95 | 96 | ### 获取Docker开发环境 97 | 98 | 本课程推荐使用配套的Docker环境[点击链接进入](docker/README.md)完成课程学习. Docker提供了一个轻量级的标准化开发环境, 能够避免本地已有环境的差异导致的奇怪问题, 避免环境配置调试的巨额时间浪费. 99 | 100 | --- 101 | 102 | ### JFYI: Dependency Overview 103 | 104 | * **C++** 105 | * **Google Protobuf**, [Click Here](https://github.com/google/protobuf.git), **branch 3.14.x** 106 | * **GeographicLib**, [Click Here](https://nchc.dl.sourceforge.net/project/geographiclib/distrib/GeographicLib-1.50.1.zip), **version 1.50.1** 107 | * **GeographicLib**, [Click Here](https://nchc.dl.sourceforge.net/project/geographiclib/distrib/GeographicLib-1.50.1.zip), **version 1.50.1** 108 | * **Sophus**, [Click Here](https://github.com/strasdat/Sophus.git), **commit id 49a7e1286910019f74fb4f0bb3e213c909f8e1b7** 109 | * **Google Ceres**, [Click Here](https://github.com/ceres-solver/ceres-solver.git), **commit id c2fab6502e5a341ff644c2bb2c5171ebd882b2d6** 110 | * **G2O**, [Click Here](https://github.com/RainerKuemmerle/g2o.git), **tag 20200410_git** 111 | * **GTSAM**, [Click Here](https://github.com/borglab/gtsam.git), **tag 4.0.3** 112 | 113 | * **Python** 114 | * **kitti2bag**, [Click Here](https://pypi.org/project/kitti2bag/), **1.5** 115 | * **evo**, [Click Here](https://pypi.org/project/evo/), **1.12.0** 116 | --- 117 | 118 | ### Workspace 119 | 120 | 当Native PC与Course Docker Environment均准备就绪时, 即可开始使用本开发环境: 121 | 122 | * **第一次使用时, 请首先下载课程配套的KITTI测试数据**[here](workspace/data/kitti/README.md). 123 | 124 | * 之后, 即可通过**本地VSCode开发, Docker内部编译测试**的模式, 完成课程作业. 125 | 126 | #### 获取课程数据 127 | 128 | 在第一次使用时, 需要将**课程配套的修复后KITTI数据**下载至本地文件系统. 具体操作方法参考[点击链接进入](workspace/data/kitti/README.md) 129 | 130 | #### 安装Native Ubuntu IDE 131 | 132 | 本课程推荐使用[VSCode](https://code.visualstudio.com/)进行开发. 请按照链接,完成VSCode的安装. **安装VSCode之后,请继续安装以下VSCode Plug-Ins**: 133 | 134 | * **C/C++** by **Microsoft**, 用于**完成作业时加速C++开发**. 135 | 136 | * **Markdown All in One** by **Yu Zhang**, 用于**在VSCode中查看课程中所有的README.md, (Shift+Ctrl+V)**. 137 | 138 | #### 开发, 编译与测试 139 | 140 | 启动Docker环境后, **Docker**中的/workspace目录, 会被映射到**当前Repo**中的workspace目录. 141 | 142 | 使用该Workspace进行开发, 编译与测试的方法如下: 143 | 144 | * 在**当前Repo的workspace**下, 启动[VSCode](https://code.visualstudio.com/), 编辑源代码: 145 | 146 | Development Environment, Native VS Code in Mounting Point 147 | 148 | * 在**Docker /workspace**下, 进行编译. 具体的编译方法, 请参考[作业1 环境搭建](workspace/assignments/01-introduction/README.md) 149 | 150 | --- 151 | 152 | ### Assignments 153 | 154 | 请各位执行如下的分支切换指令, 完成各周对应的作业. 155 | 156 | #### Week 02, Lidar Odometry, Basic 157 | 158 | ```bash 159 | git checkout 02-lidar-odometry-basic 160 | ``` 161 | 162 | #### Week 03, Lidar Odometry, Advanced 163 | 164 | ```bash 165 | git checkout 03-lidar-odometry-advanced 166 | ``` 167 | 168 | #### Week 04, Mapping and Matching 169 | 170 | ```bash 171 | git checkout 04-mapping-and-matching 172 | ``` 173 | 174 | #### Week 05, IMU Calibration 175 | 176 | ```bash 177 | git checkout 05-imu-calib 178 | ``` 179 | 180 | #### Week 06, IMU Navigation 181 | 182 | ```bash 183 | git checkout 06-imu-navigation 184 | ``` 185 | 186 | #### Week 07, Filtering, Basic 187 | 188 | ```bash 189 | git checkout 07-filtering-basic 190 | ``` 191 | 192 | #### Week 08, Filtering Advanced 193 | 194 | ```bash 195 | git checkout 08-filtering-advanced 196 | ``` 197 | 198 | #### Week 09, Graph Optimization 199 | 200 | ```bash 201 | git checkout 09-graph-optimization 202 | ``` 203 | 204 | #### Week 10, Sliding Window 205 | 206 | ```bash 207 | git checkout 10-sliding-window 208 | ``` 209 | 210 | #### Week 11, Capstone - Do It Own Your Own! 211 | 212 | --- 213 | 214 | Keep Learning & Keep Coding 215 | 216 | Ge Yao, alexgecontrol@qq.com -------------------------------------------------------------------------------- /doc/development-environment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/doc/development-environment.png -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.4' 2 | services: 3 | # cpu development: 4 | workspace-bionic-cpu-vnc: 5 | build: 6 | context: docker 7 | dockerfile: cpu.Dockerfile 8 | network: host 9 | image: registry.cn-shanghai.aliyuncs.com/shenlanxueyuan/sensor-fusion-workspace:bionic-cpu-vnc 10 | container_name: sensor-fusion-workspace-cpu 11 | privileged: true 12 | environment: 13 | # set VNC login password here: 14 | - VNC_PASSWORD=sensorfusion 15 | volumes: 16 | # mount your workspace here: 17 | - $PWD/workspace:/workspace 18 | ports: 19 | # HTML5 VNC: 20 | - 40080:80 21 | # standard VNC client: 22 | - 45901:5901 23 | # supervisord admin: 24 | - 49001:9001 25 | # ROS master: 26 | - 11311:11311 -------------------------------------------------------------------------------- /docker/.dockerignore: -------------------------------------------------------------------------------- 1 | doc -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # Docker Environment for Sensor Fusion 2 | 3 | 基于Docker的[多传感器融合定位/Sensor Fusion](https://www.shenlanxueyuan.com/my/course/261)学习环境. 4 | 5 | --- 6 | 7 | ## Overview 8 | 9 | 本文档旨在提供**多传感器融合定位**的标准开发环境, 减轻环境配置的工作量 10 | 11 | --- 12 | 13 | ## 安装配置Docker以及Docker-Compose 14 | 15 | 在开始使用前,首先需要在本地配置`Docker`以及`Docker-Compose`环境. 16 | 17 | --- 18 | 19 | ### 安装Docker 20 | 21 | 请参考[Docker官方文档](https://docs.docker.com/engine/install/ubuntu/)完成`Docker`环境的安装 22 | 23 | **安装完成后, 请务必进行如下操作**, 以保证可以无脑跟随后续文档进行操作: 24 | 25 | #### 将当前用户加入Docker Group 26 | 27 | 为了能在非`sudo`模式下使用`Docker`, 需要将当前用户加入`Docker Group`. 28 | 29 | 1. 执行命令: 30 | 31 | ```bash 32 | sudo usermod -aG docker $USER 33 | ``` 34 | 35 | 2. **为了使上述变更生效,请先Logout,再Login** 36 | 37 | --- 38 | 39 | ### 安装Docker-Compose 40 | 41 | `Docker-Compose`是基于Docker解决方案的Orchestrator. 42 | 43 | 请参考[Docker Compose官方文档](https://docs.docker.com/compose/install/)完成`Docker-Compose`环境的安装 44 | 45 | --- 46 | 47 | ## 获取镜像 48 | 49 | 在安装完成`Docker`以及`Docker-Compose`之后,需要从`阿里云`源上获得所需镜像. 50 | 51 | **注意**: 执行第1条命令时,**需要输入密码!!!需要输入密码!!!需要输入密码!!!**, 密码请看**命令上方注释行的绿字!!!命令上方注释行的绿字!!!命令上方注释行的绿字!!!*** 52 | 53 | ```bash 54 | # 1. login to Alibaba Cloud Docker registry -- default password is shenlansf20210122: 55 | docker login --username=937570601@qq.com registry.cn-shanghai.aliyuncs.com 56 | # 2. then download images: 57 | docker pull registry.cn-shanghai.aliyuncs.com/shenlanxueyuan/sensor-fusion-workspace:bionic-cpu-vnc 58 | ``` 59 | 60 | --- 61 | 62 | ### 启动实例 63 | 64 | 在当前Repo`根目录`下(即**docker-compose.yml**所在的那个文件夹), 启动Terminal, 执行命令, 启动Docker Workspace: 65 | 66 | ```bash 67 | docker-compose down && docker-compose up 68 | ``` 69 | 70 | --- 71 | 72 | ### Service Health Check 73 | 74 | 然后打开`Chrome`浏览器, 访问URL`http://localhost:49001/`, 默认账号/密码为`sensorfusion/sensorfusion`, 确保所有服务成功启动. 75 | 76 | 若**所有服务成功启动**, 系统状态如下图所示: 77 | 78 | Service Health Check 79 | 80 | --- 81 | 82 | ### 访问工作空间 83 | 84 | 接着在`Chrome`浏览器中, 访问URL`http://localhost:40080/`, 默认登录密码为`sensorfusion`, 访问Docker Workspace 85 | 86 | Access Workspace 87 | 88 | 该Workspace可理解为一个在浏览器中的`Ubuntu 18.04 Bionic`环境. 可在其中进行一切Ubuntu环境下的开发操作. 89 | 90 | --- 91 | 92 | ### 编译作业 93 | 94 | 请将作业所需的`源代码`与`数据`, 分别放到当前Repo`workspace/assignments`与`workspace/data`目录下. Docker Workspace会将当前Repo`workspace`文件夹映射到Docker Instance`/workspace`目录下. 95 | 96 | 可在Docker Workspace中执行如下命令, 确保两者--`当前Repo workspace文件夹`与`Docker Instance /workspace`文件夹--的一致性 97 | 98 | Mount Native Workspace into Docker 99 | 100 | --- 101 | 102 | ### 常见问题 103 | 104 | 1. Docker运行时默认用户为`root`, 运行过程中可能导致`当前Repo workspace文件夹`的User以及Group变更为`root`, 从而使本地文件IO操作因`Permission Denied`失败. 解决方案: 使用chown命令, 变更User-Group: 105 | 106 | ```bash 107 | sudo chown [CURRENT_USER]:[CURRENT GROUP] workspace 108 | ``` 109 | -------------------------------------------------------------------------------- /docker/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:18.04 2 | 3 | # ------ powered by Ge Yao, alexgecontrol@qq.com ------ 4 | 5 | LABEL maintainer="alexgecontrol@qq.com" 6 | 7 | # ------ USER ROOT HAS BEEN ACTIVATED ------ 8 | 9 | # use root for dependency installation: 10 | USER root 11 | 12 | # ------ PART 0: set environment variables ------ 13 | 14 | # set up environment: 15 | ENV DEBIAN_FRONTEND noninteractive 16 | ENV LANG=C.UTF-8 LC_ALL=C.UTF-8 17 | ENV HOME=/root SHELL=/bin/bash 18 | 19 | # ------ PART 1: set up CN sources ------ 20 | 21 | # Ubuntu: 22 | COPY ${PWD}/image/etc/apt/sources.list /etc/apt/sources.list 23 | RUN rm -f /etc/apt/sources.list.d/* 24 | 25 | # Python: 26 | COPY ${PWD}/image/etc/pip.conf /root/.pip/pip.conf 27 | 28 | # ------ PART 2: set up apt-fast -- NEED PROXY DUE TO UNSTABLE CN CONNECTION ------ 29 | 30 | # install: 31 | RUN apt-get update -q --fix-missing && \ 32 | apt-get install -y --no-install-recommends --allow-unauthenticated \ 33 | # PPA utilities: 34 | software-properties-common \ 35 | # certificates management: 36 | dirmngr gnupg2 \ 37 | # download utilities: 38 | axel aria2 && \ 39 | apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-keys 1EE2FF37CA8DA16B && \ 40 | add-apt-repository ppa:apt-fast/stable && \ 41 | apt-get update -q --fix-missing && \ 42 | apt-get install -y --no-install-recommends --allow-unauthenticated apt-fast && \ 43 | rm -rf /var/lib/apt/lists/* 44 | 45 | # CN config: 46 | COPY ${PWD}/image/etc/apt-fast.conf /etc/apt-fast.conf 47 | 48 | # ------ PART 3: add external repositories ------ 49 | 50 | # ROS: 51 | RUN apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654 52 | COPY ${PWD}/image/etc/apt/sources.list.d/ /etc/apt/sources.list.d/ 53 | # libsparse: 54 | RUN add-apt-repository -r ppa:bzindovic/suitesparse-bugfix-1319687 55 | 56 | # ------ PART 4: install packages ------ 57 | 58 | RUN apt-fast update --fix-missing && \ 59 | apt-fast install -y --no-install-recommends --allow-unauthenticated \ 60 | # package utils: 61 | sudo dpkg pkg-config apt-utils \ 62 | # security: 63 | openssh-server pwgen ca-certificates \ 64 | # network utils: 65 | curl wget iputils-ping net-tools \ 66 | # command line: 67 | vim grep sed patch \ 68 | # io: 69 | pv zip unzip bzip2 \ 70 | # version control: 71 | git mercurial subversion \ 72 | # daemon & services: 73 | supervisor nginx \ 74 | # dev. tools: 75 | terminator \ 76 | firefox \ 77 | # potential image & rich text IO: 78 | libsdl1.2-dev libsdl-net1.2-dev libsdl-image1.2-dev \ 79 | lxde \ 80 | gnome-themes-standard \ 81 | xvfb dbus-x11 x11-utils libxext6 libsm6 x11vnc \ 82 | gtk2-engines-pixbuf gtk2-engines-murrine pinta ttf-ubuntu-font-family \ 83 | mesa-utils libgl1-mesa-dri libxrender1 \ 84 | gnuplot \ 85 | texlive-latex-extra \ 86 | # 87 | # general development: 88 | # 89 | # a. c++: 90 | gcc g++ \ 91 | make cmake build-essential autoconf automake libtool \ 92 | libglib2.0-dev libboost-dev libboost-all-dev \ 93 | libomp-dev libtbb-dev \ 94 | libgoogle-glog-dev \ 95 | # b. Python 2: 96 | python-pip python-dev python-tk \ 97 | # c. lua: 98 | lua5.3 liblua5.3-dev libluabind-dev \ 99 | # 100 | # numerical optimization: 101 | # 102 | coinor-libcoinutils-dev \ 103 | coinor-libcbc-dev \ 104 | libeigen3-dev \ 105 | gfortran \ 106 | libopenblas-dev liblapack-dev \ 107 | libdw-dev libatlas-base-dev libsuitesparse-dev \ 108 | libcholmod3 libcxsparse3 \ 109 | libmetis-dev \ 110 | # 111 | # 3D graphics: 112 | # 113 | freeglut3-dev \ 114 | libqt4-dev libqt4-opengl-dev \ 115 | qt5-default qt5-qmake \ 116 | qtdeclarative5-dev libqglviewer-dev-qt5 \ 117 | # 118 | # ROS melodic: 119 | # 120 | ros-melodic-desktop-full \ 121 | ros-melodic-ecl-threads \ 122 | ros-melodic-rosbridge-server \ 123 | ros-melodic-tf2 ros-melodic-tf2-ros ros-melodic-tf2-sensor-msgs \ 124 | ros-melodic-teleop-twist-keyboard \ 125 | ros-melodic-rviz-visual-tools \ 126 | ros-melodic-plotjuggler \ 127 | python-catkin-tools python-rosdep python-rosinstall python-rosinstall-generator python-wstool \ 128 | ninja-build \ 129 | # imu: 130 | ros-melodic-imu-complementary-filter ros-melodic-imu-filter-madgwick ros-melodic-rviz-imu-plugin \ 131 | # lidar: 132 | ros-melodic-laser-pipeline \ 133 | ros-melodic-perception-pcl && \ 134 | apt-fast autoclean && \ 135 | apt-fast autoremove && \ 136 | rm -rf /var/lib/apt/lists/* 137 | 138 | # ordered startup fix for supervisord: 139 | RUN pip install ordered-startup-supervisord 140 | 141 | # ------ PART 5: set up ROS environments ------ 142 | 143 | # initialize rosdep 144 | # 145 | # NOTE: 146 | # be careful about DNS resolution problem caused by https://raw.githubusercontent.com 147 | # get the latest IP address of the site from Baidu and Google search engine 148 | # 149 | RUN rosdep fix-permissions && \ 150 | rosdep init && \ 151 | rosdep update 152 | 153 | # activate ros environment: 154 | RUN echo "source /opt/ros/melodic/setup.bash" >> ~/.bashrc 155 | 156 | # for remote debugging: 157 | EXPOSE 11311 158 | 159 | # ------ PART 6: set up VNC servers ------ 160 | 161 | COPY image / 162 | 163 | WORKDIR /usr/lib/ 164 | 165 | RUN git clone https://github.com/novnc/noVNC.git -o noVNC 166 | 167 | WORKDIR /usr/lib/noVNC/utils 168 | 169 | RUN git clone https://github.com/novnc/websockify.git -o websockify 170 | 171 | WORKDIR /usr/lib/webportal 172 | 173 | RUN pip install --upgrade pip && pip install -r requirements.txt 174 | 175 | EXPOSE 80 5901 9001 176 | 177 | 178 | # ------ PART 7: library dependencies ------ 179 | 180 | # load installers: 181 | COPY ${PWD}/installers /tmp/installers 182 | WORKDIR /tmp/installers 183 | 184 | # install Google Protobuf -- 3.14.x: 185 | RUN git clone https://github.com/google/protobuf.git -b 3.14.x -o protobuf && cd protobuf && \ 186 | # sync: 187 | git submodule update --init --recursive && \ 188 | # config: 189 | ./autogen.sh && ./configure && \ 190 | # build: 191 | make -j8 && \ 192 | # install: 193 | make install 194 | 195 | # install Aceinna GNSS/IMU sim IMU-GNSS-Odo simulation with customized error modes: 196 | RUN git clone https://github.com/AlexGeControl/GNSS-INS-SIM-Extended.git && cd GNSS-INS-SIM-Extended && \ 197 | # install: 198 | python setup.py install 199 | 200 | # install GeographicLib -- 1.50.1 201 | RUN wget https://nchc.dl.sourceforge.net/project/geographiclib/distrib/GeographicLib-1.50.1.zip && \ 202 | unzip -q GeographicLib-1.50.1.zip && cd GeographicLib-1.50.1 && \ 203 | mkdir build && cd build && \ 204 | # config: 205 | cmake .. && \ 206 | # build: 207 | make -j8 && \ 208 | # install: 209 | make install 210 | 211 | # install sophus -- commit id 49a7e1286910019f74fb4f0bb3e213c909f8e1b7: 212 | RUN git clone https://github.com/strasdat/Sophus.git -o Sophus && cd Sophus && \ 213 | # align version: 214 | git fetch --all --tags && git checkout 49a7e1286910019f74fb4f0bb3e213c909f8e1b7 && \ 215 | # start to build 216 | mkdir build && cd build && \ 217 | # config: 218 | cmake .. && \ 219 | # build: 220 | make -j8 && \ 221 | # install: 222 | make install 223 | 224 | # install ceres -- commit id c2fab6502e5a341ff644c2bb2c5171ebd882b2d6: 225 | RUN git clone https://github.com/ceres-solver/ceres-solver.git -o ceres-solver && cd ceres-solver && \ 226 | # align version: 227 | git fetch --all --tags && git checkout c2fab6502e5a341ff644c2bb2c5171ebd882b2d6 && cd /tmp/installers/ && \ 228 | # config: 229 | mkdir ceres-bin && cd ceres-bin && cmake ../ceres-solver && \ 230 | # build: 231 | make -j8 && \ 232 | # install: 233 | make install 234 | 235 | # install g2o -- release 20200410_git: 236 | RUN git clone https://github.com/RainerKuemmerle/g2o.git -o g2o && cd g2o && \ 237 | # align version: 238 | git fetch --all --tags && git checkout tags/20200410_git -b release-20200410 && \ 239 | # start to build: 240 | mkdir build && cd build && \ 241 | # config: 242 | cmake .. && \ 243 | # build: 244 | make -j8 && \ 245 | # install: 246 | make install 247 | 248 | # install gtsam -- 4.0.3: 249 | RUN git clone https://github.com/borglab/gtsam.git -o gtsam && cd gtsam && \ 250 | # align version: 251 | git fetch --all --tags && git checkout tags/4.0.3 -b release-4.0.3 && \ 252 | # start to build: 253 | mkdir build && cd build && \ 254 | # config: 255 | cmake .. && \ 256 | # build: 257 | make -j8 && \ 258 | # install: 259 | make install 260 | 261 | # install tini: 262 | RUN chmod u+x ./download-tini.sh && ./download-tini.sh && dpkg -i tini.deb && \ 263 | apt-get clean 264 | 265 | RUN rm -rf /tmp/installers 266 | 267 | # ------ PART 8: Python dependencies ------ 268 | 269 | COPY environment /workspace 270 | 271 | WORKDIR /workspace 272 | 273 | RUN pip install -r requirements.txt 274 | 275 | # ------------------ DONE ----------------------- 276 | 277 | # enable dependency lib linking: 278 | ENV LD_LIBRARY_PATH=/usr/local/lib 279 | 280 | ENTRYPOINT ["/startup.sh"] -------------------------------------------------------------------------------- /docker/doc/01-launch-instance.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/doc/01-launch-instance.png -------------------------------------------------------------------------------- /docker/doc/02-service-health-check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/doc/02-service-health-check.png -------------------------------------------------------------------------------- /docker/doc/03-access-workspace.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/doc/03-access-workspace.png -------------------------------------------------------------------------------- /docker/doc/04-mount-native-workspace-into-docker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/doc/04-mount-native-workspace-into-docker.png -------------------------------------------------------------------------------- /docker/environment/requirements.txt: -------------------------------------------------------------------------------- 1 | kitti2bag==1.5 2 | evo==1.12.0 -------------------------------------------------------------------------------- /docker/image/etc/apt-fast.conf: -------------------------------------------------------------------------------- 1 | ################################################################### 2 | # CONFIGURATION OPTIONS 3 | ################################################################### 4 | # Every item has a default value besides MIRRORS (which is unset). 5 | 6 | # Use aptitude, apt-get, or apt? 7 | # Note that apt-get is used as a fallback for outputting the 8 | # package URI list for e.g. aptitude, which can't do this 9 | # Optionally add the FULLPATH to apt-get or apt-rpm or aptitude 10 | # e.g. /usr/bin/aptitude 11 | # 12 | # Default: apt-get 13 | # 14 | _APTMGR=apt-get 15 | 16 | 17 | # Enable DOWNLOADBEFORE to suppress apt-fast confirmation dialog and download 18 | # packages directly. 19 | # 20 | # Default: dialog enabled 21 | # 22 | DOWNLOADBEFORE=true 23 | 24 | 25 | # Choose mirror list to speed up downloads from same archive. To select some 26 | # mirrors take a look at your distribution's archive mirror lists. 27 | # Debian: http://www.debian.org/mirror/list 28 | # Ubuntu: https://launchpad.net/ubuntu/+archivemirrors 29 | # 30 | # It is required to add mirrors in the sources.list to this array as well, so 31 | # apt-fast can destinguish between different distributions. 32 | # 33 | # Examples: 34 | # 35 | # Different distributions (as in operating systems): 36 | # 37 | # sources.list: 38 | # deb http://deb.debian.org/debian/ unstable main non-free contrib 39 | # deb http://de.archive.ubuntu.com/ubuntu/ bionic main universe 40 | # 41 | # apt-fast.conf: 42 | # MIRRORS=( 'http://deb.debian.org/debian','http://ftp.debian.org/debian,http://ftp2.de.debian.org/debian,http://ftp.de.debian.org/debian,ftp://ftp.uni-kl.de/debian' 43 | # 'http://archive.ubuntu.com/ubuntu,http://de.archive.ubuntu.com/ubuntu,http://ftp.halifax.rwth-aachen.de/ubuntu,http://ftp.uni-kl.de/pub/linux/ubuntu,http://mirror.informatik.uni-mannheim.de/pub/linux/distributions/ubuntu/' ) 44 | # 45 | # 46 | # Single distribution: 47 | # 48 | # sources.list: 49 | # deb http://fr.archive.ubuntu.com/ubuntu/ bionic main 50 | # deb http://fr.archive.ubuntu.com/ubuntu/ artful main 51 | # 52 | # apt-fast.conf: 53 | # MIRRORS=( 'http://fr.archive.ubuntu.com/ubuntu,http://bouyguestelecom.ubuntu.lafibre.info/ubuntu,http://mirror.ovh.net/ubuntu,http://ubuntu-archive.mirrors.proxad.net/ubuntu' ) 54 | # 55 | # Default: disabled 56 | # 57 | 58 | # 59 | # line 1. general ubuntu packages -- aliyun, stju, tsinghua 60 | # line 2. ROS packages -- ustc, tsinghua, bfsu 61 | # 62 | MIRRORS=( 63 | 'http://mirrors.aliyun.com/ubuntu,http://ftp.sjtu.edu.cn/ubuntu,http://mirrors.tuna.tsinghua.edu.cn/ubuntu' 64 | 'http://mirrors.ustc.edu.cn/ros/ubuntu/,http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/,http://mirrors.bfsu.edu.cn/ros/ubuntu/' 65 | ) 66 | 67 | 68 | # Maximum number of connections 69 | # You can use this value in _DOWNLOADER command. Escape with ${}: ${_MAXNUM} 70 | # 71 | # Default: 5 72 | # 73 | _MAXNUM=8 74 | 75 | 76 | # Maximum number of connections per server 77 | # Default: 10 78 | # 79 | _MAXCONPERSRV=10 80 | 81 | 82 | # Download file using given number of connections 83 | # If more than N URIs are given, first N URIs are used and remaining URIs are used for backup. 84 | # If less than N URIs are given, those URIs are used more than once so that N connections total are made simultaneously. 85 | # 86 | _SPLITCON=8 87 | 88 | 89 | # Split size i.e. size of each piece 90 | # Possible Values: 1M-1024M 91 | # 92 | _MINSPLITSZ=1M 93 | 94 | 95 | # Piece selection algorithm to use 96 | # Available values are: default, inorder, geom 97 | # default: selects piece so that it reduces the number of establishing connection, reasonable for most cases 98 | # inorder: selects pieces in sequential order starting from first piece 99 | # geom: selects piece which has minimum index like inorder, but it exponentially increasingly keeps space from previously selected pieces 100 | # 101 | _PIECEALGO=default 102 | 103 | 104 | # Downloadmanager listfile 105 | # You can use this value in _DOWNLOADER command. Escape with ${}: ${DLLIST} 106 | # 107 | # Default: /tmp/apt-fast.list 108 | # 109 | DLLIST='/tmp/apt-fast.list' 110 | 111 | 112 | # Download command to use. Temporary download list is designed for aria2. But 113 | # you can choose another download command or download manager. It has to 114 | # support following input file syntax (\t is tab character): 115 | # 116 | # # Comment 117 | # MIRROR1\tMIRROR2\tMIRROR3... 118 | # out=FILENAME1 119 | # MIRROR1\tMIRROR2\tMIRROR3... 120 | # out=FILENAME2 121 | # ... 122 | # 123 | # Examples: 124 | # aria2c with a proxy (set username, proxy, ip and password!) 125 | # _DOWNLOADER='aria2c --no-conf -c -j ${_MAXNUM} -x ${_MAXCONPERSRV} -s ${_SPLITCON} --min-split-size=${_MINSPLITSZ} --stream-piece-selector=${_PIECEALGO} --http-proxy=http://username:password@proxy_ip:proxy_port -i ${DLLIST} --connect-timeout=600 --timeout=600 -m0 --header "Accept: */*"' 126 | # 127 | # Default: _DOWNLOADER='aria2c --no-conf -c -j ${_MAXNUM} -x ${_MAXCONPERSRV} -s ${_SPLITCON} --min-split-size=${_MINSPLITSZ} --stream-piece-selector=${_PIECEALGO} -i ${DLLIST} --connect-timeout=600 --timeout=600 -m0 --header "Accept: */*"' 128 | # 129 | _DOWNLOADER='aria2c --no-conf -c -j ${_MAXNUM} -x ${_MAXCONPERSRV} -s ${_SPLITCON} --min-split-size=${_MINSPLITSZ} --stream-piece-selector=${_PIECEALGO} -i ${DLLIST} --connect-timeout=600 --timeout=600 -m0 --header "Accept: */*"' 130 | 131 | 132 | # Temporary download folder for download manager. 133 | # 134 | # Default: /var/cache/apt/apt-fast 135 | # 136 | DLDIR='/var/cache/apt/apt-fast' 137 | 138 | 139 | # APT archives cache directory 140 | # 141 | # Default /var/cache/apt/archives 142 | # (APT configuration items Dir::Cache and Dir::Cache::archives) 143 | # 144 | APTCACHE='/var/cache/apt/archives' 145 | 146 | 147 | # apt-fast colors 148 | # Colors are disabled when not using a terminal. 149 | # 150 | # Default colors are: 151 | # cGreen='\e[0;32m' 152 | # cRed='\e[0;31m' 153 | # cBlue='\e[0;34m' 154 | # endColor='\e[0m' 155 | -------------------------------------------------------------------------------- /docker/image/etc/apt/sources.list: -------------------------------------------------------------------------------- 1 | # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to 2 | # newer versions of the distribution. 3 | deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted 4 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted 5 | 6 | ## Major bug fix updates produced after the final release of the 7 | ## distribution. 8 | deb http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted 9 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted 10 | 11 | ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu 12 | ## team. Also, please note that software in universe WILL NOT receive any 13 | ## review or updates from the Ubuntu security team. 14 | deb http://mirrors.aliyun.com/ubuntu/ bionic universe 15 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic universe 16 | deb http://mirrors.aliyun.com/ubuntu/ bionic-updates universe 17 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates universe 18 | 19 | ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu 20 | ## team, and may not be under a free licence. Please satisfy yourself as to 21 | ## your rights to use the software. Also, please note that software in 22 | ## multiverse WILL NOT receive any review or updates from the Ubuntu 23 | ## security team. 24 | deb http://mirrors.aliyun.com/ubuntu/ bionic multiverse 25 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic multiverse 26 | deb http://mirrors.aliyun.com/ubuntu/ bionic-updates multiverse 27 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates multiverse 28 | 29 | ## N.B. software from this repository may not have been tested as 30 | ## extensively as that contained in the main release, although it includes 31 | ## newer versions of some applications which may provide useful features. 32 | ## Also, please note that software in backports WILL NOT receive any review 33 | ## or updates from the Ubuntu security team. 34 | deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse 35 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse 36 | 37 | ## Uncomment the following two lines to add software from Canonical's 38 | ## 'partner' repository. 39 | ## This software is not part of Ubuntu, but is offered by Canonical and the 40 | ## respective vendors as a service to Ubuntu users. 41 | # deb http://archive.canonical.com/ubuntu bionic partner 42 | # deb-src http://archive.canonical.com/ubuntu bionic partner 43 | 44 | deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted 45 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted 46 | deb http://mirrors.aliyun.com/ubuntu/ bionic-security universe 47 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security universe 48 | deb http://mirrors.aliyun.com/ubuntu/ bionic-security multiverse 49 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security multiverse -------------------------------------------------------------------------------- /docker/image/etc/apt/sources.list.d/ros-latest.list: -------------------------------------------------------------------------------- 1 | deb http://mirrors.ustc.edu.cn/ros/ubuntu/ bionic main -------------------------------------------------------------------------------- /docker/image/etc/default/keyboard: -------------------------------------------------------------------------------- 1 | # KEYBOARD CONFIGURATION FILE 2 | 3 | # Consult the keyboard(5) manual page. 4 | 5 | XKBMODEL="pc105" 6 | XKBLAYOUT="us" 7 | XKBVARIANT="" 8 | XKBOPTIONS="" 9 | 10 | BACKSPACE="guess" 11 | -------------------------------------------------------------------------------- /docker/image/etc/hosts: -------------------------------------------------------------------------------- 1 | 2 | 151.101.228.133 raw.githubusercontent.com 3 | 151.101.108.133 raw.githubusercontent.com 4 | 151.101.52.133 raw.githubusercontent.com 5 | 151.101.68.133 raw.githubusercontent.com 6 | 199.232.68.133 raw.githubusercontent.com 7 | -------------------------------------------------------------------------------- /docker/image/etc/nginx/sites-enabled/default: -------------------------------------------------------------------------------- 1 | map $http_upgrade $connection_upgrade { 2 | default upgrade; 3 | '' close; 4 | } 5 | 6 | server { 7 | listen 80; 8 | server_name _; 9 | 10 | location = / { 11 | try_files $uri @webportal; 12 | } 13 | 14 | location = /redirect.html { 15 | try_files $uri @webportal; 16 | } 17 | 18 | location / { 19 | try_files $uri @novnc; 20 | } 21 | 22 | location @webportal { 23 | include uwsgi_params; 24 | proxy_set_header X-Real-IP $remote_addr; 25 | proxy_set_header X-Forwarded-For $remote_addr; 26 | proxy_set_header Host $host; 27 | uwsgi_pass unix:/usr/lib/webportal/webportal.sock; 28 | max_ranges 0; 29 | } 30 | 31 | location @novnc { 32 | proxy_http_version 1.1; 33 | 34 | proxy_set_header Upgrade $http_upgrade; 35 | proxy_set_header Connection $connection_upgrade; 36 | 37 | proxy_pass http://127.0.0.1:6081; 38 | } 39 | } -------------------------------------------------------------------------------- /docker/image/etc/pip.conf: -------------------------------------------------------------------------------- 1 | [global] 2 | index-url = http://mirrors.aliyun.com/pypi/simple/ 3 | [install] 4 | trusted-host=mirrors.aliyun.com 5 | [list] 6 | format=columns -------------------------------------------------------------------------------- /docker/image/etc/resolv.conf: -------------------------------------------------------------------------------- 1 | nameserver 8.8.8.8 #google DNS 2 | nameserver 8.8.4.4 #google DNS -------------------------------------------------------------------------------- /docker/image/etc/supervisor/conf.d/lxde.conf: -------------------------------------------------------------------------------- 1 | [program:xvfb] 2 | priority=10 3 | directory=/ 4 | command=/usr/bin/Xvfb :1 -screen 0 1920x1200x16 5 | user=root 6 | autostart=true 7 | autorestart=true 8 | stopsignal=QUIT 9 | stdout_logfile=/var/log/xvfb.log 10 | redirect_stderr=true 11 | 12 | [program:lxsession] 13 | priority=15 14 | directory=/root 15 | command=/usr/bin/openbox 16 | user=root 17 | autostart=true 18 | autorestart=true 19 | stopsignal=QUIT 20 | environment=DISPLAY=":1",HOME="/root",USER="root" 21 | stdout_logfile=/var/log/openbox.log 22 | redirect_stderr=true 23 | 24 | [program:lxpanel] 25 | priority=15 26 | directory=/root 27 | command=/usr/bin/lxpanel --profile LXDE 28 | user=root 29 | autostart=true 30 | autorestart=true 31 | stopsignal=QUIT 32 | environment=DISPLAY=":1",HOME="/root",USER="root" 33 | stdout_logfile=/var/log/lxpanel.log 34 | redirect_stderr=true 35 | 36 | [program:pcmanfm] 37 | priority=15 38 | directory=/root 39 | command=/usr/bin/pcmanfm --desktop --profile LXDE 40 | user=root 41 | autostart=true 42 | autorestart=true 43 | stopsignal=QUIT 44 | environment=DISPLAY=":1",HOME="/root",USER="root" 45 | stdout_logfile=/var/log/pcmanfm.log 46 | 47 | [program:x11vnc] 48 | priority=20 49 | directory=/ 50 | command=x11vnc -display :1 -xkb -forever -shared -repeat -rfbport 5901 51 | user=root 52 | autostart=true 53 | autorestart=true 54 | stopsignal=QUIT 55 | stdout_logfile=/var/log/x11vnc.log 56 | redirect_stderr=true 57 | 58 | [program:novnc] 59 | priority=25 60 | directory=/usr/lib/noVNC/ 61 | command=/usr/lib/noVNC/utils/novnc_proxy --listen 6081 --vnc localhost:5901 62 | user=root 63 | autostart=true 64 | autorestart=true 65 | stopsignal=QUIT 66 | stdout_logfile=/var/log/novnc.log 67 | redirect_stderr=true 68 | stopasgroup=true -------------------------------------------------------------------------------- /docker/image/etc/supervisor/conf.d/webportal.conf: -------------------------------------------------------------------------------- 1 | [program:uwsgi] 2 | priority=30 3 | directory=/usr/lib/webportal/ 4 | command=/usr/local/bin/uwsgi --ini /usr/lib/webportal/app.ini 5 | stdout_logfile=/dev/stdout 6 | stdout_logfile_maxbytes=0 7 | stderr_logfile=/dev/stderr 8 | stderr_logfile_maxbytes=0 9 | 10 | [program:nginx] 11 | priority=30 12 | command=/usr/sbin/nginx -c /etc/nginx/nginx.conf -g "daemon off;" 13 | stdout_logfile=/dev/stdout 14 | stdout_logfile_maxbytes=0 15 | stderr_logfile=/dev/stderr 16 | stderr_logfile_maxbytes=0 17 | # Graceful stop, see http://nginx.org/en/docs/control.html 18 | stopsignal=QUIT -------------------------------------------------------------------------------- /docker/image/etc/supervisor/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | logfile=/root/supervisord.log ; supervisord log file 3 | logfile_maxbytes=50MB ; maximum size of logfile before rotation 4 | logfile_backups=10 ; number of backed up logfiles 5 | loglevel=error ; info, debug, warn, trace 6 | pidfile=/var/run/supervisord.pid ; pidfile location 7 | minfds=1024 ; number of startup file descriptors 8 | minprocs=200 ; number of process descriptors 9 | user=root ; default user 10 | childlogdir=/root ; where child log files will live 11 | 12 | [supervisorctl] 13 | serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket 14 | 15 | [inet_http_server] 16 | port=*:9001 ; (ip_address:port specifier, *:port for all iface) 17 | username=sensorfusion ; (default is no username (open server)) 18 | password=sensorfusion ; (default is no password (open server)) 19 | 20 | [unix_http_server] 21 | file=/var/run/supervisor.sock ; (the path to the socket file) 22 | chmod=0700 ; sockef file mode (default 0700) 23 | 24 | [rpcinterface:supervisor] 25 | supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface 26 | 27 | [eventlistener:inorder] 28 | command=/usr/local/bin/ordered-startup-listener 29 | autostart=true 30 | events=PROCESS_STATE 31 | 32 | [include] 33 | files=/etc/supervisor/conf.d/*.conf -------------------------------------------------------------------------------- /docker/image/root/.gtkrc-2.0: -------------------------------------------------------------------------------- 1 | # DO NOT EDIT! This file will be overwritten by LXAppearance. 2 | # Any customization should be done in ~/.gtkrc-2.0.mine instead. 3 | include "/usr/share/themes/Arc/gtk-2.0/gtkrc" 4 | 5 | gtk-theme-name="Arc" 6 | gtk-icon-theme-name="GNOME" 7 | gtk-font-name="Sans 10" 8 | gtk-cursor-theme-name="DMZ-White" 9 | gtk-cursor-theme-size=18 10 | gtk-toolbar-style=GTK_TOOLBAR_BOTH_HORIZ 11 | gtk-toolbar-icon-size=GTK_ICON_SIZE_LARGE_TOOLBAR 12 | gtk-button-images=1 13 | gtk-menu-images=1 14 | gtk-enable-event-sounds=0 15 | gtk-enable-input-feedback-sounds=0 16 | gtk-xft-antialias=1 17 | gtk-xft-hinting=1 18 | gtk-xft-hintstyle="hintslight" 19 | gtk-xft-rgba="rgb" 20 | include "/root/.gtkrc-2.0.mine" 21 | -------------------------------------------------------------------------------- /docker/image/root/Desktop/terminator.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Name=Terminator 3 | Comment=Multiple terminals in one window 4 | TryExec=terminator 5 | Exec=terminator 6 | Icon=terminator 7 | Type=Application 8 | Categories=GNOME;GTK;Utility;TerminalEmulator;System; 9 | StartupNotify=true 10 | X-Ubuntu-Gettext-Domain=terminator 11 | X-Ayatana-Desktop-Shortcuts=NewWindow; 12 | Keywords=terminal;shell;prompt;command;commandline; 13 | [NewWindow Shortcut Group] 14 | Name=Open a New Window 15 | Exec=terminator 16 | TargetEnvironment=Unity 17 | -------------------------------------------------------------------------------- /docker/image/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | mkdir -p /var/run/sshd 4 | 5 | chown -R root:root /root 6 | mkdir -p /root/.config/pcmanfm/LXDE/ 7 | cp /usr/share/doro-lxde-wallpapers/desktop-items-0.conf /root/.config/pcmanfm/LXDE/ 8 | 9 | if [ -n "$VNC_PASSWORD" ]; then 10 | echo -n "$VNC_PASSWORD" > /.password1 11 | x11vnc -storepasswd $(cat /.password1) /.password2 12 | chmod 400 /.password* 13 | sed -i 's/^command=x11vnc.*/& -rfbauth \/.password2/' /etc/supervisor/conf.d/lxde.conf 14 | export VNC_PASSWORD= 15 | fi 16 | 17 | # launch all: 18 | exec /usr/bin/tini -- /usr/bin/supervisord -n -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | app.log -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/README.md: -------------------------------------------------------------------------------- 1 | # Configuration Webportal for noVNC 2 | 3 | noVNC Configuration Webportal powered by Flask 4 | 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/app.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | # entrypoint -- app object in app.py: 3 | module = app:app 4 | # start up in master mode and spawn 2 worker processes to serve actual requests: 5 | master = true 6 | processes = 2 7 | # enable read and write on socket for nginx: 8 | socket = webportal.sock 9 | chown-socket = www-data:www-data 10 | chmod-socket = 664 11 | # clean up the socket when the process stops: 12 | vacuum = true 13 | # kill the process on signal term: 14 | die-on-term = true -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | from application import create_app 3 | 4 | app = create_app(os.getenv('FLASK_CONFIG') or 'default') 5 | 6 | if __name__ == '__main__': 7 | app.run(host='0.0.0.0', port=80, debug=True) -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from flask import Flask 4 | 5 | from config import basedir, config 6 | 7 | def create_app(config_name): 8 | # init app: 9 | app = Flask( 10 | __name__, 11 | static_url_path = '/static', static_folder = 'static' 12 | ) 13 | 14 | # apply configs: 15 | app.config.from_object(config[config_name]) 16 | config[config_name].init_app(app) 17 | 18 | # logging 19 | # ---------------------------------------------------------------- 20 | import logging 21 | from .utils.log import LoggingConfiguration 22 | LoggingConfiguration.set( 23 | logging.DEBUG if os.getenv('DEBUG') else logging.INFO, 24 | 'app.log', name='WebPortal' 25 | ) 26 | 27 | # views 28 | # ---------------------------------------------------------------- 29 | from .main import bp as blueprint_main 30 | app.register_blueprint(blueprint_main) 31 | 32 | return app -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/main/__init__.py: -------------------------------------------------------------------------------- 1 | from flask import Blueprint 2 | 3 | bp = Blueprint('main', __name__) 4 | 5 | from . import views -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/main/views.py: -------------------------------------------------------------------------------- 1 | from flask import request, render_template 2 | 3 | from flask import current_app 4 | from . import bp 5 | 6 | import subprocess 7 | import time 8 | 9 | 10 | @bp.route('/') 11 | def index(): 12 | """ Get client view portal size for noVNC 13 | """ 14 | current_app.logger.info('Get client view portal size.') 15 | 16 | return render_template('index.html') 17 | 18 | 19 | @bp.route('/redirect.html') 20 | def redirect(): 21 | """ Render noVNC portal 22 | """ 23 | if current_app.config['VIEW_PORTAL_INITIALIZED']: 24 | current_app.logger.info('Use existing view portal configuration.') 25 | return render_template('redirect.html') 26 | 27 | # parse view portal size: 28 | env = {'width': 1024, 'height': 768} 29 | if 'width' in request.args: 30 | env['width'] = request.args['width'] 31 | if 'height' in request.args: 32 | env['height'] = request.args['height'] 33 | 34 | # change desktop resolution: 35 | subprocess.check_call( 36 | r"sed -i 's#^command=/usr/bin/Xvfb.*$#command=/usr/bin/Xvfb :1 -screen 0 {width}x{height}x16#' /etc/supervisor/conf.d/lxde.conf".format(**env), 37 | shell=True 38 | ) 39 | 40 | # reload desktop: 41 | subprocess.check_call(r"supervisorctl update", shell=True) 42 | 43 | # make sure all the daemon processes are running: 44 | for i in range(current_app.config['MAX_TRYOUT']): 45 | # get the number of running supervisord processes: 46 | num_running = subprocess.check_output(r"supervisorctl status | grep RUNNING | wc -l", shell=True) 47 | if num_running.strip() == str(current_app.config['NUM_RUNNING']): 48 | # mark as initialized: 49 | current_app.config['VIEW_PORTAL_INITIALIZED'] = True 50 | current_app.logger.info( 51 | ( 52 | 'Set view portal size to (%d, %d) ' 53 | 'after tryout %d' 54 | ), 55 | int(env['width']), int(env['height']), i + 1 56 | ) 57 | return render_template('redirect.html') 58 | # sleep and try again: 59 | time.sleep(current_app.config['WAIT_TIME']) 60 | 61 | return render_template('redirect.html') 62 | 63 | @bp.route('/aboutus.html') 64 | def aboutus(): 65 | """ General info for testing 66 | """ 67 | current_app.logger.info('Get aboutus general info.') 68 | 69 | return render_template('aboutus.html') -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/static/tic.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/image/usr/lib/webportal/application/static/tic.jpg -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/templates/aboutus.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sensor Fusion Workspace 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | Init VNC Portal 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/templates/redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | Page Redirection 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/image/usr/lib/webportal/application/utils/__init__.py -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/application/utils/log.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import logging 3 | import logging.handlers 4 | 5 | 6 | #These are the sequences need to get colored ouput 7 | RESET_SEQ = "\033[0m" 8 | COLOR_SEQ = "\033[1;%dm" 9 | BOLD_SEQ = "\033[1m" 10 | 11 | 12 | class ColoredFormatter(logging.Formatter): 13 | # the terminal has 8 colors with codes from 0 to 7 14 | BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = range(8) 15 | 16 | # the background is set with 40 plus the number of the color, 17 | # and the foreground with 30 18 | COLORS = { 19 | 'WARNING': COLOR_SEQ % (30 + YELLOW) + 'WARN' + RESET_SEQ, 20 | 'INFO': COLOR_SEQ % (30 + WHITE) + 'INFO' + RESET_SEQ, 21 | 'DEBUG': COLOR_SEQ % (30 + BLUE) + 'DEBUG' + RESET_SEQ, 22 | 'CRITICAL': COLOR_SEQ % (30 + YELLOW) + 'CRITI' + RESET_SEQ, 23 | 'ERROR': COLOR_SEQ % (30 + RED) + 'ERROR' + RESET_SEQ, 24 | } 25 | 26 | def __init__(self, msg, use_color=True): 27 | logging.Formatter.__init__(self, msg) 28 | self.use_color = use_color 29 | 30 | def format(self, record): 31 | if self.use_color: 32 | # defaults to plain text with no color: 33 | record.levelname = self.COLORS.get(record.levelname, record.levelname) 34 | return logging.Formatter.format(self, record) 35 | 36 | 37 | class LoggingConfiguration(object): 38 | COLOR_FORMAT = ( 39 | "[%(asctime)s][%(threadName)-9s][%(levelname)s] " 40 | "%(message)s (" + BOLD_SEQ + "%(filename)s" + RESET_SEQ + ":%(lineno)d)" 41 | ) 42 | NO_COLOR_FORMAT = ( 43 | "[%(asctime)s][%(threadName)-9s][%(levelname)s] " 44 | "%(message)s " + "(%(filename)s:%(lineno)d)" 45 | ) 46 | FILE_FORMAT = ( 47 | "[%(asctime)s][%(threadName)-9s][%(levelname)s] " 48 | "%(message)s " 49 | ) 50 | 51 | @classmethod 52 | def set(cls, log_level, log_filename, append=None, **kwargs): 53 | """ configure a rotating file logging 54 | """ 55 | logger = logging.getLogger() 56 | logger.setLevel(log_level) 57 | 58 | COLOR_FORMAT = cls.COLOR_FORMAT 59 | NO_COLOR_FORMAT = cls.NO_COLOR_FORMAT 60 | FILE_FORMAT = cls.FILE_FORMAT 61 | if 'name' in kwargs: 62 | COLOR_FORMAT = COLOR_FORMAT.replace( 63 | '%(threadName)-9s', '%-9s' % (kwargs['name']) 64 | ) 65 | NO_COLOR_FORMAT = NO_COLOR_FORMAT.replace( 66 | '%(threadName)-9s', '%-9s' % (kwargs['name']) 67 | ) 68 | FILE_FORMAT = FILE_FORMAT.replace( 69 | '%(threadName)-9s', '%s' % (kwargs['name']) 70 | ) 71 | 72 | # log to rotating file 73 | try: 74 | log_handler = logging.handlers.RotatingFileHandler( 75 | log_filename, 76 | mode='a+', 77 | backupCount=3 78 | ) 79 | log_handler = logging.FileHandler( 80 | log_filename, 81 | mode='a+' 82 | ) 83 | log_handler.setFormatter(ColoredFormatter(FILE_FORMAT, False)) 84 | log_handler.setLevel(log_level) 85 | logger.addHandler(log_handler) 86 | if not append: 87 | # create a new log file: 88 | log_handler.doRollover() 89 | except: 90 | pass 91 | 92 | # log to sys.stderr using log level passed through command line 93 | if log_level != logging.NOTSET: 94 | log_handler = logging.StreamHandler(sys.stdout) 95 | if sys.platform.find('linux') >= 0: 96 | formatter = ColoredFormatter(COLOR_FORMAT) 97 | else: 98 | formatter = ColoredFormatter(NO_COLOR_FORMAT, False) 99 | log_handler.setFormatter(formatter) 100 | log_handler.setLevel(log_level) 101 | logger.addHandler(log_handler) 102 | -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/config.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # root dir of app: 4 | basedir = os.path.abspath(os.path.dirname(__file__)) 5 | 6 | class Config: 7 | # security: 8 | SECRET_KEY = os.environ.get('SECRET_KEY') or os.urandom(32) 9 | 10 | # view portal initialization: 11 | VIEW_PORTAL_INITIALIZED = False 12 | # the number of running supervisord processes: 13 | NUM_RUNNING = 6 14 | # max num. of tryouts: 15 | MAX_TRYOUT = 20 16 | WAIT_TIME = 1 17 | 18 | @staticmethod 19 | def init_app(app): 20 | """ integrate with app factory 21 | """ 22 | pass 23 | 24 | 25 | class DevelopmentConfig(Config): 26 | DEBUG = True 27 | 28 | 29 | class TestingConfig(Config): 30 | TESTING = True 31 | 32 | 33 | class ProductionConfig(Config): 34 | PRODUCTION=True 35 | 36 | 37 | # configs: 38 | config = { 39 | 'development': DevelopmentConfig, 40 | 'testing': TestingConfig, 41 | 'production': ProductionConfig, 42 | 43 | 'default': DevelopmentConfig 44 | } -------------------------------------------------------------------------------- /docker/image/usr/lib/webportal/requirements.txt: -------------------------------------------------------------------------------- 1 | flask==1.1.2 2 | uwsgi==2.0.19.1 -------------------------------------------------------------------------------- /docker/image/usr/share/doro-lxde-wallpapers/desktop-items-0.conf: -------------------------------------------------------------------------------- 1 | [*] 2 | wallpaper_mode=fit 3 | wallpaper_common=0 4 | wallpapers_configured=1 5 | wallpaper0=/usr/share/doro-lxde-wallpapers/theme.jpeg 6 | desktop_bg=#000000 7 | desktop_fg=#ffffff 8 | desktop_shadow=#111111 9 | desktop_font=Sans 12 10 | show_wm_menu=0 11 | sort=mtime;ascending;mingle; 12 | show_documents=0 13 | show_trash=0 14 | show_mounts=0 15 | -------------------------------------------------------------------------------- /docker/image/usr/share/doro-lxde-wallpapers/theme.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/image/usr/share/doro-lxde-wallpapers/theme.jpeg -------------------------------------------------------------------------------- /docker/image/workspace/data/nginx/noVNC.log: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/image/workspace/data/nginx/noVNC.log -------------------------------------------------------------------------------- /docker/image/workspace/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/docker/image/workspace/requirements.txt -------------------------------------------------------------------------------- /docker/installers/download-tini.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | TINI_VERSION=`curl https://github.com/krallin/tini/releases/latest | grep -o "/v.*\"" | sed 's:^..\(.*\).$:\1:'` 4 | 5 | curl -L "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini_${TINI_VERSION}.deb" > ./tini.deb -------------------------------------------------------------------------------- /ubuntu-setup/README.md: -------------------------------------------------------------------------------- 1 | # Ubuntu Setup Guide 2 | 3 | 如何安装Ubuntu系统 4 | 5 | --- 6 | 7 | ## Overview 8 | 9 | 本文档旨在提供Ubuntu操作系统Native安装配置指导, 支持某些对系统性能要求较高, 使用虚拟机无法满足性能要求的Linux开发工作 10 | 11 | --- 12 | 13 | ## Contents 14 | 15 | * [基础版, 本地磁盘双系统](doc/ubuntu-windows/Ubuntu双系统.pdf) 16 | 17 | * [进阶版, 外接硬盘安装](doc/external-disk/README.md) -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/README.md: -------------------------------------------------------------------------------- 1 | # Ubuntu Setup Guide 2 | 3 | 如何在外接SSD/NVME上安装Ubuntu系统 4 | 5 | --- 6 | 7 | ## Contents 8 | 9 | * [基础准备工作](https://www.shenlanxueyuan.com/my/course/303) 10 | 11 | * [重新启动并配置BIOS](https://www.shenlanxueyuan.com/my/course/303) 12 | 13 | * [安装Ubuntu, Part 1](https://www.shenlanxueyuan.com/my/course/303) 14 | 15 | * [安装Ubuntu, 配置分区表](https://www.shenlanxueyuan.com/my/course/303) 16 | 17 | * [安装Ubuntu, Part 2](https://www.shenlanxueyuan.com/my/course/303) 18 | 19 | * [配置阿里云源](https://www.shenlanxueyuan.com/my/course/303) 20 | 21 | --- 22 | 23 | ## 基础准备工作 24 | 25 | 首先, 准备两个硬盘: 26 | 27 | * 一个为**小容量USB Disk**, 用于制作Ubuntu Startup Disk, 作为**Ubuntu Installer**, 记录设备名称, 此处为**SanDisk USB** 28 | 29 | Ubuntu Installer Disk 30 | 31 | * 一个为**大容量SSD/NVMe Disk**, 用于Ubuntu Workspace Disk, 作为**Ubuntu Workspace**, 此处为**SAMSUNG SSD T3** 32 | 33 | Ubuntu Workspace Disk 34 | 35 | 接着, 将两个硬盘, 全部**格式化**. 格式化时目标文件系统为**Linux EXT4**. 此处以Ubuntu平台为示例, Windows与Mac用户请自行百度, 两系统均存在类似工具. 36 | 37 | Format Disks 38 | 39 | 最后, 使用工具, 在**小容量USB Disk**上制作**Ubuntu Installer**. 此处以Ubuntu平台为示例, Windows与Mac用户请自行百度, 两系统均存在类似工具. 40 | 41 | # **WARNING** 请务必仔细检查**设备名称**!!!确保选择了**正确的目标设备**!!!否则有可能**抹去现有系统盘上的数据** 42 | 43 | * 启动Creator: 44 | 45 | Launch Installer Creator 46 | 47 | * 选择设备: 48 | 49 | Select Device for Installer 50 | 51 | * 确认制作: 52 | 53 | Select Device for Installer 54 | 55 | --- 56 | 57 | ## 重新启动, 配置BIOS 58 | 59 | 在Ubuntu Installer制作完成后, 将上述两USB Disk全部连接PC, 然后重新启动PC. 在系统上电时, 进入BIOS. **进入BIOS的方式和使用设备高度相关, 此处仅作示意** 60 | 61 | 此处目标设备为ThinkPad P73. 在出现OEM Logo时, 按下提示键, 进入BIOS: 62 | 63 | Enter BIOS 64 | 65 | Enter BIOS 66 | 67 | 选择**Boot Config**: 68 | 69 | Select Boot Config 70 | 71 | 将启动优先级调整为**USB Device First**. 调整结束后: 72 | 73 | Set Boot Sequence 74 | 75 | * 首选的启动媒介为外接USB 76 | * USB设备名称有2个: 77 | 78 | * 其中一个为**Ubuntu Installer, SanDisk USB**, 它有Bootloader, 能够引导PC进入Ubuntu系统 79 | * 另一个为**Ubuntu Workspace, SAMSUNG SSD T3**, 它没有Bootloader, 不会引导PC进入Ubuntu系统 80 | 81 | * 保存BIOS设置, 重新启动设备, 若配置成功, 应当能看到如下的GRUB界面: 82 | 83 | Start Installation 84 | 85 | --- 86 | 87 | ## 安装Ubuntu 88 | 89 | 接下来进入Ubuntu安装 90 | 91 | 选择语言: 92 | 93 | Language Config 94 | 95 | 选择键盘Layout: 96 | 97 | Keyboard Config 98 | 99 | 选择**No Network Connnection** 100 | 101 | No Network Connection 102 | 103 | 安装类型选择**Normal Installation & Device Drivers** 104 | 105 | Installation Type 106 | 107 | 硬盘分区选择**Something Else**, 自定义分区类型. 108 | 109 | Custom Partition 110 | 111 | --- 112 | 113 | ## 创建分区表 114 | 115 | 接下来进入最重要的环节, 创建**Partiton Table** 116 | 117 | # **WARNING** 请务必仔细检查**设备名称**!!!确保选择了**正确的目标设备**!!!否则有可能**抹去现有系统盘上的数据** 118 | 119 | 首先, 选择正确的目标设备, 此处为**Ubuntu Workspace Disk, SAMSUNG SSD T3**, 点击**New Partition Table** 120 | 121 | Select Workspace Device 122 | 123 | # **WARNING** 请务必仔细检查**设备名称**!!!确保选择了**正确的目标设备**!!!否则有可能**抹去现有系统盘上的数据** 124 | 125 | 确认: 126 | 127 | Select Workspace Device 128 | 129 | 执行完成后, **Ubuntu Workspace Disk**会全部变成Freespace 130 | 131 | Format Workspace Device 132 | 133 | 接下来**创建分区**. 个人习惯如下, 分区按照**创建先后顺序排列**: 134 | 135 | * swap, **New Partition Type**为**Primary**, **Use As**为**swap**, 推荐大小**与PC物理内存相同**. 136 | 137 | swap 138 | 139 | * boot, **New Partition Type**为**Logical**, **Use As**为**EXT4 Filesystem**, 推荐大小**128/256MB**. 140 | 141 | boot 142 | 143 | * root, **New Partition Type**为**Logical**, **Use As**为**EXT4 Filesystem**, 推荐大小为**剩余的全部Free Space** 144 | 145 | root 146 | 147 | 完成后目标设备上的分区表如下图所示, 点击**Install Now**, 启动安装: 148 | 149 | Workspace Device Partition Table 150 | 151 | --- 152 | 153 | ## 安装Ubuntu 154 | 155 | 接下来, 完成剩余的配置, 等待安装成功: 156 | 157 | 选择区域: 158 | 159 | Region Config 160 | 161 | 设置设备名, 账号/密码: 162 | 163 | Device Config 164 | 165 | 等待安装结束: 166 | 167 | Finish 168 | 169 | 按照提示重启PC, 完成安装. 170 | 171 | --- 172 | 173 | ## 配置阿里云源 174 | 175 | 在设备下电后, 断开**Ubuntu Installer**与PC的链接, 仅保留**Ubuntu Workspace**与PC的链接, 启动Ubuntu. 176 | 177 | 接下来还需要进行最后一步: **配置阿里云源, 更新系统软件**. 此处**至关重要**, 有些设备只有在获取最新驱动后, 才能够正常使用Ubuntu 178 | 179 | 首先, 打开**etc-apt-source.list** 180 | 181 | ```bash 182 | sudo gedit /etc/apt/sources.list 183 | ``` 184 | 185 | 删除系统默认配置, 将以下阿里云源配置写入, 保存: 186 | 187 | ```bash 188 | # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to 189 | # newer versions of the distribution. 190 | deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted 191 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic main restricted 192 | 193 | ## Major bug fix updates produced after the final release of the 194 | ## distribution. 195 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates main restricted 196 | 197 | ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu 198 | ## team. Also, please note that software in universe WILL NOT receive any 199 | ## review or updates from the Ubuntu security team. 200 | deb http://mirrors.aliyun.com/ubuntu/ bionic universe 201 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic universe 202 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates universe 203 | 204 | ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu 205 | ## team, and may not be under a free licence. Please satisfy yourself as to 206 | ## your rights to use the software. Also, please note that software in 207 | ## multiverse WILL NOT receive any review or updates from the Ubuntu 208 | ## security team. 209 | deb http://mirrors.aliyun.com/ubuntu/ bionic multiverse 210 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic multiverse 211 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-updates multiverse 212 | 213 | ## N.B. software from this repository may not have been tested as 214 | ## extensively as that contained in the main release, although it includes 215 | ## newer versions of some applications which may provide useful features. 216 | ## Also, please note that software in backports WILL NOT receive any review 217 | ## or updates from the Ubuntu security team. 218 | deb http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse 219 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-backports main restricted universe multiverse 220 | 221 | ## Uncomment the following two lines to add software from Canonical's 222 | ## 'partner' repository. 223 | ## This software is not part of Ubuntu, but is offered by Canonical and the 224 | ## respective vendors as a service to Ubuntu users. 225 | # deb http://archive.canonical.com/ubuntu bionic partner 226 | # deb-src http://archive.canonical.com/ubuntu bionic partner 227 | 228 | deb http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted 229 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security main restricted 230 | deb http://mirrors.aliyun.com/ubuntu/ bionic-security universe 231 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security universe 232 | deb http://mirrors.aliyun.com/ubuntu/ bionic-security multiverse 233 | # deb-src http://mirrors.aliyun.com/ubuntu/ bionic-security multiverse 234 | deb http://mirrors.aliyun.com/ubuntu/ bionic-updates multiverse restricted universe main 235 | ``` 236 | 237 | 然后执行系统更新: 238 | 239 | ```bash 240 | sudo apt-get update && sudo apt-get update 241 | ``` 242 | 243 | 配置成功后, 可以看到Packge URL均为阿里云源. 该设置能大幅提升相关依赖安装速度. -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/00-cleanup-a-installer-disk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/00-cleanup-a-installer-disk.jpg -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/00-cleanup-b-ubuntu-disk.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/00-cleanup-b-ubuntu-disk.jpg -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/00-cleanup-format-disks.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/00-cleanup-format-disks.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/01-startup-disk-create--confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/01-startup-disk-create--confirm.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/01-startup-disk-create--existing-ubuntu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/01-startup-disk-create--existing-ubuntu.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/01-startup-disk-create--select-device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/01-startup-disk-create--select-device.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/02-BIOS-boot-config.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/02-BIOS-boot-config.jpg -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/02-BIOS-boot-sequence.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/02-BIOS-boot-sequence.jpg -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/02-BIOS-enter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/02-BIOS-enter.jpg -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/02-BIOS-setup.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/02-BIOS-setup.jpg -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/02-BIOS-start-installation.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/02-BIOS-start-installation.jpg -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-a-keyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-a-keyboard.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-a-language.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-a-language.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-c-network.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-c-network.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-d-option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-d-option.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-e-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-e-type.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-f-create-new-partition-confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-f-create-new-partition-confirm.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-f-create-new-partition-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-f-create-new-partition-result.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-f-create-new-partition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-f-create-new-partition.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-g-02-boot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-g-02-boot.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-g-03-root.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-g-03-root.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-g-result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-g-result.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-h-confirm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-h-confirm.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-i-region.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-i-region.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-k-config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-k-config.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/external-disk/images/03-install-ubuntu-l-finish.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/external-disk/images/03-install-ubuntu-l-finish.png -------------------------------------------------------------------------------- /ubuntu-setup/doc/ubuntu-windows/Ubuntu双系统.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/ubuntu-setup/doc/ubuntu-windows/Ubuntu双系统.pdf -------------------------------------------------------------------------------- /workspace/.gitignore: -------------------------------------------------------------------------------- 1 | ordered_startup.log -------------------------------------------------------------------------------- /workspace/README.md: -------------------------------------------------------------------------------- 1 | # Sensor Fusion for Localization and Mapping Workspace 2 | 3 | 本目录为Docker Workspace中 /workspace 在本地的挂载点. 4 | -------------------------------------------------------------------------------- /workspace/assignments/.gitignore: -------------------------------------------------------------------------------- 1 | image_based_modelling 2 | ImageBasedModellingEdu -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/.gitignore: -------------------------------------------------------------------------------- 1 | .catkin_tools 2 | build 3 | devel 4 | install 5 | logs 6 | output -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/README.md: -------------------------------------------------------------------------------- 1 | # Multi-Sensor Fusion for Localization & Mapping -- 多传感器融合定位与建图: Introduction 2 | 3 | 深蓝学院多传感器融合定位与建图第1节Environment Setup作业框架. 4 | 5 | --- 6 | 7 | ## Overview 8 | 9 | 本作业旨在引导您: 10 | 11 | * 验证环境配置的正确性 12 | * 熟悉课程教学框架 13 | 14 | --- 15 | 16 | ## Getting Started 17 | 18 | 启动Docker后, 打开浏览器, 前往localhost:40080, 进入Web Workspace. **若需要提高清晰度, 可以更改URL中的quality参数**. 启动Terminator, 将两个Shell的工作目录切换如下: 19 | 20 | Terminator 21 | 22 | 在**上侧**的Shell中, 输入如下命令, **编译catkin_workspace** 23 | 24 | ```bash 25 | # build 26 | catkin config --install && catkin build 27 | ``` 28 | 29 | 然后**启动解决方案** 30 | 31 | ```bash 32 | # set up session: 33 | source install/setup.bash 34 | # launch: 35 | roslaunch lidar_localization hello_kitti.launch 36 | ``` 37 | 38 | 在**下侧**的Shell中, 输入如下命令, **Play KITTI ROS Bag** 39 | 40 | ```bash 41 | # play ROS bag 42 | rosbag play kitti_2011_10_03_drive_0027_synced.bag 43 | ``` 44 | 45 | 成功后, 可以看到如下的RViz界面: 46 | 47 | KITTI Demo -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/doc/demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/workspace/assignments/01-introduction/doc/demo.png -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/doc/terminator.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexGeControl/Sensor-Fusion-for-Localization-Courseware/e1d8ea2ad00a4f4314d059630e729e540a0ad08e/workspace/assignments/01-introduction/doc/terminator.png -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | /opt/ros/melodic/share/catkin/cmake/toplevel.cmake -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | Log 3 | 4 | *.INFO 5 | *.INFO.* 6 | 7 | # Prerequisites 8 | *.d 9 | 10 | # Compiled Object files 11 | *.slo 12 | *.lo 13 | *.o 14 | *.obj 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Compiled Dynamic libraries 21 | *.so 22 | *.dylib 23 | *.dll 24 | 25 | # Fortran module files 26 | *.mod 27 | *.smod 28 | 29 | # Compiled Static libraries 30 | *.lai 31 | *.la 32 | *.a 33 | *.lib 34 | 35 | # Executables 36 | *.exe 37 | *.out 38 | *.app 39 | -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10.2) 2 | project(lidar_localization) 3 | 4 | SET(CMAKE_BUILD_TYPE "Release") 5 | SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall") 6 | add_compile_options(-std=c++14) 7 | add_definitions(-std=c++14) 8 | 9 | find_package(catkin REQUIRED COMPONENTS 10 | roscpp 11 | rospy 12 | std_msgs 13 | pcl_ros 14 | geometry_msgs 15 | tf 16 | eigen_conversions 17 | message_generation 18 | std_srvs 19 | ) 20 | 21 | set(ALL_TARGET_LIBRARIES "") 22 | 23 | include(cmake/glog.cmake) 24 | include(cmake/PCL.cmake) 25 | include(cmake/geographic.cmake) 26 | 27 | include_directories(include ${catkin_INCLUDE_DIRS}) 28 | 29 | include(cmake/global_defination.cmake) 30 | catkin_package() 31 | 32 | file(GLOB_RECURSE ALL_SRCS "*.cpp") 33 | file(GLOB_RECURSE NODE_SRCS "src/*_node.cpp") 34 | 35 | list(REMOVE_ITEM ALL_SRCS ${NODE_SRCS}) 36 | 37 | add_executable(hello_kitti_node src/hello_kitti_node.cpp ${ALL_SRCS}) 38 | target_link_libraries(hello_kitti_node ${catkin_LIBRARIES} ${ALL_TARGET_LIBRARIES}) 39 | 40 | ############# 41 | ## Install ## 42 | ############# 43 | 44 | # all install targets should use catkin DESTINATION variables 45 | # See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html 46 | 47 | ## Mark executable scripts (Python etc.) for installation 48 | ## in contrast to setup.py, you can choose the destination 49 | # catkin_install_python(PROGRAMS 50 | # scripts/my_python_script 51 | # DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 52 | # ) 53 | 54 | ## Mark executables for installation 55 | ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_executables.html 56 | 57 | install( 58 | TARGETS 59 | hello_kitti_node 60 | RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION} 61 | ) 62 | 63 | ## Mark cpp header files for installation 64 | install( 65 | DIRECTORY 66 | include/ 67 | DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} 68 | FILES_MATCHING PATTERN "*.h" 69 | PATTERN ".svn" EXCLUDE 70 | ) 71 | 72 | ## Mark other directories for installation: 73 | install( 74 | DIRECTORY 75 | launch/ 76 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch 77 | FILES_MATCHING PATTERN "*.launch" 78 | ) 79 | install( 80 | DIRECTORY 81 | config/ 82 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/config 83 | FILES_MATCHING PATTERN "*.yaml" 84 | ) 85 | install( 86 | DIRECTORY 87 | rviz/ 88 | DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/rviz 89 | FILES_MATCHING PATTERN "*.rviz" 90 | ) -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/cmake/PCL.cmake: -------------------------------------------------------------------------------- 1 | find_package(PCL 1.7 REQUIRED) 2 | list(REMOVE_ITEM PCL_LIBRARIES "vtkproj4") 3 | 4 | include_directories(${PCL_INCLUDE_DIRS}) 5 | list(APPEND ALL_TARGET_LIBRARIES ${PCL_LIBRARIES}) -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/cmake/geographic.cmake: -------------------------------------------------------------------------------- 1 | find_package (GeographicLib REQUIRED) 2 | 3 | include_directories(${GeographicLib_INCLUDE_DIRS}) 4 | list(APPEND ALL_TARGET_LIBRARIES ${GeographicLib_LIBRARIES}) -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/cmake/global_defination.cmake: -------------------------------------------------------------------------------- 1 | set(WORK_SPACE_PATH ${PROJECT_SOURCE_DIR}) 2 | configure_file ( 3 | ${PROJECT_SOURCE_DIR}/include/${PROJECT_NAME}/global_defination/global_defination.h.in 4 | ${PROJECT_BINARY_DIR}/include/${PROJECT_NAME}/global_defination/global_defination.h) 5 | include_directories(${PROJECT_BINARY_DIR}/include) -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/cmake/glog.cmake: -------------------------------------------------------------------------------- 1 | include(FindPackageHandleStandardArgs) 2 | 3 | set(GLOG_ROOT_DIR "" CACHE PATH "Folder contains Google glog") 4 | 5 | if(WIN32) 6 | find_path(GLOG_INCLUDE_DIR glog/logging.h 7 | PATHS ${GLOG_ROOT_DIR}/src/windows) 8 | else() 9 | find_path(GLOG_INCLUDE_DIR glog/logging.h 10 | PATHS ${GLOG_ROOT_DIR}) 11 | endif() 12 | 13 | if(MSVC) 14 | find_library(GLOG_LIBRARY_RELEASE libglog_static 15 | PATHS ${GLOG_ROOT_DIR} 16 | PATH_SUFFIXES Release) 17 | 18 | find_library(GLOG_LIBRARY_DEBUG libglog_static 19 | PATHS ${GLOG_ROOT_DIR} 20 | PATH_SUFFIXES Debug) 21 | 22 | set(GLOG_LIBRARY optimized ${GLOG_LIBRARY_RELEASE} debug ${GLOG_LIBRARY_DEBUG}) 23 | else() 24 | find_library(GLOG_LIBRARY glog 25 | PATHS ${GLOG_ROOT_DIR} 26 | PATH_SUFFIXES lib lib64) 27 | endif() 28 | 29 | find_package_handle_standard_args(Glog DEFAULT_MSG GLOG_INCLUDE_DIR GLOG_LIBRARY) 30 | 31 | if(GLOG_FOUND) 32 | set(GLOG_INCLUDE_DIRS ${GLOG_INCLUDE_DIR}) 33 | set(GLOG_LIBRARIES ${GLOG_LIBRARY}) 34 | message(STATUS "Found glog (include: ${GLOG_INCLUDE_DIR}, library: ${GLOG_LIBRARY})") 35 | mark_as_advanced(GLOG_ROOT_DIR GLOG_LIBRARY_RELEASE GLOG_LIBRARY_DEBUG 36 | GLOG_LIBRARY GLOG_INCLUDE_DIR) 37 | endif() 38 | 39 | include_directories(${GLOG_INCLUDE_DIRS}) 40 | list(APPEND ALL_TARGET_LIBRARIES ${GLOG_LIBRARIES}) 41 | -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/global_defination/global_defination.h.in: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-05 02:27:30 5 | */ 6 | #ifndef LIDAR_LOCALIZATION_GLOBAL_DEFINATION_H_IN_ 7 | #define LIDAR_LOCALIZATION_GLOBAL_DEFINATION_H_IN_ 8 | 9 | #include 10 | 11 | namespace lidar_localization { 12 | const std::string WORK_SPACE_PATH = "@WORK_SPACE_PATH@"; 13 | } 14 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/publisher/cloud_publisher.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 在ros中发布点云 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-05 02:27:30 5 | */ 6 | 7 | #ifndef LIDAR_LOCALIZATION_PUBLISHER_CLOUD_PUBLISHER_HPP_ 8 | #define LIDAR_LOCALIZATION_PUBLISHER_CLOUD_PUBLISHER_HPP_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "lidar_localization/sensor_data/cloud_data.hpp" 16 | 17 | namespace lidar_localization { 18 | class CloudPublisher { 19 | public: 20 | CloudPublisher(ros::NodeHandle& nh, 21 | std::string topic_name, 22 | size_t buff_size, 23 | std::string frame_id); 24 | CloudPublisher() = default; 25 | void Publish(CloudData::CLOUD_PTR cloud_ptr_input); 26 | 27 | private: 28 | ros::NodeHandle nh_; 29 | ros::Publisher publisher_; 30 | std::string frame_id_; 31 | }; 32 | } 33 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/publisher/odometry_publisher.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: odometry 信息发布 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-06 21:05:47 5 | */ 6 | #ifndef LIDAR_LOCALIZATION_PUBLISHER_ODOMETRY_PUBLISHER_HPP_ 7 | #define LIDAR_LOCALIZATION_PUBLISHER_ODOMETRY_PUBLISHER_HPP_ 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace lidar_localization { 16 | class OdometryPublisher { 17 | public: 18 | OdometryPublisher(ros::NodeHandle& nh, 19 | std::string topic_name, 20 | std::string base_frame_id, 21 | std::string child_frame_id, 22 | int buff_size); 23 | OdometryPublisher() = default; 24 | 25 | void Publish(const Eigen::Matrix4f& transform_matrix); 26 | 27 | private: 28 | ros::NodeHandle nh_; 29 | ros::Publisher publisher_; 30 | nav_msgs::Odometry odometry_; 31 | }; 32 | } 33 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/publisher/tf_broadcaster.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: TF broadcaster 3 | * @Author: Ren Qian 4 | * @Date: 2020-03-05 15:23:26 5 | */ 6 | 7 | #ifndef LIDAR_LOCALIZATION_PUBLISHER_TF_BROADCASTER_HPP_ 8 | #define LIDAR_LOCALIZATION_PUBLISHER_TF_BROADCASTER_HPP_ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | namespace lidar_localization { 17 | 18 | class TFBroadCaster { 19 | public: 20 | TFBroadCaster(std::string frame_id, std::string child_frame_id); 21 | TFBroadCaster() = default; 22 | void SendTransform(Eigen::Matrix4f pose, double time); 23 | protected: 24 | tf::StampedTransform transform_; 25 | tf::TransformBroadcaster broadcaster_; 26 | }; 27 | 28 | } 29 | 30 | #endif // namespace lidar_localization -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/sensor_data/cloud_data.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Author: Ren Qian 4 | * @Date: 2019-07-17 18:17:49 5 | */ 6 | #ifndef LIDAR_LOCALIZATION_SENSOR_DATA_CLOUD_DATA_HPP_ 7 | #define LIDAR_LOCALIZATION_SENSOR_DATA_CLOUD_DATA_HPP_ 8 | 9 | #include 10 | #include 11 | 12 | namespace lidar_localization { 13 | class CloudData { 14 | public: 15 | using POINT = pcl::PointXYZ; 16 | using CLOUD = pcl::PointCloud; 17 | using CLOUD_PTR = CLOUD::Ptr; 18 | 19 | public: 20 | CloudData() 21 | :cloud_ptr(new CLOUD()) { 22 | } 23 | 24 | public: 25 | double time = 0.0; 26 | CLOUD_PTR cloud_ptr; 27 | }; 28 | } 29 | 30 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/sensor_data/gnss_data.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Author: Ren Qian 4 | * @Date: 2019-07-17 18:25:13 5 | */ 6 | #ifndef LIDAR_LOCALIZATION_SENSOR_DATA_GNSS_DATA_HPP_ 7 | #define LIDAR_LOCALIZATION_SENSOR_DATA_GNSS_DATA_HPP_ 8 | 9 | #include 10 | 11 | #include 12 | 13 | namespace lidar_localization { 14 | class GNSSData { 15 | public: 16 | double time = 0.0; 17 | double longitude = 0.0; 18 | double latitude = 0.0; 19 | double altitude = 0.0; 20 | double local_E = 0.0; 21 | double local_N = 0.0; 22 | double local_U = 0.0; 23 | int status = 0; 24 | int service = 0; 25 | 26 | private: 27 | static GeographicLib::LocalCartesian geo_converter; 28 | static bool origin_position_inited; 29 | 30 | public: 31 | void InitOriginPosition(); 32 | void UpdateXYZ(); 33 | static bool SyncData(std::deque& UnsyncedData, std::deque& SyncedData, double sync_time); 34 | }; 35 | } 36 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/sensor_data/imu_data.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Author: Ren Qian 4 | * @Date: 2019-07-17 18:27:40 5 | */ 6 | #ifndef LIDAR_LOCALIZATION_SENSOR_DATA_IMU_DATA_HPP_ 7 | #define LIDAR_LOCALIZATION_SENSOR_DATA_IMU_DATA_HPP_ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace lidar_localization { 14 | class IMUData { 15 | public: 16 | struct LinearAcceleration { 17 | double x = 0.0; 18 | double y = 0.0; 19 | double z = 0.0; 20 | }; 21 | 22 | struct AngularVelocity { 23 | double x = 0.0; 24 | double y = 0.0; 25 | double z = 0.0; 26 | }; 27 | 28 | class Orientation { 29 | public: 30 | double x = 0.0; 31 | double y = 0.0; 32 | double z = 0.0; 33 | double w = 0.0; 34 | 35 | public: 36 | void Normlize() { 37 | double norm = sqrt(pow(x, 2.0) + pow(y, 2.0) + pow(z, 2.0) + pow(w, 2.0)); 38 | x /= norm; 39 | y /= norm; 40 | z /= norm; 41 | w /= norm; 42 | } 43 | }; 44 | 45 | double time = 0.0; 46 | LinearAcceleration linear_acceleration; 47 | AngularVelocity angular_velocity; 48 | Orientation orientation; 49 | 50 | public: 51 | // 把四元数转换成旋转矩阵送出去 52 | Eigen::Matrix3f GetOrientationMatrix(); 53 | static bool SyncData(std::deque& UnsyncedData, std::deque& SyncedData, double sync_time); 54 | }; 55 | } 56 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/subscriber/cloud_subscriber.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 订阅激光点云信息,并解析数据 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-05 02:27:30 5 | */ 6 | 7 | #ifndef LIDAR_LOCALIZATION_SUBSCRIBER_CLOUD_SUBSCRIBER_HPP_ 8 | #define LIDAR_LOCALIZATION_SUBSCRIBER_CLOUD_SUBSCRIBER_HPP_ 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "lidar_localization/sensor_data/cloud_data.hpp" 19 | 20 | namespace lidar_localization { 21 | class CloudSubscriber { 22 | public: 23 | CloudSubscriber(ros::NodeHandle& nh, std::string topic_name, size_t buff_size); 24 | CloudSubscriber() = default; 25 | void ParseData(std::deque& deque_cloud_data); 26 | 27 | private: 28 | void msg_callback(const sensor_msgs::PointCloud2::ConstPtr& cloud_msg_ptr); 29 | 30 | private: 31 | ros::NodeHandle nh_; 32 | ros::Subscriber subscriber_; 33 | 34 | std::deque new_cloud_data_; 35 | }; 36 | } 37 | 38 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/subscriber/gnss_subscriber.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Author: Ren Qian 4 | * @Date: 2019-03-31 12:58:10 5 | */ 6 | #ifndef LIDAR_LOCALIZATION_SUBSCRIBER_GNSS_SUBSCRIBER_HPP_ 7 | #define LIDAR_LOCALIZATION_SUBSCRIBER_GNSS_SUBSCRIBER_HPP_ 8 | 9 | #include 10 | #include 11 | #include "sensor_msgs/NavSatFix.h" 12 | #include "lidar_localization/sensor_data/gnss_data.hpp" 13 | 14 | namespace lidar_localization { 15 | class GNSSSubscriber { 16 | public: 17 | GNSSSubscriber(ros::NodeHandle& nh, std::string topic_name, size_t buff_size); 18 | GNSSSubscriber() = default; 19 | void ParseData(std::deque& deque_gnss_data); 20 | 21 | private: 22 | void msg_callback(const sensor_msgs::NavSatFixConstPtr& nav_sat_fix_ptr); 23 | 24 | private: 25 | ros::NodeHandle nh_; 26 | ros::Subscriber subscriber_; 27 | 28 | std::deque new_gnss_data_; 29 | }; 30 | } 31 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/subscriber/imu_subscriber.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 订阅imu数据 3 | * @Author: Ren Qian 4 | * @Date: 2019-08-19 19:22:17 5 | */ 6 | #ifndef LIDAR_LOCALIZATION_SUBSCRIBER_IMU_SUBSCRIBER_HPP_ 7 | #define LIDAR_LOCALIZATION_SUBSCRIBER_IMU_SUBSCRIBER_HPP_ 8 | 9 | #include 10 | #include 11 | #include "sensor_msgs/Imu.h" 12 | #include "lidar_localization/sensor_data/imu_data.hpp" 13 | 14 | namespace lidar_localization { 15 | class IMUSubscriber { 16 | public: 17 | IMUSubscriber(ros::NodeHandle& nh, std::string topic_name, size_t buff_size); 18 | IMUSubscriber() = default; 19 | void ParseData(std::deque& deque_imu_data); 20 | 21 | private: 22 | void msg_callback(const sensor_msgs::ImuConstPtr& imu_msg_ptr); 23 | 24 | private: 25 | ros::NodeHandle nh_; 26 | ros::Subscriber subscriber_; 27 | 28 | std::deque new_imu_data_; 29 | }; 30 | } 31 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/include/lidar_localization/subscriber/tf_listener.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: TF listener 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-06 16:01:21 5 | */ 6 | #ifndef LIDAR_LOCALIZATION_TF_LISTENER_HPP_ 7 | #define LIDAR_LOCALIZATION_TF_LISTENER_HPP_ 8 | 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | namespace lidar_localization { 16 | class TFListener { 17 | public: 18 | TFListener(ros::NodeHandle& nh, std::string base_frame_id, std::string child_frame_id); 19 | TFListener() = default; 20 | 21 | bool LookupData(Eigen::Matrix4f& transform_matrix); 22 | 23 | private: 24 | bool TransformToMatrix(const tf::StampedTransform& transform, Eigen::Matrix4f& transform_matrix); 25 | 26 | private: 27 | ros::NodeHandle nh_; 28 | tf::TransformListener listener_; 29 | std::string base_frame_id_; 30 | std::string child_frame_id_; 31 | }; 32 | } 33 | 34 | #endif -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/launch/hello_kitti.launch: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/package.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | lidar_localization 4 | 0.0.0 5 | The lidar_localization package 6 | 7 | 8 | 9 | 10 | rq 11 | 12 | 13 | 14 | 15 | 16 | TODO 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | catkin 52 | roscpp 53 | rospy 54 | roscpp 55 | rospy 56 | roscpp 57 | rospy 58 | 59 | message_generation 60 | message_runtime 61 | 62 | sensor_msgs 63 | pcl_ros 64 | std_msgs 65 | geometry_msgs 66 | tf 67 | eigen_conversions 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/rviz/hello_kitti.rviz: -------------------------------------------------------------------------------- 1 | Panels: 2 | - Class: rviz/Displays 3 | Help Height: 78 4 | Name: Displays 5 | Property Tree Widget: 6 | Expanded: 7 | - /Global Options1 8 | - /Status1 9 | - /current_scan1/Autocompute Value Bounds1 10 | Splitter Ratio: 0.5 11 | Tree Height: 237 12 | - Class: rviz/Selection 13 | Name: Selection 14 | - Class: rviz/Tool Properties 15 | Expanded: 16 | - /2D Pose Estimate1 17 | - /2D Nav Goal1 18 | - /Publish Point1 19 | Name: Tool Properties 20 | Splitter Ratio: 0.5886790156364441 21 | - Class: rviz/Views 22 | Expanded: 23 | - /Current View1 24 | Name: Views 25 | Splitter Ratio: 0.5 26 | - Class: rviz/Time 27 | Experimental: false 28 | Name: Time 29 | SyncMode: 0 30 | SyncSource: current_scan 31 | Preferences: 32 | PromptSaveOnExit: true 33 | Toolbars: 34 | toolButtonStyle: 2 35 | Visualization Manager: 36 | Class: "" 37 | Displays: 38 | - Alpha: 0.5 39 | Cell Size: 1 40 | Class: rviz/Grid 41 | Color: 160; 160; 164 42 | Enabled: true 43 | Line Style: 44 | Line Width: 0.029999999329447746 45 | Value: Lines 46 | Name: Grid 47 | Normal Cell Count: 0 48 | Offset: 49 | X: 0 50 | Y: 0 51 | Z: 0 52 | Plane: XY 53 | Plane Cell Count: 10 54 | Reference Frame: 55 | Value: true 56 | - Class: rviz/Image 57 | Enabled: true 58 | Image Topic: /kitti/camera_color_left/image_raw 59 | Max Value: 1 60 | Median window: 5 61 | Min Value: 0 62 | Name: Image 63 | Normalize Range: true 64 | Queue Size: 2 65 | Transport Hint: raw 66 | Unreliable: false 67 | Value: true 68 | - Alpha: 0.20000000298023224 69 | Autocompute Intensity Bounds: true 70 | Autocompute Value Bounds: 71 | Max Value: 4.7789998054504395 72 | Min Value: -9.574000358581543 73 | Value: false 74 | Axis: Z 75 | Channel Name: intensity 76 | Class: rviz/PointCloud2 77 | Color: 255; 255; 255 78 | Color Transformer: AxisColor 79 | Decay Time: 0 80 | Enabled: true 81 | Invert Rainbow: false 82 | Max Color: 255; 255; 255 83 | Max Intensity: 255 84 | Min Color: 0; 0; 0 85 | Min Intensity: 7 86 | Name: current_scan 87 | Position Transformer: XYZ 88 | Queue Size: 10 89 | Selectable: true 90 | Size (Pixels): 2 91 | Size (m): 0.5 92 | Style: Points 93 | Topic: /current_scan 94 | Unreliable: false 95 | Use Fixed Frame: true 96 | Use rainbow: true 97 | Value: true 98 | - Angle Tolerance: 1 99 | Class: rviz/Odometry 100 | Covariance: 101 | Orientation: 102 | Alpha: 0.5 103 | Color: 255; 255; 127 104 | Color Style: Unique 105 | Frame: Local 106 | Offset: 1 107 | Scale: 1 108 | Value: true 109 | Position: 110 | Alpha: 0.30000001192092896 111 | Color: 204; 51; 204 112 | Scale: 1 113 | Value: true 114 | Value: true 115 | Enabled: true 116 | Keep: 10000000 117 | Name: reference_odometry 118 | Position Tolerance: 1 119 | Shape: 120 | Alpha: 1 121 | Axes Length: 1 122 | Axes Radius: 0.10000000149011612 123 | Color: 255; 25; 0 124 | Head Length: 5 125 | Head Radius: 1 126 | Shaft Length: 1 127 | Shaft Radius: 0.10000000149011612 128 | Value: Arrow 129 | Topic: /lidar_odom 130 | Unreliable: false 131 | Value: true 132 | Enabled: true 133 | Global Options: 134 | Background Color: 48; 48; 48 135 | Default Light: true 136 | Fixed Frame: map 137 | Frame Rate: 30 138 | Name: root 139 | Tools: 140 | - Class: rviz/Interact 141 | Hide Inactive Objects: true 142 | - Class: rviz/MoveCamera 143 | - Class: rviz/Select 144 | - Class: rviz/FocusCamera 145 | - Class: rviz/Measure 146 | - Class: rviz/SetInitialPose 147 | Theta std deviation: 0.2617993950843811 148 | Topic: /initialpose 149 | X std deviation: 0.5 150 | Y std deviation: 0.5 151 | - Class: rviz/SetGoal 152 | Topic: /move_base_simple/goal 153 | - Class: rviz/PublishPoint 154 | Single click: true 155 | Topic: /clicked_point 156 | Value: true 157 | Views: 158 | Current: 159 | Class: rviz/Orbit 160 | Distance: 141.82858276367188 161 | Enable Stereo Rendering: 162 | Stereo Eye Separation: 0.05999999865889549 163 | Stereo Focal Distance: 1 164 | Swap Stereo Eyes: false 165 | Value: false 166 | Focal Point: 167 | X: -0.40340137481689453 168 | Y: 93.0905532836914 169 | Z: -1.8055267333984375 170 | Focal Shape Fixed Size: false 171 | Focal Shape Size: 0.05000000074505806 172 | Invert Z Axis: false 173 | Name: Current View 174 | Near Clip Distance: 0.009999999776482582 175 | Pitch: 1.5697963237762451 176 | Target Frame: base_link 177 | Value: Orbit (rviz) 178 | Yaw: 4.203584671020508 179 | Saved: ~ 180 | Window Geometry: 181 | Displays: 182 | collapsed: false 183 | Height: 551 184 | Hide Left Dock: false 185 | Hide Right Dock: true 186 | Image: 187 | collapsed: false 188 | QMainWindow State: 000000ff00000000fd00000004000000000000016a000001ccfc020000000cfb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005d00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001b300000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003e00000178000000cb00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000a0049006d00610067006501000001bc0000004e0000001600fffffffb0000000a0049006d00610067006500000002f4000000ca0000000000000000fb0000000a0049006d00610067006500000002c8000000f60000000000000000fb0000000a0049006d00610067006501000002f4000000ca0000000000000000000000010000010f00000188fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003e00000188000000a500fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004d30000003efc0100000002fb0000000800540069006d00650000000000000004d30000026c00fffffffb0000000800540069006d0065010000000000000450000000000000000000000363000001cc00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000 189 | Selection: 190 | collapsed: false 191 | Time: 192 | collapsed: false 193 | Tool Properties: 194 | collapsed: false 195 | Views: 196 | collapsed: true 197 | Width: 1235 198 | X: 0 199 | Y: 0 200 | -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/slam_data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/hello_kitti_node.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-05 02:56:27 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | #include "lidar_localization/global_defination/global_defination.h" 12 | #include "glog/logging.h" 13 | 14 | // 15 | // TF tree: 16 | // 17 | #include "lidar_localization/subscriber/tf_listener.hpp" 18 | #include "lidar_localization/publisher/tf_broadcaster.hpp" 19 | 20 | // 21 | // subscribers: 22 | // 23 | #include "lidar_localization/subscriber/cloud_subscriber.hpp" 24 | #include "lidar_localization/subscriber/imu_subscriber.hpp" 25 | #include "lidar_localization/subscriber/gnss_subscriber.hpp" 26 | // 27 | // publishers: 28 | // 29 | #include "lidar_localization/publisher/cloud_publisher.hpp" 30 | #include "lidar_localization/publisher/odometry_publisher.hpp" 31 | 32 | using namespace lidar_localization; 33 | 34 | void GetTransformIMUToMap( 35 | GNSSData &gnss_data, IMUData &imu_data, 36 | Eigen::Matrix4f &imu_to_map 37 | ) { 38 | // 39 | // init 40 | // 41 | gnss_data.UpdateXYZ(); 42 | // 43 | // a. set position: 44 | // 45 | imu_to_map(0,3) = gnss_data.local_E; 46 | imu_to_map(1,3) = gnss_data.local_N; 47 | imu_to_map(2,3) = gnss_data.local_U; 48 | // 49 | // b. set orientation: 50 | // 51 | imu_to_map.block<3,3>(0,0) = imu_data.GetOrientationMatrix(); 52 | } 53 | 54 | 55 | int main( 56 | int argc, 57 | char *argv[] 58 | ) { 59 | google::InitGoogleLogging(argv[0]); 60 | 61 | FLAGS_log_dir = WORK_SPACE_PATH + "/Log"; 62 | FLAGS_alsologtostderr = 1; 63 | 64 | ros::init(argc, argv, "hello_kitti_node"); 65 | ros::NodeHandle nh; 66 | 67 | // 68 | // get TF: 69 | // 70 | std::shared_ptr lidar_to_imu_tf_sub_ptr = std::make_shared(nh, "/imu_link", "/velo_link"); 71 | std::shared_ptr lidar_to_map_tf_pub_ptr = std::make_shared("/map", "/velo_link"); 72 | 73 | // 74 | // subscribe to topics: 75 | // 76 | std::shared_ptr cloud_sub_ptr = std::make_shared(nh, "/kitti/velo/pointcloud", 100000); 77 | std::shared_ptr imu_sub_ptr = std::make_shared(nh, "/kitti/oxts/imu", 1000000); 78 | std::shared_ptr gnss_sub_ptr = std::make_shared(nh, "/kitti/oxts/gps/fix", 1000000); 79 | 80 | // 81 | // register publishers: 82 | // 83 | std::shared_ptr cloud_pub_ptr = std::make_shared(nh, "current_scan", 100, "/map"); 84 | std::shared_ptr odom_pub_ptr = std::make_shared(nh, "lidar_odom", "/map", "velo_link", 100); 85 | 86 | std::deque cloud_data_buff; 87 | std::deque imu_data_buff; 88 | std::deque gnss_data_buff; 89 | 90 | Eigen::Matrix4f lidar_to_imu = Eigen::Matrix4f::Identity(); 91 | Eigen::Matrix4f imu_to_map = Eigen::Matrix4f::Identity(); 92 | 93 | bool transform_received = false; 94 | bool gnss_origin_position_inited = false; 95 | 96 | ros::Rate rate(100); 97 | 98 | while (ros::ok()) { 99 | ros::spinOnce(); 100 | 101 | cloud_sub_ptr->ParseData(cloud_data_buff); 102 | imu_sub_ptr->ParseData(imu_data_buff); 103 | gnss_sub_ptr->ParseData(gnss_data_buff); 104 | 105 | if (!transform_received) { 106 | if (lidar_to_imu_tf_sub_ptr->LookupData(lidar_to_imu)) { 107 | transform_received = true; 108 | } 109 | } else { 110 | while ( 111 | !cloud_data_buff.empty() && 112 | !imu_data_buff.empty() && 113 | !gnss_data_buff.empty() 114 | ) { 115 | CloudData cloud_data = cloud_data_buff.front(); 116 | IMUData imu_data = imu_data_buff.front(); 117 | GNSSData gnss_data = gnss_data_buff.front(); 118 | 119 | double d_time = cloud_data.time - imu_data.time; 120 | 121 | if (d_time < -0.05) { 122 | cloud_data_buff.pop_front(); 123 | } else if (d_time > 0.05) { 124 | imu_data_buff.pop_front(); 125 | gnss_data_buff.pop_front(); 126 | } else { 127 | cloud_data_buff.pop_front(); 128 | imu_data_buff.pop_front(); 129 | gnss_data_buff.pop_front(); 130 | 131 | if (!gnss_origin_position_inited) { 132 | gnss_data.InitOriginPosition(); 133 | gnss_origin_position_inited = true; 134 | } 135 | 136 | GetTransformIMUToMap( 137 | gnss_data, imu_data, 138 | imu_to_map 139 | ); 140 | 141 | // lidar pose in map frame: 142 | Eigen::Matrix4f lidar_odometry = imu_to_map * lidar_to_imu; 143 | // lidar measurement in map frame: 144 | pcl::transformPointCloud( 145 | *cloud_data.cloud_ptr, *cloud_data.cloud_ptr, 146 | lidar_odometry 147 | ); 148 | 149 | cloud_pub_ptr->Publish(cloud_data.cloud_ptr); 150 | odom_pub_ptr->Publish(lidar_odometry); 151 | 152 | // 153 | // publish TF: lidar -> map 154 | // 155 | lidar_to_map_tf_pub_ptr->SendTransform(lidar_odometry, cloud_data.time); 156 | } 157 | } 158 | } 159 | 160 | rate.sleep(); 161 | } 162 | 163 | return EXIT_SUCCESS; 164 | } -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/publisher/cloud_publisher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 通过ros发布点云 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-05 02:27:30 5 | */ 6 | 7 | #include "lidar_localization/publisher/cloud_publisher.hpp" 8 | 9 | namespace lidar_localization { 10 | CloudPublisher::CloudPublisher(ros::NodeHandle& nh, 11 | std::string topic_name, 12 | size_t buff_size, 13 | std::string frame_id) 14 | :nh_(nh), frame_id_(frame_id) { 15 | publisher_ = nh_.advertise(topic_name, buff_size); 16 | } 17 | 18 | void CloudPublisher::Publish(CloudData::CLOUD_PTR cloud_ptr_input) { 19 | sensor_msgs::PointCloud2Ptr cloud_ptr_output(new sensor_msgs::PointCloud2()); 20 | pcl::toROSMsg(*cloud_ptr_input, *cloud_ptr_output); 21 | cloud_ptr_output->header.stamp = ros::Time::now(); 22 | cloud_ptr_output->header.frame_id = frame_id_; 23 | publisher_.publish(*cloud_ptr_output); 24 | } 25 | 26 | } // namespace data_output -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/publisher/odometry_publisher.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 里程计信息发布 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-06 21:11:44 5 | */ 6 | #include "lidar_localization/publisher/odometry_publisher.hpp" 7 | 8 | namespace lidar_localization { 9 | OdometryPublisher::OdometryPublisher(ros::NodeHandle& nh, 10 | std::string topic_name, 11 | std::string base_frame_id, 12 | std::string child_frame_id, 13 | int buff_size) 14 | :nh_(nh) { 15 | 16 | publisher_ = nh_.advertise(topic_name, buff_size); 17 | odometry_.header.frame_id = base_frame_id; 18 | odometry_.child_frame_id = child_frame_id; 19 | } 20 | 21 | void OdometryPublisher::Publish(const Eigen::Matrix4f& transform_matrix) { 22 | odometry_.header.stamp = ros::Time::now(); 23 | 24 | //set the position 25 | odometry_.pose.pose.position.x = transform_matrix(0,3); 26 | odometry_.pose.pose.position.y = transform_matrix(1,3); 27 | odometry_.pose.pose.position.z = transform_matrix(2,3); 28 | 29 | Eigen::Quaternionf q; 30 | q = transform_matrix.block<3,3>(0,0); 31 | odometry_.pose.pose.orientation.x = q.x(); 32 | odometry_.pose.pose.orientation.y = q.y(); 33 | odometry_.pose.pose.orientation.z = q.z(); 34 | odometry_.pose.pose.orientation.w = q.w(); 35 | 36 | publisher_.publish(odometry_); 37 | } 38 | } -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/publisher/tf_broadcaster.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: TF broadcaster 3 | * @Author: Ren Qian 4 | * @Date: 2020-03-05 15:23:26 5 | */ 6 | 7 | #include "lidar_localization/publisher/tf_broadcaster.hpp" 8 | 9 | namespace lidar_localization { 10 | 11 | TFBroadCaster::TFBroadCaster(std::string frame_id, std::string child_frame_id) { 12 | transform_.frame_id_ = frame_id; 13 | transform_.child_frame_id_ = child_frame_id; 14 | } 15 | 16 | void TFBroadCaster::SendTransform(Eigen::Matrix4f pose, double time) { 17 | Eigen::Quaternionf q(pose.block<3,3>(0,0)); 18 | ros::Time ros_time(time); 19 | transform_.stamp_ = ros_time; 20 | transform_.setRotation(tf::Quaternion(q.x(), q.y(), q.z(), q.w())); 21 | transform_.setOrigin(tf::Vector3(pose(0,3), pose(1,3), pose(2,3))); 22 | broadcaster_.sendTransform(transform_); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/sensor_data/gnss_data.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-06 20:42:23 5 | */ 6 | #include "lidar_localization/sensor_data/gnss_data.hpp" 7 | 8 | #include "glog/logging.h" 9 | 10 | //静态成员变量必须在类外初始化 11 | bool lidar_localization::GNSSData::origin_position_inited = false; 12 | GeographicLib::LocalCartesian lidar_localization::GNSSData::geo_converter; 13 | 14 | namespace lidar_localization { 15 | void GNSSData::InitOriginPosition() { 16 | geo_converter.Reset(latitude, longitude, altitude); 17 | origin_position_inited = true; 18 | } 19 | 20 | void GNSSData::UpdateXYZ() { 21 | if (!origin_position_inited) { 22 | LOG(WARNING) << "GeoConverter has not set origin position"; 23 | } 24 | geo_converter.Forward(latitude, longitude, altitude, local_E, local_N, local_U); 25 | } 26 | 27 | bool GNSSData::SyncData(std::deque& UnsyncedData, std::deque& SyncedData, double sync_time) { 28 | // 传感器数据按时间序列排列,在传感器数据中为同步的时间点找到合适的时间位置 29 | // 即找到与同步时间相邻的左右两个数据 30 | // 需要注意的是,如果左右相邻数据有一个离同步时间差值比较大,则说明数据有丢失,时间离得太远不适合做差值 31 | while (UnsyncedData.size() >= 2) { 32 | if (UnsyncedData.front().time > sync_time) 33 | return false; 34 | if (UnsyncedData.at(1).time < sync_time) { 35 | UnsyncedData.pop_front(); 36 | continue; 37 | } 38 | if (sync_time - UnsyncedData.front().time > 0.2) { 39 | UnsyncedData.pop_front(); 40 | return false; 41 | } 42 | if (UnsyncedData.at(1).time - sync_time > 0.2) { 43 | return false; 44 | } 45 | break; 46 | } 47 | if (UnsyncedData.size() < 2) 48 | return false; 49 | 50 | GNSSData front_data = UnsyncedData.at(0); 51 | GNSSData back_data = UnsyncedData.at(1); 52 | GNSSData synced_data; 53 | 54 | double front_scale = (back_data.time - sync_time) / (back_data.time - front_data.time); 55 | double back_scale = (sync_time - front_data.time) / (back_data.time - front_data.time); 56 | synced_data.time = sync_time; 57 | synced_data.status = back_data.status; 58 | synced_data.longitude = front_data.longitude * front_scale + back_data.longitude * back_scale; 59 | synced_data.latitude = front_data.latitude * front_scale + back_data.latitude * back_scale; 60 | synced_data.altitude = front_data.altitude * front_scale + back_data.altitude * back_scale; 61 | synced_data.local_E = front_data.local_E * front_scale + back_data.local_E * back_scale; 62 | synced_data.local_N = front_data.local_N * front_scale + back_data.local_N * back_scale; 63 | synced_data.local_U = front_data.local_U * front_scale + back_data.local_U * back_scale; 64 | 65 | SyncedData.push_back(synced_data); 66 | 67 | return true; 68 | } 69 | } -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/sensor_data/imu_data.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: imu data 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-23 22:20:41 5 | */ 6 | #include "lidar_localization/sensor_data/imu_data.hpp" 7 | 8 | #include 9 | #include "glog/logging.h" 10 | 11 | namespace lidar_localization { 12 | Eigen::Matrix3f IMUData::GetOrientationMatrix() { 13 | Eigen::Quaterniond q(orientation.w, orientation.x, orientation.y, orientation.z); 14 | Eigen::Matrix3f matrix = q.matrix().cast(); 15 | 16 | return matrix; 17 | } 18 | 19 | bool IMUData::SyncData(std::deque& UnsyncedData, std::deque& SyncedData, double sync_time) { 20 | // 传感器数据按时间序列排列,在传感器数据中为同步的时间点找到合适的时间位置 21 | // 即找到与同步时间相邻的左右两个数据 22 | // 需要注意的是,如果左右相邻数据有一个离同步时间差值比较大,则说明数据有丢失,时间离得太远不适合做差值 23 | while (UnsyncedData.size() >= 2) { 24 | // UnsyncedData.front().time should be <= sync_time: 25 | if (UnsyncedData.front().time > sync_time) 26 | return false; 27 | // sync_time should be <= UnsyncedData.at(1).time: 28 | if (UnsyncedData.at(1).time < sync_time) { 29 | UnsyncedData.pop_front(); 30 | continue; 31 | } 32 | 33 | // sync_time - UnsyncedData.front().time should be <= 0.2: 34 | if (sync_time - UnsyncedData.front().time > 0.2) { 35 | UnsyncedData.pop_front(); 36 | return false; 37 | } 38 | // UnsyncedData.at(1).time - sync_time should be <= 0.2 39 | if (UnsyncedData.at(1).time - sync_time > 0.2) { 40 | return false; 41 | } 42 | break; 43 | } 44 | if (UnsyncedData.size() < 2) 45 | return false; 46 | 47 | IMUData front_data = UnsyncedData.at(0); 48 | IMUData back_data = UnsyncedData.at(1); 49 | IMUData synced_data; 50 | 51 | double front_scale = (back_data.time - sync_time) / (back_data.time - front_data.time); 52 | double back_scale = (sync_time - front_data.time) / (back_data.time - front_data.time); 53 | synced_data.time = sync_time; 54 | synced_data.linear_acceleration.x = front_data.linear_acceleration.x * front_scale + back_data.linear_acceleration.x * back_scale; 55 | synced_data.linear_acceleration.y = front_data.linear_acceleration.y * front_scale + back_data.linear_acceleration.y * back_scale; 56 | synced_data.linear_acceleration.z = front_data.linear_acceleration.z * front_scale + back_data.linear_acceleration.z * back_scale; 57 | synced_data.angular_velocity.x = front_data.angular_velocity.x * front_scale + back_data.angular_velocity.x * back_scale; 58 | synced_data.angular_velocity.y = front_data.angular_velocity.y * front_scale + back_data.angular_velocity.y * back_scale; 59 | synced_data.angular_velocity.z = front_data.angular_velocity.z * front_scale + back_data.angular_velocity.z * back_scale; 60 | // 四元数插值有线性插值和球面插值,球面插值更准确,但是两个四元数差别不大是,二者精度相当 61 | // 由于是对相邻两时刻姿态插值,姿态差比较小,所以可以用线性插值 62 | synced_data.orientation.x = front_data.orientation.x * front_scale + back_data.orientation.x * back_scale; 63 | synced_data.orientation.y = front_data.orientation.y * front_scale + back_data.orientation.y * back_scale; 64 | synced_data.orientation.z = front_data.orientation.z * front_scale + back_data.orientation.z * back_scale; 65 | synced_data.orientation.w = front_data.orientation.w * front_scale + back_data.orientation.w * back_scale; 66 | // 线性插值之后要归一化 67 | synced_data.orientation.Normlize(); 68 | 69 | SyncedData.push_back(synced_data); 70 | 71 | return true; 72 | } 73 | } -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/subscriber/cloud_subscriber.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 订阅激光点云信息,并解析数据 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-05 02:27:30 5 | */ 6 | 7 | #include "lidar_localization/subscriber/cloud_subscriber.hpp" 8 | 9 | #include "glog/logging.h" 10 | 11 | namespace lidar_localization { 12 | CloudSubscriber::CloudSubscriber(ros::NodeHandle& nh, std::string topic_name, size_t buff_size) 13 | :nh_(nh) { 14 | subscriber_ = nh_.subscribe(topic_name, buff_size, &CloudSubscriber::msg_callback, this); 15 | } 16 | 17 | void CloudSubscriber::msg_callback(const sensor_msgs::PointCloud2::ConstPtr& cloud_msg_ptr) { 18 | CloudData cloud_data; 19 | cloud_data.time = cloud_msg_ptr->header.stamp.toSec(); 20 | pcl::fromROSMsg(*cloud_msg_ptr, *(cloud_data.cloud_ptr)); 21 | 22 | new_cloud_data_.push_back(cloud_data); 23 | } 24 | 25 | void CloudSubscriber::ParseData(std::deque& cloud_data_buff) { 26 | if (new_cloud_data_.size() > 0) { 27 | cloud_data_buff.insert(cloud_data_buff.end(), new_cloud_data_.begin(), new_cloud_data_.end()); 28 | new_cloud_data_.clear(); 29 | } 30 | } 31 | } // namespace data_input -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/subscriber/gnss_subscriber.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 3 | * @Author: Ren Qian 4 | * @Date: 2019-03-31 13:10:51 5 | */ 6 | #include "lidar_localization/subscriber/gnss_subscriber.hpp" 7 | 8 | #include "glog/logging.h" 9 | 10 | namespace lidar_localization { 11 | GNSSSubscriber::GNSSSubscriber(ros::NodeHandle& nh, std::string topic_name, size_t buff_size) 12 | :nh_(nh) { 13 | subscriber_ = nh_.subscribe(topic_name, buff_size, &GNSSSubscriber::msg_callback, this); 14 | } 15 | 16 | void GNSSSubscriber::msg_callback(const sensor_msgs::NavSatFixConstPtr& nav_sat_fix_ptr) { 17 | GNSSData gnss_data; 18 | gnss_data.time = nav_sat_fix_ptr->header.stamp.toSec(); 19 | gnss_data.latitude = nav_sat_fix_ptr->latitude; 20 | gnss_data.longitude = nav_sat_fix_ptr->longitude; 21 | gnss_data.altitude = nav_sat_fix_ptr->altitude; 22 | gnss_data.status = nav_sat_fix_ptr->status.status; 23 | gnss_data.service = nav_sat_fix_ptr->status.service; 24 | 25 | new_gnss_data_.push_back(gnss_data); 26 | } 27 | 28 | void GNSSSubscriber::ParseData(std::deque& gnss_data_buff) { 29 | if (new_gnss_data_.size() > 0) { 30 | gnss_data_buff.insert(gnss_data_buff.end(), new_gnss_data_.begin(), new_gnss_data_.end()); 31 | new_gnss_data_.clear(); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/subscriber/imu_subscriber.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: 订阅imu数据 3 | * @Author: Ren Qian 4 | * @Date: 2019-06-14 16:44:18 5 | */ 6 | #include "lidar_localization/subscriber/imu_subscriber.hpp" 7 | 8 | #include "glog/logging.h" 9 | 10 | namespace lidar_localization{ 11 | IMUSubscriber::IMUSubscriber(ros::NodeHandle& nh, std::string topic_name, size_t buff_size) 12 | :nh_(nh) { 13 | subscriber_ = nh_.subscribe(topic_name, buff_size, &IMUSubscriber::msg_callback, this); 14 | } 15 | 16 | void IMUSubscriber::msg_callback(const sensor_msgs::ImuConstPtr& imu_msg_ptr) { 17 | IMUData imu_data; 18 | imu_data.time = imu_msg_ptr->header.stamp.toSec(); 19 | 20 | imu_data.linear_acceleration.x = imu_msg_ptr->linear_acceleration.x; 21 | imu_data.linear_acceleration.y = imu_msg_ptr->linear_acceleration.y; 22 | imu_data.linear_acceleration.z = imu_msg_ptr->linear_acceleration.z; 23 | 24 | imu_data.angular_velocity.x = imu_msg_ptr->angular_velocity.x; 25 | imu_data.angular_velocity.y = imu_msg_ptr->angular_velocity.y; 26 | imu_data.angular_velocity.z = imu_msg_ptr->angular_velocity.z; 27 | 28 | imu_data.orientation.x = imu_msg_ptr->orientation.x; 29 | imu_data.orientation.y = imu_msg_ptr->orientation.y; 30 | imu_data.orientation.z = imu_msg_ptr->orientation.z; 31 | imu_data.orientation.w = imu_msg_ptr->orientation.w; 32 | 33 | new_imu_data_.push_back(imu_data); 34 | } 35 | 36 | void IMUSubscriber::ParseData(std::deque& imu_data_buff) { 37 | if (new_imu_data_.size() > 0) { 38 | imu_data_buff.insert(imu_data_buff.end(), new_imu_data_.begin(), new_imu_data_.end()); 39 | new_imu_data_.clear(); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /workspace/assignments/01-introduction/src/lidar_localization/src/subscriber/tf_lisener.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * @Description: TF listener 3 | * @Author: Ren Qian 4 | * @Date: 2020-02-06 16:10:31 5 | */ 6 | 7 | #include "lidar_localization/subscriber/tf_listener.hpp" 8 | 9 | #include 10 | 11 | namespace lidar_localization { 12 | TFListener::TFListener(ros::NodeHandle& nh, std::string base_frame_id, std::string child_frame_id) 13 | :nh_(nh), base_frame_id_(base_frame_id), child_frame_id_(child_frame_id) { 14 | } 15 | 16 | bool TFListener::LookupData(Eigen::Matrix4f& transform_matrix) { 17 | try { 18 | tf::StampedTransform transform; 19 | listener_.lookupTransform(base_frame_id_, child_frame_id_, ros::Time(0), transform); 20 | TransformToMatrix(transform, transform_matrix); 21 | return true; 22 | } catch (tf::TransformException &ex) { 23 | return false; 24 | } 25 | } 26 | 27 | bool TFListener::TransformToMatrix(const tf::StampedTransform& transform, Eigen::Matrix4f& transform_matrix) { 28 | Eigen::Translation3f tl_btol(transform.getOrigin().getX(), transform.getOrigin().getY(), transform.getOrigin().getZ()); 29 | 30 | double roll, pitch, yaw; 31 | tf::Matrix3x3(transform.getRotation()).getEulerYPR(yaw, pitch, roll); 32 | Eigen::AngleAxisf rot_x_btol(roll, Eigen::Vector3f::UnitX()); 33 | Eigen::AngleAxisf rot_y_btol(pitch, Eigen::Vector3f::UnitY()); 34 | Eigen::AngleAxisf rot_z_btol(yaw, Eigen::Vector3f::UnitZ()); 35 | 36 | // 此矩阵为 child_frame_id 到 base_frame_id 的转换矩阵 37 | transform_matrix = (tl_btol * rot_z_btol * rot_y_btol * rot_x_btol).matrix(); 38 | 39 | return true; 40 | } 41 | } -------------------------------------------------------------------------------- /workspace/assignments/README.md: -------------------------------------------------------------------------------- 1 | # 编程作业 2 | 3 | 章节作业开发环境 4 | 5 | --- -------------------------------------------------------------------------------- /workspace/data/kitti/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | !README.md -------------------------------------------------------------------------------- /workspace/data/kitti/README.md: -------------------------------------------------------------------------------- 1 | # KITTI Dataset 2 | 3 | KITTI ROS Bags存放路径 4 | 5 | --- 6 | 7 | ## 获取数据 8 | 9 | 初次使用时, 请点击下述链接, 将课程配套数据下载至**当前路径**, 即: 10 | 11 | * 相对于Repo根目录的workspace/data/kitti 12 | 13 | 这样, 数据便可在Docker环境的/workspace/data下直接访问. 14 | 15 | 可供选择的网盘链接如下: 16 | 17 | * [腾讯云下载地址](https://share.weiyun.com/GxqcTaE2) 18 | 19 | * 百度云下载地址 20 | 21 | * **下载链接** https://pan.baidu.com/s/1gpO2Ssa12GoQTbYAseSFNA 22 | * **提取码** cau9 23 | --------------------------------------------------------------------------------