|
@@ -221,7 +221,7 @@ bool Ground_region::classify_ceres_detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cl
|
|
|
//下采样
|
|
|
pcl::VoxelGrid<pcl::PointXYZ> vox; //创建滤波对象
|
|
|
vox.setInputCloud(cloud_filtered); //设置需要过滤的点云给滤波对象
|
|
|
- vox.setLeafSize(0.02f, 0.02f, 0.02f); //设置滤波时创建的体素体积为1cm的立方体
|
|
|
+ vox.setLeafSize(0.01f, 0.01f, 0.01f); //设置滤波时创建的体素体积为1cm的立方体
|
|
|
vox.filter(*cloud_filtered); //执行滤波处理,存储输出
|
|
|
if (cloud_filtered->size() == 0)
|
|
|
{
|
|
@@ -264,7 +264,7 @@ bool Ground_region::classify_ceres_detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cl
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- // LOG(WARNING) << error_str;
|
|
|
+ LOG(WARNING) << error_str;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
@@ -337,11 +337,11 @@ bool computer_var(std::vector<double> data, double &var)
|
|
|
|
|
|
Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, detect_wheel_ceres3d::Detect_result &last_result)
|
|
|
{
|
|
|
- // 1.*********点云合法性检验
|
|
|
+ // 1.*********点云合法性检验*********
|
|
|
if (cloud->size() == 0)
|
|
|
return Error_manager(VELODYNE_REGION_EMPTY_CLOUD, NORMAL, "no point");
|
|
|
|
|
|
- // 2.*********点云预处理
|
|
|
+ // 2.*********点云预处理*********
|
|
|
std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
|
|
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);
|
|
|
for (int i = 0; i < cloud->size(); ++i)
|
|
@@ -357,7 +357,7 @@ Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, d
|
|
|
pcl::StatisticalOutlierRemoval<pcl::PointXYZ> sor;
|
|
|
sor.setInputCloud(cloud_filtered);
|
|
|
sor.setMeanK(15); //K近邻搜索点个数
|
|
|
- sor.setStddevMulThresh(3.0); //标准差倍数
|
|
|
+ sor.setStddevMulThresh(1.0); //标准差倍数
|
|
|
sor.setNegative(false); //保留未滤波点(内点)
|
|
|
sor.filter(*cloud_filtered); //保存滤波结果到cloud_filter
|
|
|
|
|
@@ -379,19 +379,20 @@ Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, d
|
|
|
mp_cloud_filtered->operator+=(*cloud_filtered);
|
|
|
m_filtered_cloud_mutex.unlock();
|
|
|
|
|
|
- // 3.*********位姿优化,获取中心xy与角度
|
|
|
+ // 3.*********位姿优化,获取中心xy与角度*********
|
|
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_detect_z(new pcl::PointCloud<pcl::PointXYZ>);
|
|
|
double x, y, theta, width, z_value=0.2;
|
|
|
if(!Car_pose_detector::get_instance_references().detect_pose(cloud_filtered, cloud_detect_z, x, y, theta, width, z_value, false))
|
|
|
{
|
|
|
- return Error_manager(VELODYNE_REGION_CERES_SOLVE_ERROR, NEGLIGIBLE_ERROR, "find chassis z value failed.");
|
|
|
+ return Error_manager(VELODYNE_REGION_CERES_SOLVE_ERROR, NEGLIGIBLE_ERROR, "find general car pose value failed.");
|
|
|
}
|
|
|
- std::cout << "cx: " << x+m_region.plc_offsetx() << ", cy: " << y+m_region.plc_offsety() << ", theta: " << theta*180.0/M_PI << std::endl;
|
|
|
+ LOG(INFO) << "car pose :::: cx: " << x+m_region.plc_offsetx() << ", cy: " << y+m_region.plc_offsety() << ", theta: " << theta*180.0/M_PI << std::endl;
|
|
|
|
|
|
std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
|
|
|
std::chrono::duration<double> time_used_bowl = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
|
|
|
|
|
|
- // 4.*********xoz优化获取底盘高度
|
|
|
+ // 4.*********xoz优化获取底盘高度*********
|
|
|
+ // 重新取包含地面点的点云,用于底盘优化
|
|
|
chassis_ceres_solver t_solver;
|
|
|
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_z_solver(new pcl::PointCloud<pcl::PointXYZ>);
|
|
|
for (int i = 0; i < cloud->size(); ++i)
|
|
@@ -402,15 +403,19 @@ Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, d
|
|
|
cloud_z_solver->push_back(pt);
|
|
|
}
|
|
|
}
|
|
|
- double mid_z = 0.06, height = 0.08;
|
|
|
+ //离群点过滤
|
|
|
+ sor.setInputCloud(cloud_z_solver);
|
|
|
+ sor.setMeanK(15); //K近邻搜索点个数
|
|
|
+ sor.setStddevMulThresh(1.0); //标准差倍数
|
|
|
+ sor.setNegative(false); //保留未滤波点(内点)
|
|
|
+ sor.filter(*cloud_z_solver); //保存滤波结果到cloud_filter
|
|
|
+
|
|
|
+ double mid_z = 0.05, height = 0.08;
|
|
|
+ // 去中心,角度调正
|
|
|
Car_pose_detector::get_instance_references().inv_trans_cloud(cloud_z_solver, x, y, theta);
|
|
|
- // //下采样
|
|
|
- // vox.setInputCloud(cloud_z_solver); //设置需要过滤的点云给滤波对象
|
|
|
- // vox.setLeafSize(0.02f, 0.02f, 0.02f); //设置滤波时创建的体素体积为1cm的立方体
|
|
|
- // vox.filter(*cloud_z_solver); //执行滤波处理,存储输出
|
|
|
|
|
|
- if (cloud_filtered->size() == 0)
|
|
|
- return Error_manager(VELODYNE_REGION_EMPTY_CLOUD, NORMAL, "filtered no point");
|
|
|
+ if (cloud_z_solver->size() == 0)
|
|
|
+ return Error_manager(VELODYNE_REGION_EMPTY_CLOUD, NORMAL, "z solver no point");
|
|
|
|
|
|
x = 0.0;
|
|
|
width = 1.0;
|
|
@@ -431,6 +436,9 @@ Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, d
|
|
|
// cloud_z_solver->push_back(pcl::PointXYZ(width/2.0, i, 0));
|
|
|
// }
|
|
|
// std::cout << "\n------------------------------------ chassis z1: " << mid_z + height / 2.0 << std::endl;
|
|
|
+
|
|
|
+ if(ec != SUCCESS)
|
|
|
+ return Error_manager(VELODYNE_REGION_CERES_SOLVE_ERROR, NORMAL, "failed to find chassis z value.");
|
|
|
std::chrono::steady_clock::time_point t3 = std::chrono::steady_clock::now();
|
|
|
std::chrono::duration<double> time_used_block = std::chrono::duration_cast<std::chrono::duration<double>>(t3 - t2);
|
|
|
|
|
@@ -440,19 +448,21 @@ Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, d
|
|
|
mp_cloud_detect_z->operator+=(*cloud_z_solver);
|
|
|
m_detect_z_cloud_mutex.unlock();
|
|
|
|
|
|
- // 二分法存在错误,直接使用底盘z值
|
|
|
+ // 二分法存在错误弃用!!!直接使用底盘z值
|
|
|
std::vector<detect_wheel_ceres3d::Detect_result> results;
|
|
|
detect_wheel_ceres3d::Detect_result result;
|
|
|
double chassis_z = mid_z + height / 2.0; // + 0.02;
|
|
|
if(chassis_z > m_region.maxz() || chassis_z < m_region.minz())
|
|
|
{
|
|
|
- return Error_manager(VELODYNE_REGION_CERES_SOLVE_ERROR, NEGLIGIBLE_ERROR, (std::string("failed to find chassis z value: ")+std::to_string(chassis_z)).c_str());
|
|
|
+ return Error_manager(VELODYNE_REGION_CERES_SOLVE_ERROR, NEGLIGIBLE_ERROR, (std::string("optimized chassis z value out of range: ")+std::to_string(chassis_z)).c_str());
|
|
|
}
|
|
|
bool ret = false;
|
|
|
- while(chassis_z > (mid_z-0.02))
|
|
|
+
|
|
|
+ while (chassis_z > (mid_z))
|
|
|
{
|
|
|
+ LOG_IF(WARNING, m_region.region_id() == 4) << "chassis z: " << chassis_z;
|
|
|
ret = classify_ceres_detect(cloud_filtered, chassis_z, result);
|
|
|
- // changed by yct, 暂时直接识别,调试用,之后将条件恢复
|
|
|
+ // changed by yct, 根据底盘z识别,失败则向下移动直至成功或超过底盘内空中点
|
|
|
if(ret)
|
|
|
{
|
|
|
results.push_back(result);
|
|
@@ -461,33 +471,6 @@ Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, d
|
|
|
chassis_z -= 0.01;
|
|
|
}
|
|
|
}
|
|
|
- // float start_z = m_region.minz();
|
|
|
- // float max_z = z_value;//0.2;
|
|
|
- // float center_z = (start_z + max_z) / 2.0;
|
|
|
- // float last_center_z = start_z;
|
|
|
- // float last_succ_z = -1.0;
|
|
|
- // int count = 0;
|
|
|
- // //二分法 找识别成功的 最高的z
|
|
|
- // std::vector<detect_wheel_ceres3d::Detect_result> results;
|
|
|
- // do
|
|
|
- // {
|
|
|
- // detect_wheel_ceres3d::Detect_result result;
|
|
|
- // bool ret = classify_ceres_detect(cloud_filtered, center_z, result);
|
|
|
- // // std::cout << "z: " << center_z <<", "<<start_z<<"," << max_z <<(ret?"clustered":"clustering failed")<< std::endl;
|
|
|
- // if (ret)
|
|
|
- // {
|
|
|
- // results.push_back(result);
|
|
|
- // last_succ_z = center_z;
|
|
|
- // start_z = center_z;
|
|
|
- // last_center_z = center_z;
|
|
|
- // }
|
|
|
- // else
|
|
|
- // {
|
|
|
- // max_z = center_z;
|
|
|
- // last_center_z = center_z;
|
|
|
- // }
|
|
|
- // center_z = (start_z + max_z) / 2.0;
|
|
|
- // count++;
|
|
|
|
|
|
// } while (fabs(center_z - last_center_z) > 0.01);
|
|
|
std::chrono::steady_clock::time_point t4 = std::chrono::steady_clock::now();
|
|
@@ -497,18 +480,18 @@ Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, d
|
|
|
if (results.size() == 0)
|
|
|
{
|
|
|
// 20201010, may lead to problem in chutian, uncomment in debug only
|
|
|
- // // changed by yct, save 3d wheel detect result.
|
|
|
- // static int save_debug = 0;
|
|
|
- // if (save_debug++ == 2)
|
|
|
- // m_detector->save_debug_data("/home/youchen/extra_space/chutian/measure/chutian_velo_ws/log/debug");
|
|
|
+ // changed by yct, save 3d wheel detect result.
|
|
|
+ static int save_debug = 0;
|
|
|
+ if (save_debug++ == 5)
|
|
|
+ m_detector->save_debug_data("/home/youchen/extra_space/chutian/measure/chutian_velo_ws/log/debug");
|
|
|
|
|
|
// std::cout << "\n-------- no result: " << std::endl;
|
|
|
- LOG(INFO) << "failed with midz, currz: " << mid_z << ", " << chassis_z;
|
|
|
- return Error_manager(FAILED, NORMAL, "no car detected");
|
|
|
+ LOG_IF(INFO, m_region.region_id() == 4) << "failed with midz, currz: " << mid_z << ", " << chassis_z;
|
|
|
+ return Error_manager(VELODYNE_REGION_CERES_SOLVE_ERROR, NEGLIGIBLE_ERROR, "3d wheel detect failed.");
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- LOG(INFO) << "detected with suitable z value: " << chassis_z;
|
|
|
+ LOG_IF(INFO, m_region.region_id() == 4) << "detected with suitable z value: " << chassis_z;
|
|
|
}
|
|
|
/// to be
|
|
|
float min_mean_loss = 1.0;
|
|
@@ -533,8 +516,8 @@ Error_manager Ground_region::detect(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, d
|
|
|
// center_z, last_result.theta, last_result.front_theta, last_result.wheel_base, last_result.width,
|
|
|
// min_mean_loss);
|
|
|
// std::cout << "\n-------- final z: " << chassis_z << std::endl;
|
|
|
- std::cout << "cx: " << last_result.cx << ", cy: " << last_result.cy << ", theta: " << last_result.theta
|
|
|
- << ", front: " << last_result.front_theta << ", wheelbase: " << last_result.wheel_base << ", width: " << last_result.width << std::endl << std::endl;
|
|
|
+ // std::cout << "cx: " << last_result.cx << ", cy: " << last_result.cy << ", theta: " << last_result.theta
|
|
|
+ // << ", front: " << last_result.front_theta << ", wheelbase: " << last_result.wheel_base << ", width: " << last_result.width << std::endl << std::endl;
|
|
|
|
|
|
// last_result.cx -= x;
|
|
|
// last_result.cy -= y;
|