如何用top查看每个进程的线程

程序中创建的线程(也称为轻量级进程,LWP)会具有和程序的PID相同的“线程组ID”。各个线程会获得其自身的线程ID

列出由进程号为的进程创建的所有线程

1
ps -T -p <pid>

SID栏表示线程ID,而CMD栏则显示了线程名称

还可以通过htop查看单个进程的线程,它是一个基于ncurses的交互进程查看器。该程序允许你在树状视图中监控单个独立线程。

开启htop,然后按<F2>进入htop的设置菜单。选择“设置”栏下面的“显示选项”,然后开启“树状视图”和“显示自定义线程名”选项。按<F10>退出设置。


设置python使用的版本
  1. 检查系统上可用的Python版本
1
2
$ ls /usr/bin/python*
/usr/bin/python2 /usr/bin/python2.7 /usr/bin/python3 /usr/bin/python3.8

查看是否配置了Python替代方案。

1
2
$ sudo update-alternatives --list python
update-alternatives: error: no alternatives for python

  1. 设置替代版本

对于本例,我们将设置两个Python替代:Python2和Python3。

1
2
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 1
$ sudo update-alternatives --install /usr/bin/python python /usr/bin/python3 2

确认两个备选方案都可以使用:

1
2
3
$ sudo update-alternatives --list python
/usr/bin/python2
/usr/bin/python3

选择可选的Python版本

1
2
3
4
5
6
7
8
$ sudo update-alternatives --config python
There are 2 choices for the alternative python (providing /usr/bin/python).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/bin/python3 2 auto mode
1 /usr/bin/python2 1 manual mode
2 /usr/bin/python3 2 manual mode
Press to keep the current choice[*], or type selection number: 1

输入您的选择。在本例中,选择1来选择python2

检查你的python版本:

1
2
$ python -V
Python 2.7.18rc1


move_base的缺陷

TEB避障的实际情况
无论传感器是雷达还是相机,都只能看到障碍物的一部分。如果障碍物比较大,而目标点在障碍物内(我们知道,机器人不知道),机器人会绕过它看到的障碍部分,前往目标点,然后它又看到障碍,于是接着绕行,这样会绕很久。目前只能设置参数planner_patience,绕的时间太长时,进行Abort

向move_base发布目标的频率太高,会出错

写一个loop程序,高频率循环发两个目标点,连C++程序都不用,写bash脚本即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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
#!/bin/bash

# 每隔1秒就发布下一个目标点
while true; do

rostopic pub /move_base_simple/goal geometry_msgs/PoseStamped "header:
seq: 0
stamp:
secs: 0
nsecs: 0
frame_id: 'map'
pose:
position:
x: 20
y: 7
z: 0.0
orientation:
x: 0.0
y: 0.0
z: 1
w: 0" & sleep 1 && kill -2 $!

# -2 是用信号量表示的 $!是子进程号 相当于执行ctrl+C

rostopic pub /move_base_simple/goal geometry_msgs/PoseStamped "header:
seq: 0
stamp:
secs: 0
nsecs: 0
frame_id: 'map'
pose:
position:
x: 24
y: 7
z: 0.0
orientation:
x: 0.0
y: 0.0
z: 0
w: 1" & sleep 1 && kill -2 $!

sleep 1
echo " ---------- start next loop ---------- "
done

sleep 1 && kill -2 $!是关键,sleep 1秒就杀死进程。 如果没有这句,机器人执行第一次导航时,必须等待Ctrl+C才能进入下一次导航

经过测试,向move_base发布目标点的频率如果太高,会报错,最快为0.6秒一次。 但是关掉rviz后,可达到0.5秒一次,可见优化程序会有效。

init.py的2140行
rospy client.py 251行
这里就涉及ROS源码了,想彻底优化就得着手ROS源码了,但是感觉没有必要。


Livox-MID360

旋转式的雷达寿命短,难过车规。 Livox雷达寿命更长,符合车规

按照说明书获得雷达和电脑应设置的静态IP。说明书指出可以只连接电源线,红正黑负。直流12V

可以去Livox的官网下载LivoxViewer2_Ubuntu_v2.3.0,配置很简单。运行LivoxViewer2.sh即可

先安装Livox-SDK2,然后安装livox_ros_driver2

修改MID360_config.jsoncmd_data_ip改为电脑的静态IP,把lidar_configs里的ip改为雷达IP。 然后运行roslaunch livox_ros_driver2 rviz_MID360.launch就可以看到结果了。

参考: 配置过程


公司机器人碰撞机制的实现
Welcome to my blog, enter password to read.
Read more
如何判断机器人出了地图
Welcome to my blog, enter password to read.
Read more
如何判断到达弓字终点
Welcome to my blog, enter password to read.
Read more
如何精确追踪长直线
Welcome to my blog, enter password to read.
Read more
ROS自定义层(写法模仿静态层)加载时的阻塞问题
abstract Welcome to my blog, enter password to read.
Read more
GDB, Benchmark, perf, core dump

