Tare_Planner小项目---->2D雷达的数据接口(二)gazebo2D雷达

//***给自己的话***//:tare接受的点云数据id_dense是要设置成false的,不然报错;另外雷达intensity是人为设置成1了,还没尝试过不设置会怎么样,但是如果做现实的数据接口记得做好雷达intensify数据.

目标:采用2D雷达替换3D雷达,为Tare_planner提供数据

一.伤口断裂处

        1.注释掉tare当中不必要的话题订阅(在sensor_coverage_planner_ground.cpp)

           把kCheckTerrainCollision在yaml里默认改为false(取消地势分析)

                (这里我把地势分析也注释了,这个不知道不去除的话效果会不会更好;不过2D雷达确实捕捉不到3D地势的特征,所以地势分析似乎是没法提取出有用的地势信息的)

// exploration_start_sub_ =
  //     nh.subscribe(pp_.sub_start_exploration_topic_, 5, &SensorCoveragePlanner3D::ExplorationStartCallback, this);     //这个订阅未被使用
  registered_scan_sub_ =
      nh.subscribe(pp_.sub_registered_scan_topic_, 5, &SensorCoveragePlanner3D::RegisteredScanCallback, this);//******三D相机********/registered_scan
        //EXPL 1.每帧执行pd_.planning_env_的一个操作 => :上传一次机器人位置和pd_.registered_cloud_->cloud_    2. 每5帧上传kepose ==>> 当前机器人位置"keypose_.pose.pose.position;pd_.keypose_.pose.covariance;pd_.cur_keypose_node_ind_" 和  "pd_.keypose_cloud_->cloud_",    
  // terrain_map_sub_ = nh.subscribe(pp_.sub_terrain_map_topic_, 5, &SensorCoveragePlanner3D::TerrainMapCallback, this);//局部地势/terrain_map
  //       //EXPL 1.将接收到的点,intensity达到阈值的都赋值给pd_.terrain_collision_cloud_->cloud_->points (只有这件事情)        (这个是局部地势)
  // terrain_map_ext_sub_ =
  //     nh.subscribe(pp_.sub_terrain_map_ext_topic_, 5, &SensorCoveragePlanner3D::TerrainMapExtCallback, this);//更大的地势/terrain_map_ext
  //       //EXPL 1.将接收到的点,intensity达到阈值的都赋值给pd_.terrain_ext_collision_cloud_             (只有这件事情)        (这个是较为全局的地势)
  state_estimation_sub_ =
      nh.subscribe(pp_.sub_state_estimation_topic_, 5, &SensorCoveragePlanner3D::StateEstimationCallback, this);//位置估计/state_estimation_at_scan
        //EXPL 1.跟机器人的位置有关,将位置信息赋值给pd_.initial_position_,(只初始化一次)   2.每次更新yaw(翻译是偏离航线)  3.每次更新机器人位置
        //MYTODO  地势的都是在   SensorCoveragePlanner3D::UpdateViewPoints()  这个函数里使用;;如果加入2D想要放弃地势变化的话看看怎么改能让这个函数正常工作
  // coverage_boundary_sub_ =                                                                                               //这3个订阅未被使用
  //     nh.subscribe(pp_.sub_coverage_boundary_topic_, 1, &SensorCoveragePlanner3D::CoverageBoundaryCallback, this);
  // viewpoint_boundary_sub_ =
  //     nh.subscribe(pp_.sub_viewpoint_boundary_topic_, 1, &SensorCoveragePlanner3D::ViewPointBoundaryCallback, this);
  // nogo_boundary_sub_ =
  //     nh.subscribe(pp_.sub_nogo_boundary_topic_, 1, &SensorCoveragePlanner3D::NogoBoundaryCallback, this);

        2.在vehicle_simulator这里修改了lidar.urdf.xacro,新建了一个文件lidar_2D_urdf.xacro.

这里将两行注释掉,并且新写了它下面的两行(即5.6行),其发布的话题为"/2D_Lascan"(输入)

