2个反光柱的摆放要求:靠着墙摆,因为我们只能从一侧看到2个反光柱,从两侧都看到至少需要3个反光柱来定位。
landmark检测原理:因为我们是从一侧看到2个反光柱,所以看到2个反光柱在一帧激光数据中会有顺序,有2种情形,如下图
这两种情形,我们发现
情形1: 这种情形2个反光柱子被检测到的激光角度小于180,我们认为大一些激光角度的是原点。
情形2: 这种情形2个反光柱子被检测到的激光角度大于180,我们认为小一些激光角度的是原点。
这样原点就固定下来,并是唯一的。2个反光柱构成的坐标系也就确定了。和激光坐标系之间的旋转关系可以通过2个向量之间的夹角计算得出。再补充一张图:

talk is cheap, show my code first
代码如下:

    //use two reflector as a landmark//log(Info, "reflectors_ size " + std::to_string(reflectors_.size() ));if (reflectors_.size() < 2)return;for (int i = 0; i < reflectors_.size(); i++){Reflector_pos item_i = reflectors_[i];//log(Info, "item_i.center_yaw : " + std::to_string(item_i.center_yaw));for (int j = i + 1; j < reflectors_.size(); j++){Reflector_pos item_j = reflectors_[j];//log(Info, "item_j.center_yaw : " + std::to_string(item_j.center_yaw));double x_ij = fabs(item_i.center_x - item_j.center_x);double y_ij = fabs(item_i.center_y - item_j.center_y);double distance_ij = sqrt(pow(x_ij, 2) + pow(y_ij, 2));//log(Info, "item_i.center_x : " + std::to_string(item_i.center_x));//log(Info, "item_i.center_y : " + std::to_string(item_i.center_y));//log(Info, "item_j.center_x : " + std::to_string(item_j.center_x));//log(Info, "item_j.center_y : " + std::to_string(item_j.center_y));//log(Info, "x_ij : " + std::to_string(x_ij));//log(Info, "y_ij : " + std::to_string(y_ij));//log(Info, "distance_ij : " + std::to_string(distance_ij));//if two reflectors not arrange by special mode, jump outif (fabs(distance_ij - reflector_combined_length) > 0.2)continue;double distance_i = sqrt(pow(item_i.center_x,2) + pow(item_i.center_y,2));double distance_j = sqrt(pow(item_j.center_x,2) + pow(item_j.center_y,2));double coord_x, coord_y, coord_theta;double origin_x, origin_y, origin_theta;if (fabs(item_i.center_yaw - item_j.center_yaw) < M_PI){if (item_i.center_yaw > item_j.center_yaw){//item_i is origindouble up_value = pow(distance_i, 2) + pow(distance_ij, 2) - pow(distance_j, 2);double down_value = 2 * distance_i * distance_ij;double cos_theta = acos(up_value / down_value);coord_x = cos(cos_theta) * distance_i;coord_y = sin(cos_theta) * distance_i;origin_x = item_i.center_x;origin_y = item_i.center_y;origin_theta = atan2(1, 0) - atan2(item_j.center_y - item_i.center_y, item_j.center_x - item_i.center_x);if(origin_theta > M_PI){origin_theta -= 2*M_PI;}if(origin_theta < -M_PI){origin_theta += 2*M_PI;}}else{//item_j is origindouble up_value = pow(distance_j, 2) + pow(distance_ij, 2) - pow(distance_i, 2);double down_value = 2 * distance_j * distance_ij;double cos_theta = acos(up_value / down_value);coord_x = cos(cos_theta) * distance_j;coord_y = sin(cos_theta) * distance_j;coord_theta = atan2(coord_y, coord_x);origin_x = item_j.center_x;origin_y = item_j.center_y;origin_theta = atan2(1, 0) - atan2(item_i.center_y - item_j.center_y, item_i.center_x - item_j.center_x);if(origin_theta > M_PI){origin_theta -= 2*M_PI;}if(origin_theta < -M_PI){origin_theta += 2*M_PI;}}}else{if (item_i.center_yaw < item_j.center_yaw){//item_i is origindouble up_value = pow(distance_i, 2) + pow(distance_ij, 2) - pow(distance_j, 2);double down_value = 2 * distance_i * distance_ij;double cos_theta = acos(up_value / down_value);coord_x = cos(cos_theta) * distance_i;coord_y = sin(cos_theta) * distance_i;coord_theta = atan2(coord_y, coord_x);origin_x = item_i.center_x;origin_y = item_i.center_y;origin_theta = atan2(1, 0) - atan2(item_j.center_y - item_i.center_y, item_j.center_x - item_i.center_x);if(origin_theta > M_PI){origin_theta -= 2*M_PI;}if(origin_theta < -M_PI){origin_theta += 2*M_PI;}}else{//item_j is origindouble up_value = pow(distance_j, 2) + pow(distance_ij, 2) - pow(distance_i, 2);double down_value = 2 * distance_j * distance_ij;double cos_theta = acos(up_value / down_value);coord_x = cos(cos_theta) * distance_j;coord_y = sin(cos_theta) * distance_j;coord_theta = atan2(coord_y, coord_x);origin_x = item_j.center_x;origin_y = item_j.center_y;origin_theta = atan2(1, 0) - atan2(item_i.center_y - item_j.center_y, item_i.center_x - item_j.center_x);if(origin_theta > M_PI){origin_theta -= 2*M_PI;}if(origin_theta < -M_PI){origin_theta += 2*M_PI;}}}//log(Info, "origin_x : " + std::to_string(origin_x));//log(Info, "origin_y : " + std::to_string(origin_y));//log(Info, "origin_theta : " + std::to_string(origin_theta));/*Reflector_pos item;item.center_x = (item_i.center_x + item_j.center_x) / 2;item.center_y = (item_i.center_y + item_j.center_y) / 2;item.center_yaw = atan2(item.center_y , item.center_x);// + M_PI_2;log(Info, "item_i.center_yaw : " + std::to_string(item_i.center_yaw));log(Info, "item_j.center_yaw : " + std::to_string(item_j.center_yaw));//log(Info, "item.center_yaw : " + std::to_string(item.center_yaw));//publish the center pointsgeometry_msgs::PointStamped point;point.header.stamp = scan->header.stamp;point.header.frame_id = "car_laser";point.point.x = item.center_x;point.point.y = item.center_y;point.point.z = 0;reflector_points_.publish(point);*/double distance = sqrt(pow(coord_x, 2) + pow(coord_y, 2));if (distance < 1.0)continue;//cartographer_ros_msgs::LandmarkEntry reflector_LandMarkEntry;reflector_LandMarkEntry.id = "landmark_1";reflector_LandMarkEntry.tracking_from_landmark_transform.position.x = origin_x;reflector_LandMarkEntry.tracking_from_landmark_transform.position.y = origin_y;reflector_LandMarkEntry.tracking_from_landmark_transform.position.z = 0;tf::Quaternion quat = tf::createQuaternionFromYaw(-1.0*origin_theta);reflector_LandMarkEntry.tracking_from_landmark_transform.orientation.x = quat.x();reflector_LandMarkEntry.tracking_from_landmark_transform.orientation.y = quat.y();reflector_LandMarkEntry.tracking_from_landmark_transform.orientation.z = quat.z();reflector_LandMarkEntry.tracking_from_landmark_transform.orientation.w = quat.w();reflector_LandMarkEntry.translation_weight = 1.0;reflector_LandMarkEntry.rotation_weight = 1.0;reflector_LandMarkEntry.type = "reflector_combined";reflector_LandMarkList.header.frame_id = "car_laser";reflector_LandMarkList.header.stamp = scan->header.stamp; //ros::Time::now();reflector_LandMarkList.landmarks.push_back(reflector_LandMarkEntry);#ifdef VISUAL_RVIZvisualization_msgs::Marker landmark_item;landmark_item.pose.position.x = origin_x;landmark_item.pose.position.y = origin_y;landmark_item.pose.orientation.x = 0.0;landmark_item.pose.orientation.y = 0.0;landmark_item.pose.orientation.z = 0.0;landmark_item.pose.orientation.w = 1.0;landmark_item.header.frame_id = "car_laser";landmark_item.header.stamp = scan->header.stamp; //ros::Time::now();landmark_item.scale.x = kLandmarkMarkerScale;landmark_item.scale.y = kLandmarkMarkerScale;landmark_item.scale.z = kLandmarkMarkerScale;landmark_item.type = visualization_msgs::Marker::SPHERE;landmark_item.ns = "Landmarks";landmark_item.id = reflector_LandMarkList.landmarks.size();landmark_item.color.a = 1.0;landmark_item.color.r = 0;landmark_item.color.g = 255;landmark_item.color.b = 0;landmark_item.lifetime = ros::Duration(0.05);landmark_poses_list.markers.push_back(landmark_item);
