前言
前面的所有教程已经完全足够你上手修改模型和自己写Python脚本来驱动小车了,这里因为单片机主要还是支持c语言,所以这一节讲下用c++来驱动。
注意!这一章节由于我debug过程略微有点曲折,可能中间细节没记录,大家有问题在评论区留言,我会提供解决方案!!!
创建cpp程序包
cd ~/smartcar_ws/src
catkin_create_pkg buptsmartcar_cpp roscpp geometry_msgs cv_bridge image_transport
Tips:
· 程序包名,buptsmartcar_cpp;依赖消息类型roscpp和geometry_msgs,cv_bridge,image_transport
· 这里可以看到src下多了个文件夹buptsmartcar_cpp:
准备
安装opencv
sudo apt-get install libopencv-dev
修改CMakeList.txt文件(这就是用c++的麻烦之处)
sudo gedit ~/smartcar_ws/src/buptsmartcar_cpp/CMakeLists.txt
CMakeLists.txt如下(这里我把所有的注释都删了,实在太长了)你们把他复制进去替换你的内容:
cmake_minimum_required(VERSION 2.8.3)
project(buptsmartcar_cpp)
set(OpenCV_DIR /opt/ros/kinetic/share/OpenCV-3.3.1-dev/)
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
OpenCV
roscpp
cv_bridge
image_transport
)
catkin_package(
)
include_directories(
${catkin_INCLUDE_DIRS}
${OpenCV_INCLUDE_DIRS}
)
add_executable(findLine src/findLine.cpp)
target_link_libraries(findLine
${catkin_LIBRARIES}
${OpenCV_LIBRARIES}
)
add_dependencies(findLine findLine_tutorials_generate_messages_cpp)
创建cpp巡线文件
gedit ~/smartcar_ws/src/buptsmartcar_cpp/src/findLine.cpp
findLine.cpp如下(解释见代码注释):
#include <ros/ros.h>
#include <stdio.h>
#include "std_msgs/Float64.h"
#include "sensor_msgs/Image.h"
#include "geometry_msgs/Twist.h"
#include <opencv-3.3.1-dev/opencv2/core.hpp>
#include <opencv-3.3.1-dev/opencv/highgui.h>
#include <opencv-3.3.1-dev/opencv2/opencv.hpp>
#include "cv_bridge/cv_bridge.h"
#include<sensor_msgs/image_encodings.h>
#include<image_transport/image_transport.h>
using namespace cv;//opencv的名字空间
//巡线的类
class Follower{
public:
ros::NodeHandle node;//ros节点
static ros::Publisher cmdpub;//发布速度
static ros::Subscriber imageSub;//订阅传感器图片
//图片处理的回调函数
static void image_callback(const sensor_msgs::ImageConstPtr& msg);
//速度控制函数
static void speed_contrl(float speed_car,float angular_car);
//类的构造函数
Follower();
};
//初始化静态成员变量
ros::Publisher Follower::cmdpub;
ros::Subscriber Follower::imageSub;
//main
int main(int argc, char* argv[])
{
//初始化节点
ros::init(argc,argv,"follower_cpp");
//调用构造函数
Follower f;
//ros机制,程序不退出一直执行回调函数
ros::spin();
}
//传感器图片回调函数
void Follower::image_callback(const sensor_msgs::ImageConstPtr& msg)
{
//定义从ros图片转成opencv图片的指针
cv_bridge::CvImagePtr cv_ptr;
//捕获异常
try
{
//将ros图片转换成opencv支持的类型
cv_ptr = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
}
catch(cv_bridge::Exception& e)//处理异常
{
ROS_ERROR("cv_bridge exception: %s", e.what());
return;
}
//定义两个Mat变量来使用
Mat hsv = cv_ptr->image.clone();
Mat mask = cv_ptr->image.clone();
//原图转成hsv图
cvtColor(cv_ptr->image, hsv, COLOR_BGR2HSV);
//hsv参数
double low_H = 0;
double low_S = 0;
double low_V = 221;
double high_H = 180;
double high_S = 30;
double high_V = 255;
//从hsv中提取白色
inRange(hsv, Scalar(low_H, low_S, low_V), Scalar(high_H, high_S, high_V), mask);
//------------!!!这里写你的图像处理函数!!!------------//
//处理结果输出给速度控制
speed_contrl(0.2,0.2);
//就是想show一下
imshow("mask",mask);
waitKey(3);
}
//速度控制函数
void Follower::speed_contrl(float speed_car,float angular_car)
{
//配置参数
geometry_msgs::Twist twist;
geometry_msgs::Vector3 linear;
linear.x=speed_car;
linear.y=0;
linear.z=0;
geometry_msgs::Vector3 angular;
angular.x=0;
angular.y=0;
angular.z=angular_car;
twist.linear=linear;
twist.angular=angular;
//发布速度
cmdpub.publish(twist);
}
//构造函数
Follower::Follower()
{
//给静态成员赋值
cmdpub = node.advertise<geometry_msgs::Twist>("cmd_vel", 10, true);
imageSub = node.subscribe("camera/image_raw",10,image_callback);
}
编译工程
这里要非常非常注意了!!!!,cpp文件和Python不一样,写c++程序你做了一点修改你就必须去编译一下
cd ~/smartcar_ws
catkin_make
source ./devel/setup.bash
这样就ok了
运行程序
rosrun buptsmartcar_cpp findLine
这里也要注意了,findLine是不用加.cpp的哈
效果如下:
这很明显是我的hsv参数设置的不太好,这里就是个演示效果就不去细细调整了。
上面写的程序就是让小车原地旋转哈,没有加上巡线的代码,就把之前的python脚本翻译了一下,大家可以自己扩展。
结束