文章目录
2020.12.21
1. 编译报错
执行如下catkin_make时,
报错如下:
CMake Warning (dev) at turtlebot/navigation/move_base/CMakeLists.txt:45 (add_dependencies):
Policy CMP0046 is not set: Error on non-existent dependency in
add_dependencies. Run "cmake --help-policy CMP0046" for policy details.
Use the cmake_policy command to set the policy and suppress this warning.
The dependency target "geometry_msgs_gencpp" of target "move_base" does not
exist.
This warning is for project developers. Use -Wno-dev to suppress it.
-- Generating done
-- Build files have been written to: /home/zth/work_ws/build
Invoking "cmake" failed
报错信息中给出了解决方案:
$ catkin_make -Wno-dev
编译成功后如下:
接下来这步编译依旧会出现上面那个问题,同样方法处理即可。
2. 周六去实验室验证该步骤
hokoyu 配置最后插入激光传感器,检查文件权限。
2020.12.25
1. 编译时显示无法确定目标文件的语言
- 报错如下:
CMake Error: CMake can not determine linker language for target: DetectLine
- 问题背景:编译时,显示不知道DetectLine.cpp的语言,但这文件明明是C++啊?查看CmakeList.txt文件时发现下面这句(从实验报告中copy的)存在问题,
add_executable(DetectLine src/DetectLine.cpp)
target_link_libraries(DetectLine ${
catkin_LIBRARIES})
- 解决方法:src/DetectLine.cpp中的“/”后多了一个空格,删掉空格后编译成功。
2. msg.angle_min编译报错
解决方法:
将msg.angle_min
改为msg->angle_min
。
3. 实验2代码
参数设定如下:
- 一个霍夫变换算法检测的角度范围:60°
- 每次步进的角度:10°
- 激光传感器扫描的角度:180°
- 选取中间的120°
- 将其均分为30°-90°,40°-100°,……90°-150°
- 在30°-90°这60°的范围内,选取N=11束激光
- 将直线的方向离散化为有限个等间距的离散值=2°
- 误差允许范围设为0.01
- 阈值设为N-1
3.1 DetectLine.cpp版本1(存在错误,版本2是修复过的)
#include "ros/ros.h"
#include "sensor_msgs/LaserScan.h"
#define PI 3.1415926
// 回调函数
void laserCallback(const sensor_msgs::LaserScan::ConstPtr& msg)
{
std::vector<float> ranges = msg->ranges;
std::vector<double> angle;
// std::vector<double> X;
// std::vector<double> Y;
// 转换到二维XY平面坐标系下
for(int i = 0; i < ranges.size(); i++)
{
angle.push_back(msg->angle_min + i * msg->angle_increment);
// X.push_back(ranges[i] * cos(angle[i]));
// Y.push_back(ranges[i] * sin(angle[i]));
}
// 激光传感器扫描的角度为180度,选取其中间的120度
int angle_start_order = ranges.size() * 30/180; // 要计算的起始角度 = 30度
int angle_end_order = ranges.size() * 150/180; // 要计算的结束角度 = 150度
// 选定霍夫变换的角度范围为60度,每次歩进的角度为10度
int Hough_angle_range_order = ranges.size() * 60/180; // 霍夫变换的角度范围 = 60度
int Hough_angle_step_order = ranges.size() * 10/180; // 每次歩进的角度 = 10度
// 对每一个60度范围执行1次霍夫变换检测
int N = 11; // 在这60度的范围内选取N束激光 = 11条
int M = Hough_angle_range_order / (N - 1); // 均匀选取N束激光时,每束激光的角度间隔数,即个间隔几个msg->angle_increment。如60度的范围内取11束激光,就是60/(11-1)=6度,M=6/msg->angle_increment,M向下取整,得到977
int times = 7; // 霍夫变换次数 = (angle_end_order - angle_start_order - Hough_angle_range_order) / Hough_angle_step_order + 1 = (150-30-60)/10 + 1 = 7
std::vector<double> laser_angle; // 激光角度
std::vector<double> x;
std::vector<double> y;
std::vector<std::vector<double> > r(N, std::vector<double>(180/2+1)); // 格式:二维动态数组N行180/2+1列
std::vector<std::vector<double> > error(N, std::vector<double>(N)); // 每组中 N 个 r 值之间的误差。格式:二维动态数组N行N列
for(int i = 0; i < times; i++) // 霍夫变换次数 = (angle_end - angle_start - Hough_angle_range) / Hough_angle_step + 1 = (150-30-60)/10 + 1 = 7
{
double Hough_angle_start = angle[angle_start_order] + angle[Hough_angle_step_order] * i; // 每次霍夫变换的起始角度
for(int j = 0; j < N; j++)
{
int laser_order = angle_start_order + Hough_angle_step_order * i + j * M;
laser_angle.push_back(angle[laser_order]);
x.push_back(ranges[laser_order] * cos(angle[laser_order]));
y.push_back(ranges[laser_order] * sin(angle[laser_order]));
// 计算每个角度对应的参数空间的值 r
for(int k = 0; k < 180/2+1; k++)
{
r[j][k] = (x[j] * cos(k*2/180*PI) + y[j] * sin(k*2/180*PI));
}
}
// 在每个离散化角度下,对计算出的 N 个 r 值进行比较
for(int k = 0; k < 180/2+1; k++)
{
for(int m = 0; m < N; m++)
{
int vote_times = 0;
for(int n = 0; n < N; n++)
{
error[m][n] = r[k][m] - r[k][n];
// 取误差绝对值
if(error[m][n] < 0)
error[m][n] = - error[m][n];
// 如果误差在设定的范围内
if(error[m][n] < 0.01)
{
vote_times++;
}
}
// 投票次数达到阈值,则这是一条直线,输出结果; 否则,投票数清零,计算其他组合
if(vote_times >= N - 1)
ROS_INFO("IsStraightLine: 1");
}
}
// 没有检测到直线
ROS_INFO("IsStraightLine: 0");
}
}
int main(int argc, char **argv)
{
// 初始化ROS,新建DetectLine节点
ros::init(argc, argv, "DetectLine");
// 创建句柄
ros::NodeHandle n;
// 新建一个ros:Subscribe对象,该对象订阅话题/sacn上发布的消息
ros::Subscriber sub = n.subscribe("/scan", 10, laserCallback);
// 进入自循环,等待消息的到达
ros::spin();
return 0;
}
实物验证时,上述代码存在数组访问越界,误差阈值设置过小的问题。
下面的代码是修改后测试效果良好的。
3.2 DetectLine.cpp版本2
#include "ros/ros.h"
#include "sensor_msgs/LaserScan.h"
#define PI 3.1415926
// 回调函数
void laserCallback(const sensor_msgs::LaserScan::ConstPtr& msg)
{
ROS_INFO("laserCallback is called!");
std::vector<float> ranges = msg->ranges;
std::vector<double> angle;
// std::vector<double> X;
// std::vector<double> Y;
// 转换到二维XY平面坐标系下
for(int i = 0; i < ranges.size(); i++)
{
angle.push_back(msg->angle_min + i * msg->angle_increment);
// X.push_back(ranges[i] * cos(angle[i]));
// Y.push_back(ranges[i] * sin(angle[i]));
//ROS_INFO("range_order: %d, ranges: %f", i, ranges[i]);
}
// 激光传感器扫描的角度为180度,选取其中间的120度
int angle_start_order = ranges.size() * 30/180; // 要计算的起始角度 = 30度
//ROS_INFO("angle_start_order: %d\n", angle_start_order);
int angle_end_order = ranges.size() * 150/180; // 要计算的结束角度 = 150度
//ROS_INFO("angle_end_order: %d\n", angle_end_order);
// 选定霍夫变换的角度范围为60度,每次歩进的角度为10度
int Hough_angle_range_order = ranges.size() * 60/180; // 霍夫变换的角度范围 = 60度
//ROS_INFO("Hough_angle_range_order: %d\n", Hough_angle_range_order);
int Hough_angle_step_order = ranges.size() * 10/180; // 每次歩进的角度 = 10度
//ROS_INFO("Hough_angle_step_order: %d\n", Hough_angle_step_order);
// 对每一个60度范围执行1次霍夫变换检测
int N = 11; // 在这60度的范围内选取N束激光 = 11条
int M = Hough_angle_range_order / (N - 1); // 均匀选取N束激光时,每束激光的角度间隔数,即个间隔几个msg->angle_increment。如60度的范围内取11束激光,就是60/(11-1)=6度,M=6/msg->angle_increment,M向下取整,得到
//ROS_INFO("M: %d\n", M);
int times = 7; // 霍夫变换次数 = (angle_end_order - angle_start_order - Hough_angle_range_order) / Hough_angle_step_order + 1 = (150-30-60)/10 + 1 = 7
//std::vector<double> laser_angle; // 激光角度
//std::vector<double> x;
//std::vector<double> y;
std::vector<std::vector<double> > r(N, std::vector<double>(180/2+1)); // 格式:二维动态数组N行180/2+1列
std::vector<std::vector<double> > error(N, std::vector<double>(N)); // 每组中 N 个 r 值之间的误差。格式:二维动态数组N行N列
for(int i = 0; i < times; i++) // 霍夫变换次数 = (angle_end - angle_start - Hough_angle_range) / Hough_angle_step + 1 = (150-30-60)/10 + 1 = 7
{
//ROS_INFO("Hough times: %d", i);
double Hough_angle_start = angle[angle_start_order] + angle[Hough_angle_step_order] * i; // 每次霍夫变换的起始角度
for(int j = 0; j < N; j++)
{
int laser_order = angle_start_order + Hough_angle_step_order * i + j * M;
//laser_angle.push_back(angle[laser_order]);
double x = (ranges[laser_order] * cos(angle[laser_order]));
double y = (ranges[laser_order] * sin(angle[laser_order]));
//ROS_INFO("x = %f", x);
//ROS_INFO("y = %f", y);
// 计算每个角度对应的参数空间的值 r
for(int k = 0; k < 180/2+1; k++)
{
//r[j][k] = (x[j] * cos(k*2/180*PI) + y[j] * sin(k*2/180*PI));
r[j][k] = (x * cos(k*2/180*PI) + y * sin(k*2/180*PI));
//ROS_INFO("r: %f", r[j][k]);
}
}
// 在每个离散化角度下,对计算出的 N 个 r 值进行比较
for(int k = 0; k < 180/2+1; k++)
{
for(int m = 0; m < N; m++)
{
int vote_times = 0;
for(int n = 0; n < N; n++)
{
error[m][n] = r[m][k] - r[n][k];
//ROS_INFO("error: %f", error[m][n]);
// 取误差绝对值
if(error[m][n] < 0)
error[m][n] = - error[m][n];
// 如果误差在设定的范围内
if(error[m][n] < 0.1)
{
vote_times++;
//ROS_INFO("vote_times: %d", vote_times);
}
}
// 投票次数达到阈值,则这是一条直线,输出结果; 否则,投票数清零,计算其他组合
if(vote_times >= N - 1)
ROS_INFO("IsStraightLine: 1");
}
}
// 没有检测到直线
//ROS_INFO("IsStraightLine: 0");
}
}
int main(int argc, char **argv)
{
// 初始化ROS,新建DetectLine节点
ros::init(argc, argv, "DetectLine");
// 创建句柄
ros::NodeHandle n;
// 新建一个ros:Subscribe对象,该对象订阅话题/sacn上发布的消息
ros::Subscriber sub = n.subscribe("/scan", 10, laserCallback);
// 进入自循环,等待消息的到达
ros::spin();
return 0;
}