#endif}}

开源代码
https://gitee.com/laser_reflector_detect

cartographer如何使用2个反光柱子作为一个landmark相关推荐

  1. cartographer如何使用3个反光柱作为一个landmark

    3个反光柱的摆放规则:摆成一个直角三角形或者直线或其他特征 ,直角边不同即可,可以设置边的长度来作为附加特征. 原理:检测3个顶点的角度,检测到是直角时可以确定该点是landmark坐标系的原点.然后 ...

  2. cartographer中的反光板定位

    0. 简介 反光板定位作为cartographer中landmark数据最常用的部分,其特性和AprilTag使用方法类似,在cartographer中,landmark必须是tracking fra ...

  3. 图像反光能被一键去除了?港科大开源RFC,仅用一个操作,强反光也能完美去除|CVPR2021...

    点击上方"3D视觉工坊",选择"星标" 干货第一时间送达 作者丨雷晨阳 审稿丨邓富城 编辑丨极市平台 导读 本文介绍一篇来自香港科技大学中稿CVPR2021的工 ...

  4. 图像反光能被一键去除了?港科大开源RFC,仅用一个操作,强反光也能完美去除|CVPR2021

    本文首发极市平台(微信公众号同名),转载请标明出处. 极市平台是国内专业的计算机视觉开发者平台,原文请戳这里. 代码以及数据集:https://github.com/ChenyangLEI/flash ...

  5. 机器人之Cartographer

    Cartographer 简介 框架介绍 可执行节点 建图参数 launch文件 安装方法(更新中...) 参考: 此文仅作为自身学习使用. 简介 整体而言,Local SLAM 部分负责生成较好的子 ...

  6. unity2D小鸟飞过柱子小游戏

    (1)启动unity应用程序,在弹出的对话框里单击New project 按钮 (2)我们要得到的效果 (3)首先用户在玩这个游戏的时候小鸟是不断向前飞的,我们知道unity中用户眼睛看到的界面就是摄 ...

  7. 柱状图特殊处理,每个柱子颜色不同,图例对应。

    series写多个对象,则一个对象就对应一个柱子,注意data数组只能写一个值,不然就会又多个柱子对应一个图例.xAxis,yAxis不用写数据了.

  8. Cartographer使用篇:保存地图

    工作环境: ubuntu16.04+ROS(Kinetic)+Cartographer-1.0.0 地图文件 .pbstream cartographer格式地图文件,本质上是一个压缩protobuf ...

  9. 反光柱建图venus和我的方案

    venus的方式是一种纯反光柱的方案, 网址:https://gitee.com/dustinksi/VEnus 视频地址:https://www.bilibili.com/video/av80266 ...

