目录
- 前言
- 数组类型在不同消息类型中的定义
- 在ROS消息中的定义
- 在C++中定义数组
- vector数组的一些常用操作
前言
ROS系统的一个显著优势就是分布式和灵活性,用户可以很方便自定义消息类型。在自动驾驶中,无论是传感器消息sensoe_msgs,还是导航消息nav_msgs等等几乎都离不开一个基本的结构:vector数组。尤其是在SLAM中,在处理雷达消息更是必不可少的操作。所以把vector理解透彻对于ROS开发还是非常重要的。
接下来的内容以C++语言为主,python语言是类似的,但是语法可能稍有不同。(PS:对于搞自动驾驶的同学,还是强烈推荐用C++开发,原因无他,C++快!!!在自动驾驶领域,处理速度是决定性的一个因素)
数组类型在不同消息类型中的定义
在ROS消息中的定义
ROS常用的消息分别是msg、srv、action,分别对应于topic话题、service服务、action动作三种通信模式。对于这三种数据类型,数组的定义格式都是一样的:
DateType[] name
举例:
msg消息sensor_msgs/LaserScan.msg
[std_msgs/Header] header
float32 angle_min
float32 angle_max
float32 angle_increment
float32 time_increment
float32 scan_time
float32 range_min
float32 range_max
float32[] ranges
float32[] intensities
这里ranges和intensities都是float32类型的数组
自定义srv消息
uint64 path_id #路径id
---
geometry_msgs/Pose2D[] path
geometry_msgs/Pose2D[] waypoints
自定义action消息
---
uint64 path_id #当前路径id
geometry_msgs/Pose2D[] path #所有路径点位姿,包括巡航点
geometry_msgs/Pose2D[] waypoints #巡航点位姿
bool success # 储存成功为true,否则为false
string message # error messages
---
uint64 path_id #当前路径id
geometry_msgs/Pose2D[] path_record #已经采样的路径点
geometry_msgs/Pose2D[] waypoints_record #已经采样的巡航点位姿
在C++中定义数组
使用它时需要包含头文件: #include
其构造函数为:
vector();
vector( size_type num, const TYPE &val );
vector( const vector &from );
vector( input_iterator start, input_iterator end );
举例:
vector a; //无参数 - 构造一个空的vector,
vector a(10); //定义了10个整型元素的向量(尖括号中为元素类型名,它可以是任何合法的数据类型),但没有给出初值,其值是不确定的。
vector a(10,1); //定义了10个整型元素的向量,且给出每个元素的初值为1
vector a(b); //用b向量来创建a向量,整体复制性赋值, 拷贝构造
vector v3=a ; //移动构造
vector a(b.begin(),b.begin+3); //定义了a值为b中第0个到第2个(共3个)元素
int b[7]={1,2,3,4,5,9,8};
vector a(b,b+6); //从数组中获得初值,b[0]~b[5]
vector数组的一些常用操作
基本操作
(1)a.assign(b.begin(), b.begin()+3); //b为向量,将b的0~2个元素构成的向量赋给a
(2)a.assign(4,2); //是a只含4个元素,且每个元素为2
(3)a.back(); //返回a的最后一个元素
(4)a.front(); //返回a的第一个元素
(5)a[i]; //返回a的第i个元素,当且仅当a[i]存在2013-12-07
(6)a.clear(); //清空a中的元素
(7)a.empty(); //判断a是否为空,空则返回ture,不空则返回false
(8)a.pop_back(); //删除a向量的最后一个元素
(9)a.erase(a.begin()+1, a.begin()+3); //删除a中第1个(从第0个算起)到第2个元素,也就是说删除的元素从a.begin()+1算起(包括它)一直到a.begin()+3(不包括它)
(10)a.push_back(5); //在a的最后一个向量后插入一个元素,其值为5
(11)a.insert(a.begin()+1, 5); //在a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4,插入元素后为1,5,2,3,4
(12)a.insert(a.begin()+1, 3,5); //在a的第1个元素(从第0个算起)的位置插入3个数,其值都为5
(13)a.insert(a.begin()+1,b+3, b+6); //b为数组,在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b+6),如b为1,2,3,4,5,9,8,插入元素后为1,4,5,9,2,3,4,5,9,8
(14)a.size(); //返回a中元素的个数;
(15)a.capacity(); //返回a在内存中总共可以容纳的元素个数
(16)a.resize(10); //将a的现有元素个数调至10个,多则删,少则补,其值随机
(17)a.resize(10, 2); //将a的现有元素个数调至10个,多则删,少则补,其值为2
(18)a.reserve(100); //将a的容量(capacity)扩充至100,也就是说现在测试a.capacity();的时候返回值是100.这种操作只有在需要给a添加大量数据的时候才显得有意义,因为这将避免内存多次容量扩充操作(当a的容量不足时电脑会自动扩容,当然这必然降低性能)
(19)a.swap(b); //b为向量,将a中的元素和b中的元素进行整体性交换
(20)a.begin(); // 返回指向容器第一个元素的迭代器
(21)a.end(); // 返回指向容器最后一个元素的迭代器
&#xff08;22&#xff09;a&#61;&#61;b; //b为向量&#xff0c;向量的比较操作还有!&#61;,>&#61;,<&#61;,>,<
(23) reverse(a.begin(),a.end()); //对a中的从a.begin()&#xff08;包括它&#xff09;到a.end()&#xff08;不包括它&#xff09;的元素倒置&#xff0c;但不排列&#xff0c;如a中元素为1,3,2,4,倒置后为4,2,3,1
&#xff08;24&#xff09;copy(a.begin(),a.end(),b.begin()&#43;1); //把a中的从a.begin()&#xff08;包括它&#xff09;到a.end()&#xff08;不包括它&#xff09;的元素复制到b中&#xff0c;从b.begin()&#43;1的位置&#xff08;包括它&#xff09;开 始复制&#xff0c;覆盖掉原有元素
求数组的最值
可以用max_element&#xff08;&#xff09;及min_element&#xff08;&#xff09;函数&#xff0c;二者返回的都是迭代器或指针。
需要加入头文件&#xff1a;#include
1.求数组的最大值或最小值
1&#xff09;vector容器
vector v;
最大值&#xff1a;int maxValue &#61; *max_element(v.begin(),v.end());
最小值&#xff1a;int minValue &#61; *min_element(v.begin(),v.end());
2&#xff09;普通数组
a[]&#61;{1,2,3,4,5,6};
最大值&#xff1a;int maxValue &#61; *max_element(a,a&#43;6);
最小值&#xff1a;int minValue &#61; *min_element(a,a&#43;6);
2.求数组最大值最小值对应的下标
1&#xff09;vector容器
vector v;
最大值下标&#xff1a;int maxPosition &#61; max_element(v.begin(),v.end()) - v.begin();
最小值下标&#xff1a;int minPosition &#61; min_element(v.begin(),v.end()) - v.begin();
2&#xff09;普通数组
最大值下标&#xff1a;int maxPosition &#61; max_element(a,a&#43;6) - a;
最小值下标&#xff1a;int minPosition &#61; min_element(a,a&#43;6) - a;
注意&#xff1a;返回的是第一个最大&#xff08;小&#xff09;元素的位置。
遍历数组
1.
struct Point
{
double x;
double y;
Point()
{
x &#61; 0;
y &#61; 0;
}
};
vector m_testPoint;
//第一种遍历方式&#xff0c;下标
cout <<"第一种遍历方式&#xff0c;下标访问" < for (int i &#61; 0; i {
cout < }
//第二种遍历方式&#xff0c;迭代器
cout <<"第二种遍历方式&#xff0c;迭代器访问" < for (vector::iterator iter &#61; m_testPoint.begin(); iter !&#61; m_testPoint.end(); iter&#43;&#43;)
{
cout <<(*iter).x <<" " <<(*iter).y < }
//第三种遍历方式&#xff0c;auto关键字
cout <<"C&#43;&#43;11,第三种遍历方式&#xff0c;auto关键字" < for (auto iter &#61; m_testPoint.begin(); iter !&#61; m_testPoint.end(); iter&#43;&#43;)
{
cout <<(*iter).x <<" " <<(*iter).y < }
//第四种遍历方式&#xff0c;auto关键字的另一种方式
cout <<"C&#43;&#43;11,第四种遍历方式&#xff0c;auto关键字" < for (auto i : m_testPoint)
{
cout < }
排序数组
sort(a.begin(),a.end()); //对a中的从a.begin()&#xff08;包括它&#xff09;到a.end()&#xff08;不包括它&#xff09;的元素进行从小到大排列
查找数组
find(a.begin(),a.end(),10); //在a中的从a.begin()&#xff08;包括它&#xff09;到a.end()&#xff08;不包括它&#xff09;的元素中查找10&#xff0c;若存在返回其在向量中的位置
注意
C&#43;&#43;11版本以后建议优先使用emplace_back()来代替push_back()。因为emplace_back能通过参数构造对象&#xff0c;不需要拷贝或者移动内存&#xff0c;相比push_back能更好地避免内存的拷贝与移动&#xff0c;使容器插入元素的性能得到进一步提升。