<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="example">
  <link name="lidar" />
  <!-- <xacro:include filename="$(find velodyne_description)/urdf/VLP-16.urdf.xacro"/>
  <xacro:VLP-16 parent="lidar" name="velodyne" topic="/velodyne_points" hz="5" samples="350" min_range="0.1" organize_cloud="true"> -->
  <xacro:include filename="$(find velodyne_description)/urdf/lidar_2D_urdf.xacro"/>
  <xacro:VLP-16 parent="lidar" name="2D_Ladar" topic="/2D_Lascan" hz="5" samples="350" min_range="0.1" organize_cloud="true">
    <origin xyz="0 0 0" rpy="0 0 0" />
  </xacro:VLP-16>
</robot>

        3.由于urdf的修改,这里不再能接受到"/velodyne_points"的数据,新实例化一个订阅对象subScan_new,新写一条回调函数.

ros::Subscriber subScan_new = nh.subscribe<sensor_msgs::LaserScan>("/2D_Lascan", 100, scanHandler_for_2DLadar);      //##  接收消息2D并发布到/registered_scan

           在vehicle_simulator这里修改了vehicleSimulator.cpp,将pubScan的发布话题改成了"/registered_scan_old",即对其进行了废弃.新实例化一个发布对象pubScan_new,发布的话题名称为"/registered_scan"(输出).

二.尝试把功能都能正常做起来,并连接伤口

        1.写urdf让gazebo能够正常发出激光雷达数据,这是新建的lidar_2D_urdf.xacro文件

        (注释的为VLP-16.urdf.xacro源代码,注释下面是新加的代码=>采用2D雷达reference)

