配置万集716雷达

万集的716雷达马上会停产。
万集WLR-716

记录一下配置的过程。雷达只有网口和24V的电源线,红正黑负。

windows上的上位机配置,按照说明书进行就可以了,没什么复杂的。只看ubuntu的配置过程

插上网线后,找到有线网络的参数。这是ubuntu的参数,不是雷达的
有线网络显示的参数
到IPV4页面进行配置,MAC地址也要配置,可能填192.168.0.4会ping不同雷达,那就换别的IP试试

ping通雷达后,启动launch应该没问题了
launch成功启动


强度信息



加入反光板后
此时的强度信息

测试发现,距离反光板小于1.8m时,强度都是最大值1500。之后距离增大,强度值减小,当距离4.4m时,强度值仍在900以上。 看来雷达对高反物体还是很敏感的。

网上声称万集718的角分辨率降到0.25°,对不锈钢面、货架腿的识别效果极好,能达到30mm精度。但是我查万集的官网发现WLR-718角分辨率还是0.33°,不知这说的是不是WLR-718 Mini,如果是真的,那么对拖尾现象会避免很好。 对强光、雨雾、对射干扰,能滤除干扰回波,测量很可靠。


transform和back_inserter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
std::string s("Hello");
std::string f;

// 前两个参数是变换的范围,第三个是变换的起始位置
// 第四个参数为lambda表达式,变换的规则
std::transform(s.begin(), s.end(), s.begin(),
[](unsigned char c) { return std::toupper(c); });
std::cout <<"after transform, s: "<< s << std::endl; // HELLO

std::transform( s.begin(), s.end(), std::back_inserter(f),
[](unsigned char c) { return std::tolower(c); } );
std::cout << "after transform, f: " << f << std::endl; // hello

std::copy( s.begin(), s.end(), std::back_inserter(f) );
std::cout << "after copy, f: " << f << std::endl; // helloHELLO

back_inserter属于插入迭代器,有三种插入迭代器(back_inserter,inserter,front_inserter),插入迭代器是指被绑定在一个容器上,可用来向容器插入元素的迭代器。 back_inserter是创建一个使用push_back的迭代器

1
2
3
vector<int> v={1,2,3,4,5,6};
vector<int> s;
copy(v.begin(), v.end(), back_inserter(s) ); // s: 123456

追加数据比较适合这种copy+back_inserter的做法。如果把新数据转为string,再用string的+运算符,这就太复杂了。数据很有可能是不以'\0'结尾,这样的话将出现严重bug。


tf2的学习(二)

有次我如此使用:

1
2
3
tf2_ros::Buffer buffer_;
tf2_ros::TransformListener listener(buffer_);
buffer_.transform(in_pose, out_pose, frame, transform_duration_);

结果报错: Exception in transformPose: “map” passed to lookupTransform argument source_frame does not exist

结果发现还是这个问题,我的用法其实相似,最好是把 buffer_listener都作为成员变量(指针),在构造函数里初始化listenner: listener = new tf2_ros::TransformListener(buffer_);, transform函数的使用就比较自由了

问题

使用tf2_ros::Buffer.transform()tf2_ros::Buffer.lookupTransform() 导致 “undefined reference” errors

解决: #include "tf2_geometry_msgs/tf2_geometry_msgs.h"

参考:


文本操作和读写文件

对字符串根据字符进行分段

1
2
3
4
5
6
7
8
9
vector<std::string> params;
std::string file = "123.45.abc.0";
std::istringstream param_stream(file);
std::string param;
while(getline(param_stream, param, '.'))
{
cout << param <<endl;
params.push_back(param);
}

运行结果:

1
2
3
4
123
45
abc
0

读Excel文件

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
45
46
bool readCSVInput(int N, vector<double> &input_points_x, vector<double> &input_points_y, vector<double> &anchor_points_x, vector<double> &anchor_points_y)
{
ifstream readCSV("/home/user/data.csv", ios::in);
int lineNum = 0;
string lineString;
vector<vector<string>> stringArray;
cout << endl;
while (getline(readCSV, lineString) )
{
//cout << lineString << endl;
if (lineNum > 0)
{
stringstream ss(lineString);
string s;
vector<string> oneLineStrings;
while (getline(ss, s, ',') )
oneLineStrings.push_back(s);
if (oneLineStrings.size() != 5)
{
cout << "ERROR:oneLineStrings.size() != 5" << endl;
return false;
}
else
{
input_points_x.push_back(std::stod(oneLineStrings[1]));
input_points_y.push_back(std::stod(oneLineStrings[2]));
anchor_points_x.push_back(std::stod(oneLineStrings[3]));
anchor_points_y.push_back(std::stod(oneLineStrings[4]));
}
}
lineNum++;
}
if (N == input_points_x.size())
{
return true;
}
else
{
input_points_x.clear();
input_points_y.clear();
anchor_points_x.clear();
anchor_points_y.clear();
cout << "ERROR:N == input_points_x.size()" << endl;
return false;
}
}

使用多个相机的记录

Xvisio相机

按照指导书进行配置即可,需要注意的只有noetic的配置有些不同。
启动驱动

在xvisio_viewer查看SLAM的信息
我模仿驱动里的demo-api,写了一个程序获得SLAM位姿,跟xvisio_viewer的效果相同。发布的话题vslam_pose的频率足够满足需求。

