一、ROS通信编程
①工作空间
1、创建工作空间
mkdir -p ~/catkin_ws/src#创建文件夹
cd ~/catkin_ws/src#进入目录
catkin_init_workspace#初始化,使其成为ROS的工作
2、编译工作空间
cd ..
catkin_make
3、设置环境变量
source /home/lyy/catkin_ws/devel/setup.bash#该环境变量设置只对当前终端有效,lyy是用户名
#将上面命令放置到~/.bashrc文件中,让其对所有终端都有效
sudo nano ~/.bashrc
4、检查环境变量
echo $ROS_PACKAGE_PATH
②功能包
cd ~/catkin_ws/src
catkin_create_pkg learning_communication std_msgs rospy roscpp
#catkin_create_pkg 功能包名字 依赖
#std_msgs:定义的标准的数据结构
#rospy:提供python编程接口
#roscpp:提供c++编程接口
2、编译功能包
cd ~/catkin_ws
catkin_make
在同一个工作空间下,不允许存在同名的功能包
不同工作空间,可以存在同名的功能包
③ROS通信编程
1、话题编程
步骤:
- 创建发布者
1、初始化ROS节点
2、向ROS Master注册节点信息,包括发布的话题名和话题中的消息类型
3、按照一定频率循环发布消息 - 创建订阅者
1、初始化ROS节点
2、订阅需要的话题
3、循环等待话题消息,接受到消息后进行回调函数
4、回调函数中完成消息处理 - 添加编译选项
1、设置需要编译的代码和生成的可执行文件
2、设置链接库
3、设置依赖 - 运行可执行程序
talker.cpp
#include<sstream>
#include"ros/ros.h"
#include"std_msgs/String.h"
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"talker");
//创建节点句柄
ros::NodeHandle n;
//创建一个Publisher,发布名为chatter的topic,消息类型为std_msgs::String
ros::Publisher chatter_pub=n.advertise<std_msgs::String>("chatter",1000);
//设置循环的频率
ros::Rate loop_rate(10);
int count=0;
while(ros::ok())
{
//初始化std_msgs::String类型的消息
std_msgs::String msg;
std::stringstream ss;
ss<<"hello world"<<count;
msg.data=ss.str();
//发布消息
ROS_INFO("%s",msg.data.c_str());
chatter_pub.publish(msg);
//循环等待回调函数
ros::spinOnce();
//接受循环频率延时
loop_rate.sleep();
++count;
}
return 0;
}
listener.cpp
#include"ros/ros.h"
#include"std_msgs/String.h"
//接收到订阅的消息,会进入消息的回调函数
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
//将接收到的消息打印处理
ROS_INFO("I heard:{%s}",msg->data.c_str());
}
int main(int argc,char **argv)
{
//初始化ROS节点
ros::init(argc,argv,"listener");
//创建节点句柄
ros::NodeHandle n;
//创建一个Subscriber,订阅名为chatter的topic,注册回调函数chatterCallback
ros::Subscriber sub=n.subscribe("chatter",1000,chatterCallback);
//循环等待回调函数
ros::spin();
return 0;
}
设置CMakeLists.txt文件
编译
运行可执行文件
roscore
rosrun learning_communication talker
rosrun learning_communication listener
2、服务编程
定义服务请求与应答的方式
定义srv文件
mkdir ~/catkin_ws/src/learning_communication/srv
sudo nano AddTwoInts.srv
AddTwoInts.srv
int64 a
int64 b
---
int64 sum
在package.xml中添加功能包依赖
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
进入CMakeLists.txt
找到
find_package(catkin REQUIRED COMPONENTS
在下面添加:
message_generation
找到
# add_service_files(
# FILES
# Service1.srv
# Service2.srv
# )
替换为
add_service_files(
FILES
AddTwoInts.srv
)
找到
# generate_messages(
# DEPENDENCIES
# # std_msgs # Or other packages containing msgs
# )
替换为
generate_messages(
DEPENDENCIES
std_msgs
)
重新编译
cd ~/catkin_ws
catkin_make -DCATKIN_WHITELIST_PACKAGES="service_example"
编写代码
进入service_example,新建scripts
cd ~/catkin_ws/src/service_example
mkdir scripts
创建server.cpp
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
//service回调函数,输入参数req,输出参数res
bool add(learning_communication::AddTwoInts::Request &req,learning_communication::AddTwoInts::Response &res)
{
//将输入的参数中的请求数据相加,结果放到应答变量中
res.sum=req.a+req.b;
ROS_INFO("request: x=%1d,y=%1d",(long int)req.a,(long int)req.b);
ROS_INFO("sending back response:[%1d]",(long int)res.sum);
return true;
}
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"add_two_ints_server");
//创建节点句柄
ros::NodeHandle n;
//创建一个名为add_two_ints的server,注册回调函数add()
ros::ServiceServer service=n.advertiseService("add_two_ints",add);
//循环等待回调函数
ROS_INFO("Ready to add two ints.");
ros::spin();
return 0;
}
创建client.cpp
#include<cstdlib>
#include<ros/ros.h>
#include"learning_communication/AddTwoInts.h"
int main(int argc,char **argv)
{
//ROS节点初始化
ros::init(argc,argv,"add_two_ints_client");
//从终端命令行获取两个加数
if(argc!=3)
{
ROS_INFO("usage:add_two_ints_client X Y");
return 1;
}
//创建节点句柄
ros::NodeHandle n;
//创建一个client,请求add_two_ints_service
//service消息类型是learning_communication::AddTwoInts
ros::ServiceClient client=n.serviceClient<learning_communication::AddTwoInts>("add_two_ints");
//创建learning_communication::AddTwoInts类型的service消息
learning_communication::AddTwoInts srv;
srv.request.a=atoll(argv[1]);
srv.request.b=atoll(argv[2]);
//发布service请求,等待加法运算的应答请求
if(client.call(srv))
{
ROS_INFO("sum: %1d",(long int)srv.response.sum);
}
else
{
ROS_INFO("Failed to call service add_two_ints");
return 1;
}
return 0;
}
授权
chmod ~/catkin_ws/src/service_example/scripts/*.cpp
编译
cd ~/catkin_ws
catkin_make -DCATKIN_WHITELIST_PACKAGES="service_example"
运行
roscore
运行
source ~/catkin_ws/devel/setup.bash
rosrun service_example server.cpp
source ~/catkin_ws/devel/setup.bash
rosrun service_example client.cpp 1 3
二、opencv库编写打开摄像头压缩视频的程序
准备工作
安装opencv
一张图片
3.0 安装opencv
① 安装opencv依赖库
sudo apt-get install build-essential libgtk2.0-dev libgtk-3-dev libavcodec-dev libavformat-dev libjpeg-dev libswscale-dev libtiff5-dev
安装库
# python3支持(首次安装了python的库,但make报错了,之后删了这两个库,若不使用python,建议不安装)
sudo apt install python3-dev python3-numpy
# streamer支持
sudo apt install libgstreamer-plugins-base1.0-dev libgstreamer1.0-dev
# 可选的依赖
sudo apt install libpng-dev libopenexr-dev libtiff-dev libwebp-dev
③ 下载openCV 4.5源文件
# 安装4.5.0版本
wget -O opencv.zip https://github.com/opencv/opencv/archive/4.5.0.zip
④ 把里面的opencv4.5解压到主目录,并改名为opencv
⑤ Cmake配置和编译openCV
进入目录,新建目录build
cd opencv
mkdir build
cd build
用cmake配置opencv
cmake -D CMAKE_BUILD_TYPE=Release -D OPENCV_GENERATE_PKGCONFIG=YES ..
用make进行编译
make -j4
…
用make进行编译
make -j4
用make进行安装
sudo make install
⑥ 配置环境
首先找到opencv4.pc的路径
sudo find / -iname opencv4.pc
打开PKG_CONFIG_PATH:
sudo vim /etc/profile.d/pkgconfig.sh
将找到的opencv4.pc的路径赋值进去
然后在末端加入:
export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig:$PKG_CONFIG_PATH
保存后激活
# 激活
source /etc/profile
激活后可以用以下指令验证
pkg-config --libs opencv4
⑦ 配置动态库环境
打开文件
sudo vim /etc/ld.so.conf.d/opencv4.conf
在文件末尾加入
/usr/local/lib
这是opencv的lib路径
加入后保存退出,激活路径
sudo ldconfig
然后测试一下是否安装成功
cd ~/opencv/samples/cpp/example_cmake
cmake .
make
./opencv_example
3.1
① 新建 test1.cpp
mkdir test1.cpp
按“i”进入输入模式
输入代码
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// 读取图像
Mat image = imread("image.jpg");
// 检查图像是否成功加载
if (image.empty()) {
cout << "无法读取图像文件,请确保路径正确" << endl;
return -1;
}
// 显示原始图像
imshow("Original Image", image);
// 灰度化
Mat gray_image;
cvtColor(image, gray_image, COLOR_BGR2GRAY);
// 显示灰度图像
imshow("Grayscale Image", gray_image);
// 边缘检测
Mat edges;
Canny(gray_image, edges, 50, 150);
// 显示边缘图像
imshow("Edge Detected Image", edges);
// 图像模糊
Mat blurred_image;
GaussianBlur(image, blurred_image, Size(5, 5), 0);
// 显示模糊图像
imshow("Blurred Image", blurred_image);
// 等待按键
waitKey(0);
return 0;
}
② 编译运行
g++ test1.cpp -o test1 `pkg-config --cflags --libs opencv4`
./text1
请解释这条编译命令,它是如何获得opencv头文件、链接lib库文件的路径的?
g++ test1.cpp -o test1 pkg-config --cflags --libs opencv4
这条编译命令使用了pkg-config
工具来获取OpenCV4库的编译选项。具体来说,pkg-config --cflags --libs opencv4
这部分命令获取了OpenCV4库的头文件路径和链接库文件路径,然后传递给编译器g++
。这样编译器就知道应该在哪里查找OpenCV4的头文件和链接OpenCV4的库文件。整条命令最终将test1.cpp
编译成一个可执行文件test1
。
3.2 练习使用opencv库编写打开摄像头压缩视频的程序
准备工作
检查虚拟机摄像头是否可用
准备一个视频
① 练习示例代码一
编译运行此代码
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
VideoCapture capture("sion.mp4");//记得替换为视频名称
if (!capture.isOpened()) {
cerr << "Error: Failed to open camera." << endl;
return -1;
}
while (true)
{
Mat frame;
capture >> frame;
if (frame.empty()) {
cerr << "Error: Failed to capture frame." << endl;
break;
}
imshow("Read Video", frame);
if (waitKey(30) >= 0) break;
}
return 0;
}
参考链接
https://blog.youkuaiyun.com/qq_43279579/article/details/114764633
https://blog.youkuaiyun.com/qq_42451251/article/details/104664926