<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="VLP-16">
  <xacro:property name="M_PI" value="3.1415926535897931" />
  <xacro:macro name="VLP-16" params="*origin parent:=base_link name:=velodyne topic:=/velodyne_points organize_cloud:=false hz:=10 lasers:=16 samples:=1875 collision_range:=0.3 min_range:=0.9 max_range:=130.0 noise:=0.008 min_angle:=-${M_PI} max_angle:=${M_PI} gpu:=false">

    <joint name="${name}_base_mount_joint" type="fixed">
      <xacro:insert_block name="origin" /> 
      <parent link="${parent}"/>
      <child link="${name}_base_link"/>
    </joint>

    <link name="${name}_base_link">
      <inertial>
        <mass value="0.83"/>
        <origin xyz="0 0 0.03585"/>
        <inertia ixx="${(0.83 * (3.0*0.0516*0.0516 + 0.0717*0.0717)) / 12.0}" ixy="0" ixz="0"
          iyy="${(0.83 * (3.0*0.0516*0.0516 + 0.0717*0.0717)) / 12.0}" iyz="0"
          izz="${0.5 * 0.83 * (0.0516*0.0516)}"/>
      </inertial>
      <visual>
        <geometry>
          <mesh filename="package://velodyne_description/meshes/VLP16_base_1.dae" />
        </geometry>
      </visual>
      <visual>
        <geometry>
          <mesh filename="package://velodyne_description/meshes/VLP16_base_2.dae" />
        </geometry>
      </visual>
      <collision>
        <origin rpy="0 0 0" xyz="0 0 0.03585"/>
        <geometry>
          <cylinder radius="0.0516" length="0.0717"/>
        </geometry>
      </collision>
    </link>

    <joint name="${name}_base_scan_joint" type="fixed" >
      <origin xyz="0 0 0.0377" rpy="0 0 0" />
      <parent link="${name}_base_link" />
      <child link="${name}"/>
    </joint>

    <link name="${name}">
      <inertial>
        <mass value="0.01"/>
        <origin xyz="0 0 0"/>
        <inertia ixx="1e-7" ixy="0" ixz="0" iyy="1e-7" iyz="0" izz="1e-7"/>
      </inertial>
      <visual>
        <origin xyz="0 0 -0.0377" />
        <geometry>
          <mesh filename="package://velodyne_description/meshes/VLP16_scan.dae" />
        </geometry>
      </visual>
    </link>

    <!-- Gazebo requires the velodyne_gazebo_plugins package -->
    <!-- <gazebo reference="${name}">
      <xacro:if value="${gpu}">
        <sensor type="gpu_ray" name="${name}-VLP16">
          <pose>0 0 0 0 0 0</pose>
          <visualize>false</visualize>
          <update_rate>${hz}</update_rate>
          <ray>
            <scan>
              <horizontal>
                <samples>${samples}</samples>
                <resolution>1</resolution>
                <min_angle>${min_angle}</min_angle>
                <max_angle>${max_angle}</max_angle>
              </horizontal>
              <vertical>
                <samples>${lasers}</samples>
                <resolution>1</resolution>
                <min_angle>-${15.0*M_PI/180.0}</min_angle>
                <max_angle> ${15.0*M_PI/180.0}</max_angle>
              </vertical>
            </scan>
            <range>
              <min>${collision_range}</min>
              <max>${max_range+1}</max>
              <resolution>0.001</resolution>
            </range>
            <noise>
              <type>gaussian</type>
              <mean>0.0</mean>
              <stddev>0.0</stddev>
            </noise>
          </ray>
          <plugin name="gazebo_ros_laser_controller" filename="libgazebo_ros_velodyne_gpu_laser.so">
            <topicName>${topic}</topicName>
            <frameName>${name}</frameName>
            <organize_cloud>${organize_cloud}</organize_cloud>
            <min_range>${min_range}</min_range>
            <max_range>${max_range}</max_range>
            <gaussianNoise>${noise}</gaussianNoise>
          </plugin>
        </sensor>
      </xacro:if>
      <xacro:unless value="${gpu}">
        <sensor type="ray" name="${name}-VLP16">
          <pose>0 0 0 0 0 0</pose>
          <visualize>false</visualize>
          <update_rate>${hz}</update_rate>
          <ray>
            <scan>
              <horizontal>
                <samples>${samples}</samples>
                <resolution>1</resolution>
                <min_angle>${min_angle}</min_angle>
                <max_angle>${max_angle}</max_angle>
              </horizontal>
              <vertical>
                <samples>${lasers}</samples>
                <resolution>1</resolution>
                <min_angle>-${15.0*M_PI/180.0}</min_angle>
                <max_angle> ${15.0*M_PI/180.0}</max_angle>
              </vertical>
            </scan>
            <range>
              <min>${collision_range}</min>
              <max>${max_range+1}</max>
              <resolution>0.001</resolution>
            </range>
            <noise>
              <type>gaussian</type>
              <mean>0.0</mean>
              <stddev>0.0</stddev>
            </noise>
          </ray>
          <plugin name="gazebo_ros_laser_controller" filename="libgazebo_ros_velodyne_laser.so">
            <topicName>${topic}</topicName>
            <frameName>${name}</frameName>
            <organize_cloud>${organize_cloud}</organize_cloud>
            <min_range>${min_range}</min_range>
            <max_range>${max_range}</max_range>
            <gaussianNoise>${noise}</gaussianNoise>
          </plugin>
        </sensor>
      </xacro:unless>
    </gazebo> -->
    <!-- 配置雷达传感器信息 -->
    <gazebo reference="${name}">
        <sensor type="ray" name="rplidar">
            <pose>0 0 0 0 0 0</pose>
            <visualize>false</visualize>
            <update_rate>${hz}</update_rate>
            <ray>
                <scan>
                    <horizontal>
                        <samples>360</samples>
                        <resolution>1</resolution>
                        <min_angle>-3</min_angle>
                        <max_angle>3</max_angle>
                    </horizontal>
                </scan>
                <range>
                    <min>0.10</min>
                    <max>40.0</max>
                    <resolution>0.01</resolution>
                </range>
                <noise>
                    <type>gaussian</type>
                    <mean>0.0</mean>
                    <stddev>0.01</stddev>
                </noise>
            </ray>
            <plugin name="gazebo_rplidar" filename="libgazebo_ros_laser.so">
                <topicName>${topic}</topicName>
                <frameName>${name}</frameName>
            </plugin>
        </sensor>
    </gazebo>

  </xacro:macro>
</robot>

此时运行roslaunch vehicle_simulator system_tunnel.launch,再另起一个rviz,应该可以看到

2D雷达的数据可以显示出来了

