数据预处理(18)_将单线激光雷达的LaserScan数据从极坐标下转到笛卡尔坐标系并存储

方法1:

void AutoGetLine::TransScanToPoints(const sensor_msgs::LaserScan& scan_in,std::vector<Eigen::Vector3d>& Points)
{
    size_t pts_num=scan_in.ranges.size();
    Eigen::ArrayXXd ranges_d(pts_num,2);//pt_num行,2列
    Eigen::ArrayXXd output_xy(pts_num,2);
    Eigen::ArrayXXd angle(pts_num,2);
    for(size_t i=0;i<pts_num;i++)
    {
        ranges_d(i,0)=(double)scan_in.ranges[i];//距离
        ranges_d(i,1)=(double)scan_in.ranges[i];//距离
        angle(i,0)=cos(scan_in.angle_min+(double)i*scan_in.angle_increment);
        angle(i,1)=sin(scan_in.angle_min+(double)i*scan_in.angle_increment);
    }
    output_xy=ranges_d*angle;
    for(size_t i=0;i<pts_num;i++)
    {
        double range_cutoff=10;//假设有效距离10m
        const float range=scan_in.ranges[i];
        if(range<range_cutoff&& range>scan_in.range_min)
            Points.push_back(Eigen::Vector3d(output_xy(i,0),output_xy(i,1),0));
        else
            Points.push_back(Eigen::Vector3d(1000.0,1000.0,0));
        }
    }
}

方法2:这里转换的方式非常巧妙,先是把第一帧激光线按照角度划分,然后给定相应角度的索引值,激光测量的距离值直接按照索引值对应的角度、正余弦即可计算出笛卡尔坐标系下的X、Y。

//数据结构
struct CachedData
{
  std::vector<unsigned int> indices;
  std::vector<double> bearings;
  std::vector<double> cos_bearings;
  std::vector<double> sin_bearings;
};

struct RangeData
{
  std::vector<double> ranges;
  std::vector<double> xs;
  std::vector<double> ys;
};
//数据设置
void LineExtraction::setCachedData(const std::vector<double>& bearings,
                                   const std::vector<double>& cos_bearings,
                                   const std::vector<double>& sin_bearings,
                                   const std::vector<unsigned int>& indices)
{
  c_data_.bearings = bearings;
  c_data_.cos_bearings = cos_bearings;
  c_data_.sin_bearings = sin_bearings;
  c_data_.indices = indices;
}

void LineExtraction::setRangeData(const std::vector<double>& ranges)
{
  r_data_.ranges = ranges;
  r_data_.xs.clear();
  r_data_.ys.clear();
  for (std::vector<unsigned int>::const_iterator cit = c_data_.indices.begin(); cit != c_data_.indices.end(); ++cit)
  {
    r_data_.xs.push_back(c_data_.cos_bearings[*cit] * ranges[*cit]);
    r_data_.ys.push_back(c_data_.sin_bearings[*cit] * ranges[*cit]);
  }
}
//缓存第一帧数据
void LineExtractionROS::cacheData(const sensor_msgs::LaserScan::ConstPtr &scan_msg)
{
  std::vector<double> bearings, cos_bearings, sin_bearings;
  std::vector<unsigned int> indices;
  const std::size_t num_measurements = std::ceil((scan_msg->angle_max - scan_msg->angle_min) / scan_msg->angle_increment);
  for (std::size_t i = 0; i < num_measurements; ++i)
  {
    const double b = scan_msg->angle_min + i * scan_msg->angle_increment;
    bearings.push_back(b);
    cos_bearings.push_back(cos(b));
    sin_bearings.push_back(sin(b));
    indices.push_back(i);
  }

  line_extraction_.setCachedData(bearings, cos_bearings, sin_bearings, indices);
  ROS_DEBUG("Data has been cached.");
}

//laserscan的回调函数
void LineExtractionROS::laserScanCallback(const sensor_msgs::LaserScan::ConstPtr &scan_msg)
{
  if (!data_cached_)//因为每一帧数据角度的变化是固定的,只运行一次作缓存即可
  {
    cacheData(scan_msg); 
    data_cached_ = true;
  }
  std::vector<double> scan_ranges_doubles(scan_msg->ranges.begin(), scan_msg->ranges.end());
  line_extraction_.setRangeData(scan_ranges_doubles);
}
  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是一个示例代码,它将激光雷达数据和图像数据进行同步,然后将同步的数据保存到硬盘上。 ```python import rospy from sensor_msgs.msg import LaserScan, Image from cv_bridge import CvBridge import cv2 class ImageAndLaserSync: def __init__(self): self.bridge = CvBridge() self.image_sub = rospy.Subscriber("/camera/image", Image, self.image_callback) self.laser_sub = rospy.Subscriber("/laser_scan", LaserScan, self.laser_callback) self.image_data = None self.laser_data = None def image_callback(self, data): self.image_data = data def laser_callback(self, data): self.laser_data = data def save_sync_data(self): if self.image_data is not None and self.laser_data is not None: image = self.bridge.imgmsg_to_cv2(self.image_data, "bgr8") laser = self.laser_data.ranges # 在这里进行图像和激光雷达数据的处理 # ... # 保存同步数据 cv2.imwrite("sync_data.png", image) with open("sync_data.txt", "w") as f: for i, r in enumerate(laser): f.write("{} {}\n".format(i, r)) if __name__ == "__main__": rospy.init_node("image_and_laser_sync") sync = ImageAndLaserSync() rate = rospy.Rate(10) while not rospy.is_shutdown(): sync.save_sync_data() rate.sleep() ``` 在这个示例中,我们订阅了一个 `/camera/image` 话题和一个 `/laser_scan` 话题,分别用于获取图像数据激光雷达数据。当两个话题都收到数据后,我们将它们进行处理,并将同步的数据保存到硬盘上。 注意,我们使用了 `cv_bridge` 库将 ROS 图像消息转换为 OpenCV 图像格式,这使得我们可以方便地进行图像数据的处理。另外,我们还将激光雷达数据保存为文本文件,每行包含一个数据点的角度和距离。这应该足以满足大多数应用程序的需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值