最新文章

  1. python和c哪个适合入门-Python和C先学哪个好?
  2. linux s g文本替换问题
  3. SQL Server数据库损坏、检测以及简单的修复办法
  4. 谁说导航一定要用地图?谷歌DeepMind的强化学习模型靠街景认路
  5. 什么是WEBserver? 经常使用的WEBserver有哪些?
  6. sql中多表连接查询——自连接
  7. 怎么使用biopython_Biopython - 简介
  8. Win系统 - 笔记本电脑之耳机插入没声音
  9. Xmind思维导图 常用快捷键使用
  10. 用Now SMS/MMS 发送中国移动彩信
  11. uniapp 登录页跳转到首页
  12. return next(val for val in obj if safe_isfinite(val)) StopIteravtion报错解决方法
  13. NDK - JNI官方中文资料
  14. SAS学习笔记5:删除字符串空格-left/right/trim/strip/compress/compbl等函数的比较
  15. C#小工具 ---- 压缩图片并指定图片大小
  16. 中国天眼新发现登Nature封面:恒星形成速度比我们想象快10倍
  17. python 新闻摘要_每日新闻摘要:iPad Mini评论,AT&T首席执行官获得Robocall等等
  18. postgresql 字符串拼接函数concat_lower_or_upper
  19. 目前就常用计算机类型,CAD-CAM练习题
  20. 文献阅读:ESAM: Discriminative Domain Adaptation with Non-Displayed Items to Improve Long-Tail Performanc

热门文章

  1. 弘辽科技:淘宝推广效果不好?是由哪些原因造成的?该如何解决?
  2. 如何成为一名“优秀”的商业分析师
  3. EMC实验实战案例-ESD静电实验
  4. Spring/Boot/Cloud系列知识:SpringMVC 传参详解(下)
  5. [原创]电信网络限制破解
  6. Essence and accidents of software engineering(软件工程的本质和附加属性)
  7. NAS4FREE无法打开网页控制台(WebGui)的解决办法
  8. 解决在IDEA里Git特别慢的问题
  9. 2020年回顾与2021年展望
  10. 色值的透明度与十六进制代码转换