目录
b. 打开VScode在你创建的软件包下的src目录书写代码,然后在VScode里面编译
d.修改CMakeLists.txt文件,在最下面添加如下代码(代码的基本形式在文件中都存在):
代码传送门:
https://github.com/2004062882604002/ROS.githttps://github.com/2004062882604002/ROS.git
安装ubuntu虚拟机
版本号:ubuntu 20.04
安装方法:参考小鱼(鱼香ROS)的教程
提醒:小鱼的安装教程中的ubuntu版本是22.04,20.04的的镜像:
1.ubuntu官网查找
2.小鱼的网址将22.04更改20.04
虚拟机基本设置
A. 切换中文界面
a. settings
b.Language
B. 中文输入法
安装ROS
版本:ROS1_Noetic
安装方法:参考小鱼(鱼香ROS)的一键安装(极其简且无脑操作)
wget http://fishros.com/install -O fishros && . fishros
Ubuntu_Visual Studio Code
可参考视频教程(机器人工匠):
下载VScode:
Ubuntu_Terminator
可参考视频教程(机器人工匠):
sudo apt install terminator
前期准备
编译实例代码
可参考视频教程(机器人工匠):
需全部看完并执行
DO
A. 上传Bag到虚拟机
简单粗暴的方法:用移动硬盘接入虚拟机
其他方法:使用百度网盘,或其他
B. 查看Bag包数据
rosbag info all.bag
需要关注的即是:topics
我们要订阅他
C. 命令行窗口显示小车的IMU
思路:创建节点,运行节点实现功能
a.创建软件包
catkin_create_pkg imu_read std_msgs rospy roscpp sensor_msgs rosbag
b. 打开VScode在你创建的软件包下的src目录书写代码,然后在VScode里面编译
c.代码
#include <ros/ros.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <sensor_msgs/Imu.h>
int main(int argc, char** argv)
{
// 初始化 ROS 节点
ros::init(argc, argv, "bag_imu_reader");
ros::NodeHandle nh;
// 打开 ROSBAG 文件
rosbag::Bag bag;
bag.open("your_bag_file.bag", rosbag::bagmode::Read); //修改bag地址
// 创建一个 View,用于获取指定话题的消息
rosbag::View view(bag, rosbag::TopicQuery("/imu_topic")); //订阅的话题名称
// 遍历 ROSBAG 中的消息
for (const rosbag::MessageInstance& msg : view)
{
// 检查消息类型是否为 IMU 消息
if (msg.isType<sensor_msgs::Imu>())
{
// 将消息转换为 IMU 消息类型
sensor_msgs::Imu::ConstPtr imu_msg = msg.instantiate<sensor_msgs::Imu>();
// 在命令行中打印 IMU 数据
std::cout << "Timestamp: " << imu_msg->header.stamp << std::endl;
std::cout << "Angular Velocity (x, y, z): " << imu_msg->angular_velocity.x << ", "
<< imu_msg->angular_velocity.y << ", " << imu_msg->angular_velocity.z << std::endl;
std::cout << "Linear Acceleration (x, y, z): " << imu_msg->linear_acceleration.x << ", "
<< imu_msg->linear_acceleration.y << ", " << imu_msg->linear_acceleration.z << std::endl;
std::cout << "Orientation (x, y, z, w): " << imu_msg->orientation.x << ", "
<< imu_msg->orientation.y << ", " << imu_msg->orientation.z << ", "
<< imu_msg->orientation.w << std::endl;
std::cout << "----------------------------------" << std::endl;
}
}
// 关闭 ROSBAG 文件
bag.close();
return 0;
}
d.修改CMakeLists.txt文件,在最下面添加如下代码(代码的基本形式在文件中都存在):
实例代码:
# add_executable(${PROJECT_NAME}_node src/imu_read_node.cpp)
# target_link_libraries(${PROJECT_NAME}_node
# ${catkin_LIBRARIES}
# )
修改代码:
add_executable(bag_imu_reader src/bag_imu_reader.cpp)
target_link_libraries(bag_imu_reader
${catkin_LIBRARIES}
)
e.实现效果
D. 里程计(Odometry)
步骤与上面完全一样,更改一下代码
依赖:
roscpp nav_msgs rosbag
代码:
#include <ros/ros.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <nav_msgs/Odometry.h>
int main(int argc, char** argv)
{
// 初始化 ROS 节点
ros::init(argc, argv, "bag_odometry_reader");
ros::NodeHandle nh;
// 打开 ROSBAG 文件
rosbag::Bag bag;
bag.open("your_bag_file.bag", rosbag::bagmode::Read);
// 创建一个 View,用于获取指定话题的消息
rosbag::View view(bag, rosbag::TopicQuery("/odom_topic"));
// 遍历 ROSBAG 中的消息
for (const rosbag::MessageInstance& msg : view)
{
// 检查消息类型是否为 Odometry 消息
if (msg.isType<nav_msgs::Odometry>())
{
// 将消息转换为 Odometry 消息类型
nav_msgs::Odometry::ConstPtr odom_msg = msg.instantiate<nav_msgs::Odometry>();
// 在命令行中打印 Odometry 数据
std::cout << "Timestamp: " << odom_msg->header.stamp << std::endl;
std::cout << "Position (x, y, z): " << odom_msg->pose.pose.position.x << ", "
<< odom_msg->pose.pose.position.y << ", " << odom_msg->pose.pose.position.z << std::endl;
std::cout << "Orientation (x, y, z, w): " << odom_msg->pose.pose.orientation.x << ", "
<< odom_msg->pose.pose.orientation.y << ", " << odom_msg->pose.pose.orientation.z << ", "
<< odom_msg->pose.pose.orientation.w << std::endl;
std::cout << "Linear Velocity (x, y, z): " << odom_msg->twist.twist.linear.x << ", "
<< odom_msg->twist.twist.linear.y << ", " << odom_msg->twist.twist.linear.z << std::endl;
std::cout << "Angular Velocity (x, y, z): " << odom_msg->twist.twist.angular.x << ", "
<< odom_msg->twist.twist.angular.y << ", " << odom_msg->twist.twist.angular.z << std::endl;
std::cout << "----------------------------------" << std::endl;
}
}
// 关闭 ROSBAG 文件
bag.close();
return 0;
}
实现效果:
E. 颜色相机和深度相机
与上面相同
依赖:
sensor_msgs OpenCV cv_bridge rosbag
代码:
#include <ros/ros.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <sensor_msgs/CameraInfo.h>
#include <sensor_msgs/Image.h>
#include <opencv2/opencv.hpp>
#include <cv_bridge/cv_bridge.h>
int main(int argc, char** argv)
{
// 初始化ROS节点
ros::init(argc, argv, "camera_info_display");
ros::NodeHandle nh;
// 创建ROSbag对象并打开文件
rosbag::Bag bag;
bag.open("/home/robot/all.bag", rosbag::bagmode::Read);
// 定义需要读取的话题
std::vector<std::string> topics = {"/camera/color/camera_info", "/camera/color/image_raw"};
// 创建ROSbag视图对象,并设置话题过滤器
rosbag::View view(bag, rosbag::TopicQuery(topics));
// 创建OpenCV窗口
cv::namedWindow("Camera Image");
// 遍历ROSbag中的消息
for (const rosbag::MessageInstance& msg : view)
{
// 检查消息类型是否为CameraInfo
if (msg.getDataType() == "sensor_msgs/CameraInfo")
{
sensor_msgs::CameraInfo::ConstPtr camera_info = msg.instantiate<sensor_msgs::CameraInfo>();
// 在命令行中显示CameraInfo信息
ROS_INFO_STREAM("CameraInfo: " << *camera_info);
}
// 检查消息类型是否为图像数据
else if (msg.getDataType() == "sensor_msgs/Image")
{
sensor_msgs::Image::ConstPtr image = msg.instantiate<sensor_msgs::Image>();
// 将图像数据转换为OpenCV格式
cv_bridge::CvImagePtr cv_image;
try
{
cv_image = cv_bridge::toCvCopy(image, image->encoding);
}
catch (cv_bridge::Exception& e)
{
ROS_ERROR("cv_bridge exception: %s", e.what());
continue;
}
// 显示图像
cv::imshow("Camera Image", cv_image->image);
// 等待用户按下ESC键退出
if (cv::waitKey(1) == 27)
break;
}
}
// 关闭ROSbag文件
bag.close();
return 0;
}
F.雷达点云
基本上相同,就是修改CMakeLists.txt文件有差异
依赖:
pcl rosbag sensor_msgs
代码:
#include <ros/ros.h>
#include <rosbag/bag.h>
#include <rosbag/view.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl_conversions/pcl_conversions.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
int main(int argc, char** argv)
{
// 初始化ROS节点
ros::init(argc, argv, "laser_scan_display");
ros::NodeHandle nh;
// 创建ROSbag对象并打开文件
rosbag::Bag bag;
bag.open("/home/robot/all.bag", rosbag::bagmode::Read);
// 定义需要读取的话题
std::vector<std::string> topics = {"/scan"};
// 创建ROSbag视图对象,并设置话题过滤器
rosbag::View view(bag, rosbag::TopicQuery(topics));
// 创建PCL可视化对象
pcl::visualization::PCLVisualizer viewer("Laser Scan");
// 遍历ROSbag中的消息
for (const rosbag::MessageInstance& msg : view)
{
// 检查消息类型是否为PointCloud2
if (msg.getDataType() == "sensor_msgs/PointCloud2")
{
sensor_msgs::PointCloud2::ConstPtr cloud_msg = msg.instantiate<sensor_msgs::PointCloud2>();
// 创建PCL点云对象并从ROS消息中填充数据
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromROSMsg(*cloud_msg, *cloud);
// 在PCL可视化对象中添加点云数据
viewer.addPointCloud(cloud, "cloud");
// 更新PCL可视化窗口
viewer.spinOnce();
}
}
// 关闭ROSbag文件
bag.close();
// 显示点云并保持窗口打开
viewer.spin();
return 0;
}
CMakeLists.txt文件:
cmake_minimum_required(VERSION 3.0.2)
project(my_pcl)
find_package(catkin REQUIRED COMPONENTS
pcl_conversions
pcl_ros
rosbag
roscpp
sensor_msgs
)
find_package(PCL REQUIRED)
catkin_package()
include_directories(
${catkin_INCLUDE_DIRS}
${PCL_INCLUDE_DIRS}
)
link_directories(
${PCL_LIBRARY_DIRS}
)
add_executable(laser_scan_display src/laser_scan_display.cpp)
target_link_libraries(laser_scan_display
${catkin_LIBRARIES}
${PCL_LIBRARIES}
)