GDB

  • bt: 当前运行的堆栈列表
  • print: 输出或者修改指定变量或者表达式的值
  • info thread: 显示所有线程信息
  • info program: 来查看程序的是否在运行,进程号,被暂停的原因
  • run(简写r): 运行程序,当遇到断点后,程序会在断点处停止运行,等待用户输入下一步的命令。
  • continue(简写c): 继续执行,到下一个断点处(或运行结束)
  • next(简写n): 单步跟踪程序,当遇到函数调用时,直接调用,不进入此函数体;
  • step(简写s): 单步调试如果有函数调用,则进入函数;与命令n不同,n是不进入调用的函数的
  • until: 运行程序直到退出循环体; / until+行号: 运行至某行
  • finish: 运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息
  • list 函数名: 将显示“函数名”所在函数的源代码,如: list main

Benchmark

Benchmark是Goole的一个开源基准测试框架,主要用于比较不同代码实现的性能和效率。Benchmak提供了丰富的测试功能,包括时、统计和分析等,可以帮助开发人员优化程序的性能和效率。

  • 安装Benchmark

可以使用包管理器或者源代码安装Benchmark。安装sudo apt-get install libbenchmark-dev1

  • 编写测试用例

首先,我们需要编写一个简单的测试函数,用于对比不同实现的性能。以计算数组元素之和为例,我们可以编写以下函数.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <numeric>
#include <vector>
#include <benchmark/benchmark.h>

static void BM_accumulate(benchmark::State& state)
{
std::vector<int> vec(state.range(0));
std::iota(vec.begin(), vec.end(), 0);

for (auto _ : state) {
int sum = std::accumulate(vec.begin(), vec.end(), 0);
benchmark::DoNotOptimize(sum);
}
}

BENCHMARK(BM_accumulate)->Arg(100)->Arg(1000)->Arg(10000);

这个函数使用了Benchmark提供的 tate 对象,该对象可以帮助我们迭代多次测试,并记录每次测试的结果。在函数中,我们先使用std::vector 生成一个指定大小的数组,并用 std::iota 填数组元素。然后,我们使用 std::accumulate 计算数组元素之和,并调用benchmark::DoNotoptimize 来确保这个计算不会被优化掉,最后,我们使用 BENCHMARK 宏将这个函数注册为基准测试用例,并使用Arg 方法指定测试用例的参数。

  • 运行测试

编写测试用例后,我们可以使用 benchmark::RunSpecifiedBenchmarks 函数来运行所有注册的基准测试用例,并生成测试报告。代码如下:

1
2
3
4
5
int main(int argc, char** argv)
{
::benchmark::Initialize(&argc, argv);
::benchmark::RunSpecifiedBenchmarks();
}

运行后
1
2
3
4
5
6
7
8
9
10
11
12
13
Run on (8 X 2200 MHz CPU s)
CPU Caches:
L1 Data 32 KiB (x8)
L1 Instruction 32 KiB (x8)
L2 Unified 256 KiB (x8)
L3 Unified 8192 KiB (x1)
Load Average: 1.20, 1.33, 1.18
-------------------------------------------------------------------------
Benchmark Time CPU Iterations
-------------------------------------------------------------------------
BM_accumulate/100 208 ns 208 ns 3251616
BM_accumulate/1000 2236 ns 2236 ns 313125
BM_accumulate/10000 22563 ns 22561 ns 31189

这个报告显示了每个测试用例的执行时间、吞吐量和标准差,以及与其他测试的比较。同时,也会显示出每个测试函数的代码行数和CPU 循环数等重详细的信息。除了默认的报告格式外,Goodle Benchmak 还提供了其他输出格式,例如 JSON、CSV 和 console等可以使用相应的命令行选项进行设置。
Goocle Benchmak 是一个基于 C++ 的高性能基准测试库,可以对代码的运行时间、内存使用和 CPU 循环等方面进行准确的测量和分析,帮助开发者优化代码性能。使用 Google Benchmark,可以轻松编写测试用例,自定义测试参数和运行选项,并生成详细的测试报告,方便分析和比较测试结果。

perf

在Nano上安装perf,参考这里,我下载的页面是

先用ps aux找到进程的PID,再观察进程内各个函数的CPU使用情况:sudo perf top -p <pid>
分析cartographer_node 进程

记录采样结果,以供后续分析,加上-g会记录调用链:sudo perf record -g -p <pid>

在当前终端读取采样结果:sudo perf report,会自动读取perf.data

core dump

如果进程在运行期间发生奔溃,操作系统会为进程生成一个快照文件,这个文件就叫做 core dump。之后我们可以对 core dump 文件进行分析,弄清楚进程为什么会奔溃。默认情况下,Linux 不允许生成 core dump 文件。

  1. 如果执行ulimit -c的结果是0,说明还未开启。命令ulimit -c unlimited只能在当前终端生效,所以加入~/.bashrc
  1. 指定core dump文件的路径: 修改/etc/sysctl.conf,在最后添加 kernel.core_pattern=/home/user/coredump_%e_%p_%s_%t,命名格式为 命令名_PID_导致core的信号_UNIX时间cat /proc/sys/kernel/core_pattern可以查看设置的格式。

  2. 执行sysctl -p

  3. 遇到程序非正常阻塞不运行时,在另一个终端查看其PID,然后使用 kill -s SIGSEGV <pid>产生 core dump 文件,这样就可以快速重启程序,然后慢慢分析 core dump 文件。

成功生成core dump文件时,会提示`core dumped`
  1. 执行gdb ./exec /path/coredump_file,就可以回放core dump