xvisio相机启动时,必须面对有特征的环境,否则之后会一直不能获取SLAM信息。在相机移动过程中也要尽量面对有特征环境,如果面对纯色的环境,会失败,和遮挡镜头是一样的。 但即使这样,偶尔也有失败的情况。

反复测试后,感觉这个相机不适合我的需求,只好放弃了。

奥比中光-大白相机

我直接修改了奥比相机的驱动,从源头直通滤波、体素滤波、统计滤波。否则比较远的点云(比如3m以上)乱七八糟还极不稳定,根本不需要。另外两个方向的点云,坐标值比较大的时候,也极不稳定,没有使用的必要。

原始点云256000个点,滤波后,最多20000+个点。

装在机器人上,移动时,偶尔收不到点云数据

realsense D435f

比D435增加一个750nm 近红外滤光片(厚度0.5mm, CLAREX NIR-75N),一个mask。 红外滤光片(IR pass filter)装在相机的前端,两个孔对应红外发射和RGB相机。减少了光反射和阳光引起的深度噪声,它可传播近红外光和吸收可见光。

D435 和 D435f的对比
我做了很多试验,发现D435f确实好很多,不仅在阳光和有光反射情况下,连普通环境也减少了空洞现象。

D435f的射程收到红外发射器的限制,校正可能需要额外的红外补光。

考虑自己买750nm的滤光片装在D435上,淘宝发现很小的一块要80,真是贵。

参考: realsense-d435f


肇观电子的N1(价格 350)和M1(价格 750)相机

M1 主动双目,空洞率少。 N1 被动双目,空洞太多,想使用深度图和点云就不必考虑了。


mipi转USB


雷达的拖尾现象和处理
abstract Welcome to my blog, enter password to read.
Read more
ssh自动登录远程机和expect的使用

从本机连接到远程机,发起SSH连接,执行命令cd ~/Downloads;ls

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash

# router parameters
ROUTER_USER="xiaoqiang"
ROUTER_HOST="192.168.0.110"
ROUTER_PASSWORD="1"
ROUTER_PORT="22" # default

# start except
expect <<-EOF
set timeout -1
spawn ssh $ROUTER_USER@$ROUTER_HOST -p $ROUTER_PORT -o StrictHostKeyChecking=no -C "cd ~/Downloads;ls"
expect "*password:"
send "$ROUTER_PASSWORD\n\r\n"
expect eof;
EOF

首次远程连接时,会提示公钥确认,远程IP改变时,会提示公钥不一致,这种情况有时非常烦人。对于自动化任务,我们希望跳过公钥确认,修改/etc/ssh/ssh_config,加入:
1
StrictHostKeyChecking no

或者在命令行中使用-o参数: ssh -o StrictHostKeyChecking=no

运行结果:

1
2
3
4
5
6
7
spawn ssh xiaoqiang@192.168.0.110 -p 22 -o StrictHostKeyChecking=no -C cd ~/Downloads;ls
xiaoqiang@192.168.0.110's password:
c-ares-1.17.0.tar.gz
cd1folder.zsh
CursorTheme
darcula.css
g2o_curve_fitting

在password一行之后为命令执行的结果,一直没法实现换行,不太完美


修改roslaunch源码
abstract Welcome to my blog, enter password to read.
Read more
编译链接 ${catkin_LIBRARIES} 的问题

编译xvisio相机驱动时,遇到了这样的错误

显然是ddynamic_reconfigure包的问题,于是安装对应的ROS包,但是问题依旧,真是奇怪

于是在cmake中使用MESSAGE(${catkin_LIBRARIES})看看链接的文件有什么问题,结果发现其他的ROS库都是链接到了ROS安装目录,比如 /opt/ros/noetic/lib/libcamera_info_manager.so/usr/lib/x86_64-linux-gnu/libtinyxml2.so。 唯独ddynamic_reconfigure链接到了我之前放的库文件: /home/user/catkin_ws/devel/lib/libddynamic_reconfigure.so

这真是太奇怪了,环境变量catkin_LIBRARIES是如何换到另一个so库文件的??? 于是我把ROS安装目录的libddynamic_reconfigure.so覆盖catkin_ws的so库文件,重新编译成功了,相机驱动可以正常运行。

但是这样其实没有解决根本问题,最后只好把target_link_libraries${catkin_LIBRARIES}换成一个个的so文件,在开头要LINK_DIRECTORIES(/opt/ros/noetic/lib)


cartographer的杂项模块

detect_floors.cc

detect_floors.h定义了关于3D扫描楼层的数据结构。

1
2
3
4
5
6
7
8
9
10
struct Timespan {
common::Time start;
common::Time end;
};
Timespan表征扫描的时间范围。

struct Floor {
std::vector< Timespan> timespans;
double z; //z轴的中值
};

一个楼层对应多个扫描timespan:有可能重复的扫描多次,但只有一个高度z。

std::vector DetectFloors(const proto::Trajectory& trajectory); 使用启发式搜索寻找building的不同楼层的z值。

normal_estimation_2d.cc

用于计算TSDF地图中的点云法向量,可以不看。 normal_estimation_2d_test.cc是测试文件,但是没有在CMakeLists中设置 。