其中Fixed Frame应该选择2D_Ladar,topic应该选2D_Lascan,这个以lidar.urdf.xacro写的这个为准.

<xacro:VLP-16 parent="lidar" name="2D_Ladar" topic="/2D_Lascan" hz="5" samples="350" min_range="0.1" organize_cloud="true">

        2.订阅雷达数据,将其转换成pcl2类型

                这个如伤口断裂处所言,在visualizationTools.cpp做订阅和发布接口=>在订阅的回调函数中完成数据的转换.

订阅:

ros::Subscriber subScan_new = nh.subscribe<sensor_msgs::LaserScan>("/2D_Lascan", 100, scanHandler_for_2DLadar);

回调函数:

        (回调函数由两部分组成,一部分从雷达数据laserscan转成pcl2,此时获得的是雷达坐标系下的(x,y)坐标;另一部分由原本scanHandler()函数中的代码构成,用于数据旋转平移到map坐标系下)

void scanHandler_for_2DLadar(const sensor_msgs::LaserScan::ConstPtr &input)
                                                                            //EXPL 这个承载行参的变量是指针还是对象是有讲究的,这个具体看订阅的时候的书写格式!
{
  // cloud.points.clear();
  cloud.clear();
  copy_cloud.clear();
  std::vector<float> ranges = input->ranges;
  cloud.points.resize(ranges.size());                                                     
                                      //??   这里给pcl2声明容量 
  cloud.width = ranges.size();
                                      //??   这里给pcl2 width,heighy赋值
  cloud.height = 1;
  cloud.header.stamp = input->header.stamp.toSec();
                                      //??   这里给pcl2时间戳赋值
  cloud.header.frame_id = "map";
                                      //??   这里给pcl2设置发送ID
  /*--------------这段进行"角度range"到(x,y)坐标的转换---------------*/
  //转换到二维XY平面坐标系下;
  // std::cout<<"cloud其他初始化"<<std::endl;
  for(int i=0; i< ranges.size(); i++)
  {                    
    double angle = input->angle_min + i * input->angle_increment;
    double lX = ranges[i] * cos(angle);
    double lY = ranges[i] * sin(angle);
    float intensity = input->intensities[i];
    cloud.points[i].x=lX;
    cloud.points[i].y=lY;
    cloud.points[i].z=0;
    cloud.points[i].intensity=1;
    //BUG 这个intensity注意  => 之后做显示如果能返回正确的intensity的话一定要使用到这个信息,不能直接赋值1
  }
  
  /*--------------这段进行"角度range"到(x,y)坐标的转换---------------*/

  /*------------------------这段给点云复制,多增加立体感end--------------------------##*/
  std::vector<int> mapping;
	pcl::removeNaNFromPointCloud(cloud, cloud, mapping);
                                                      //TAG 这里去除ranges里面的inf/NaN值不知道有没有用
  pcl::copyPointCloud(cloud,copy_cloud);
  for(int h=0;h<=20;h+=2)
  {
      for(int i=0;i<copy_cloud.points.size();i++)
      {
          copy_cloud.points[i].z=(float)h/10;
      }
      // std::cout<<"cloud_add.points[i].z: "<<(float)h/10<<std::endl;
      cloud+=copy_cloud;
  }
  /*------------------------这段给点云复制,多增加立体感end----------------------------##*/
  /*------------------------------------------------------------上面这段是2D雷达 => 本地(x,y)坐标系---------------------------------------------------------------------------------*/
  /*----------------------------------------------------下面这段是本地(x,y)坐标系 => 全局(x,y)坐标系---------------------------------------------------------------------------------*/
  if (!systemInited) {
    systemInitCount++;
    if (systemInitCount > systemDelay) {
      systemInited = true;
    }
    return;
  }

  double scanTime = cloud.header.stamp;

  if (odomSendIDPointer < 0)
  {
    return;
  }
  while (odomTimeStack[(odomRecIDPointer + 1) % stackNum] < scanTime &&
         odomRecIDPointer != (odomSendIDPointer + 1) % stackNum)
  {
    odomRecIDPointer = (odomRecIDPointer + 1) % stackNum;
  }

  double odomRecTime = odomTime.toSec();
  float vehicleRecX = vehicleX;
  float vehicleRecY = vehicleY;
  float vehicleRecZ = vehicleZ;
  float vehicleRecRoll = vehicleRoll;
  float vehicleRecPitch = vehiclePitch;
  float vehicleRecYaw = vehicleYaw;
  float terrainRecRoll = terrainRoll;
  float terrainRecPitch = terrainPitch;

  if (use_gazebo_time)
  {
    odomRecTime = odomTimeStack[odomRecIDPointer];
    vehicleRecX = vehicleXStack[odomRecIDPointer];
    vehicleRecY = vehicleYStack[odomRecIDPointer];
    vehicleRecZ = vehicleZStack[odomRecIDPointer];
    vehicleRecRoll = vehicleRollStack[odomRecIDPointer];
    vehicleRecPitch = vehiclePitchStack[odomRecIDPointer];
    vehicleRecYaw = vehicleYawStack[odomRecIDPointer];
    terrainRecRoll = terrainRollStack[odomRecIDPointer];
    terrainRecPitch = terrainPitchStack[odomRecIDPointer];
  }

  float sinTerrainRecRoll = sin(terrainRecRoll);
  float cosTerrainRecRoll = cos(terrainRecRoll);
  float sinTerrainRecPitch = sin(terrainRecPitch);
  float cosTerrainRecPitch = cos(terrainRecPitch);

  scanData->clear();
  // pcl::fromROSMsg(*scanIn, *scanData);                         
  pcl::copyPointCloud(cloud,*scanData);
  // ?? ##  1获取数据
  pcl::removeNaNFromPointCloud(*scanData, *scanData, scanInd);

  int scanDataSize = scanData->points.size();
  for (int i = 0; i < scanDataSize; i++)
  {
    float pointX1 = scanData->points[i].x;
    float pointY1 = scanData->points[i].y * cosTerrainRecRoll - scanData->points[i].z * sinTerrainRecRoll;
    float pointZ1 = scanData->points[i].y * sinTerrainRecRoll + scanData->points[i].z * cosTerrainRecRoll;

    float pointX2 = pointX1 * cosTerrainRecPitch + pointZ1 * sinTerrainRecPitch;
    float pointY2 = pointY1;
    float pointZ2 = -pointX1 * sinTerrainRecPitch + pointZ1 * cosTerrainRecPitch;

    float pointX3 = pointX2 + vehicleRecX;
    float pointY3 = pointY2 + vehicleRecY;
    float pointZ3 = pointZ2 + vehicleRecZ;

    scanData->points[i].x = pointX3;
    scanData->points[i].y = pointY3;
    scanData->points[i].z = pointZ3;
  }
  // ?? ##  2旋转平移处理
  // publish 5Hz registered scan messages
  
  scanData->is_dense=false;
  sensor_msgs::PointCloud2 scanData2;
  pcl::toROSMsg(*scanData, scanData2);                       //1.数据  2.时间戳
  scanData2.header.stamp = ros::Time().fromSec(odomRecTime);
  scanData2.header.frame_id = "map";
  pubScanPointer_new->publish(scanData2);
  // ?? ##  3发布
}

发布pcl2:

scanData->is_dense=false;
sensor_msgs::PointCloud2 scanData2;
pcl::toROSMsg(*scanData, scanData2);                       //1.数据  2.时间戳
scanData2.header.stamp = ros::Time().fromSec(odomRecTime);
scanData2.header.frame_id = "map";
pubScanPointer_new->publish(scanData2);

三.数据流动过程(效果)

gazebo(urdf) => 发布话题frame"2D_Ladar",topic"/2D_Lascan" => 节点vehicleSimulator(也就是上面那个.cpp)订阅 => 回调函数scanHandler_for_2DLadar  => 回调函数中laserscan->pcl2  => 回调函数中发布到/registered_scan  

图1.urdf发布的2D数据laserscan

 

 图2.节点vehicleSimulator上laserscan转pcl2

 图3.节点上z轴方向上复制堆叠并发布到/registered_scan 

​​​​​​​

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值