1 | std::string s("Hello"); |
back_inserter属于插入迭代器,有三种插入迭代器(back_inserter,inserter,front_inserter),插入迭代器是指被绑定在一个容器上,可用来向容器插入元素的迭代器。 back_inserter是创建一个使用push_back的迭代器1
2
3vector<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。
有次我如此使用:1
2
3tf2_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"
代表:图漾, Astro Dabai, ZED
代表: OAK, 奥比中光, Realsense
按照指导书进行配置即可,需要注意的只有noetic的配置有些不同。

我模仿驱动里的demo-api,写了一个程序获得SLAM位姿,跟xvisio_viewer的效果相同。发布的话题vslam_pose的频率足够满足需求。
xvisio相机启动时,必须面对有特征的环境,否则之后会一直不能获取SLAM信息。在相机移动过程中也要尽量面对有特征环境,如果面对纯色的环境,会失败,和遮挡镜头是一样的。 但即使这样,偶尔也有失败的情况。
反复测试后,感觉这个相机不适合我的需求,只好放弃了。
我直接修改了奥比相机的驱动,从源头直通滤波、体素滤波、统计滤波。否则比较远的点云(比如3m以上)乱七八糟还极不稳定,根本不需要。另外两个方向的点云,坐标值比较大的时候,也极不稳定,没有使用的必要。
原始点云256000个点,滤波后,最多20000+个点。
装在机器人上,移动时,偶尔收不到点云数据
比D435增加一个750nm 近红外滤光片(厚度0.5mm, CLAREX NIR-75N),一个mask。 红外滤光片(IR pass filter)装在相机的前端,两个孔对应红外发射和RGB相机。减少了光反射和阳光引起的深度噪声,它可传播近红外光和吸收可见光。

我做了很多试验,发现D435f确实好很多,不仅在阳光和有光反射情况下,连普通环境也减少了空洞现象。
D435f的射程收到红外发射器的限制,校正可能需要额外的红外补光。
考虑自己买750nm的滤光片装在D435上,淘宝发现很小的一块要80,真是贵。
参考: realsense-d435f
肇观电子的N1(价格 350)和M1(价格 750)相机
M1 主动双目,空洞率少。 N1 被动双目,空洞太多,想使用深度图和点云就不必考虑了。


从本机连接到远程机,发起SSH连接,执行命令cd ~/Downloads;ls1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 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
7spawn 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一行之后为命令执行的结果,一直没法实现换行,不太完美
编译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)
头文件: #include <algorithm>
返回范围 [first, last) 中满足特定判别标准的首个元素:
find: 搜索等于 value 的元素
find_if: 根据指定的查找规则,在指定区域内查找第一个符合该函数要求(使函数返回 true)的元素。如果查找成功,该迭代器指向的是查找到的那个元素;反之,如果查找失败,该迭代器的指向和 last 迭代器相同
find_if_not: 与find_if相反
示例代码:1
2
3
4
5
6
7
8
9
10
11std::vector<int> score{ 10, 20, 30, 40 };
auto it_1 = std::find(score.begin(), score.end(), 30 );
if(it_1 != score.end() )
qDebug()<< "found !";
else qDebug()<< "no found !";
auto it_2 = std::find_if(score.begin(), score.end(), [](int& m){return m>20;} );
if(it_2 != score.end() )
qDebug()<< "found: " << *it_2;
else qDebug()<< "no found !";
原型template <class BidirectionalIterator>
BidirectionalIterator prev (BidirectionalIterator it, typename iterator_traits<BidirectionalIterator>::difference_type n = 1);
该函数会返回一个距离 it 迭代器 n 个元素的新迭代器。当 n 为正数时,其返回的迭代器将位于 it 左侧;反之,当 n 为负数时,其返回的迭代器位于 it 右侧。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
using namespace std;
int main() {
//创建并初始化一个 list 容器
std::list<int> mylist{ 1,2,3,4,5 };
std::list<int>::iterator it = mylist.end();
//获取一个距离 it 迭代器 2 个元素的迭代器,由于 2 为正数,newit 位于 it 左侧
auto newit = prev(it, 2);
cout << "prev(it, 2) = " << *newit << endl; // 4
//n为负数,newit 位于 it 右侧
it = mylist.begin();
newit = prev(it, -2);
cout << "prev(it, -2) = " << *newit; // 3
return 0;
}prev() 函数自身不会检验新迭代器的指向是否合理,需要我们自己来保证其合理性。
next()函数和prev()函数恰好相反
如果没有ninja,在使用时会报错: CMake was unable to find a build program corresponding to "Ninja". CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool.
ninja需要依赖于re2c,否则编译是会报错,re2c是一款语法分析器,官网地址是:http://re2c.org/
下载页面的安装说明都在: http://re2c.org/install/install.html, 这里直接从源码安装最新版本
安装re2c:1
2
3
4
5git clone https://github.com/skvadrik/re2c
cd re2c
./autogen.sh
./configure make
make install
可以从ninja的github仓库切换到release分支或者使用git下载:1
2git clone https://github.com/ninja-build/ninja.git
cd ninja
采用python的安装方式1
./configure.py --bootstrap
等待完成即可
ninja比较精简,只需要一个可执行文件即可,现在可以做软链或者复制到/usr/bin下面就可以直接调用了1
cp ninja /usr/bin/