鱼香ROS官网:https://fishros.com/ (鱼神!)

生成 install 文件:catkin_make install

功能包命名:要小写开头,不然会报警告⚠

ROS + Vscode 配置:
http://t.csdnimg.cn/X34DS

中转节点在ROS中的使用

创建工作空间&功能包

理论上工作空间在任何文件夹中可以建立,为了保证组织性和环境配置的简化,一般都位于主目录下建立:

1
2
3
4
5
6
7
8
9
10
11
mkdir workspace #名字可以随意 
cd workspace #进入文件夹
mkdir src
cd src
catkin_init_workspace
cd ..
catkin_make
cd src
catkin_create_pkg Test_pkg roscpp rospy std_msgs
cd ..
catkin_make

环境变量

单次添加

1
2
cd workspace
source ./devel/setup.bash

多次添加

1
2
3
vi|gedit ~/.bashrc
#最后一行添加
source ~/workspace/devel/setup.bash

消息类型

sensor_msgs::Imu

can_msgs/Frame

ROS—CAN 通信思考

注意:在ROS中,接受CAN报文是一种主动的行为,需要不断定期的读取;

思考:实时性 不断读取造成的开销

解决方案:

可以使用低延迟的通讯协议CAN FD

编写一种能够实现中断的功能 (ing)

多线程处理: 如下(可扩展思路)

ROS 相关写法

ROS 多线程

消息回调函数:

ros::spin() ros::spinOnce()

1
2
3
4
5
6
7
8
/**
* The MultiThreadedSpinner object allows you to specify a number of threads to use
* to call callbacks. If no explicit # is specified, it will use the # of hardware
* threads available on your system. Here we explicitly specify 4 threads.
*/
ros::MultiThreadedSpinner s(4);
ros::spin(s);

sync(同步)

官方demo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <message_filters/subscriber.h>
#include <message_filters/time_synchronizer.h>
#include <sensor_msgs/Image.h>
#include <sensor_msgs/CameraInfo.h>

using namespace sensor_msgs;
using namespace message_filters;

void callback(const ImageConstPtr& image, const CameraInfoConstPtr& cam_info)
{
// Solve all of perception here...
}

int main(int argc, char** argv)
{
ros::init(argc, argv, "vision_node");

ros::NodeHandle nh;

message_filters::Subscriber<Image> image_sub(nh, "image", 1);
message_filters::Subscriber<CameraInfo> info_sub(nh, "camera_info", 1);
TimeSynchronizer<Image, CameraInfo> sync(image_sub, info_sub, 10);
sync.registerCallback(boost::bind(&callback, _1, _2));

ros::spin();

return 0;
}

Async(异步)

异步线程处理,同时拥有start() 和stop() 函数,并且在销毁的时候会自动停止。

1
2
ros::AsyncSpinner s(4);
s.start();

callback

写法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Listener
{
public:
ros::NodeHandle node_handle_;
ros::V_Subscriber subs_;

Listener(const ros::NodeHandle& node_handle): node_handle_(node_handle)
{
}

void init()
{
subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 1")));
subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 2")));
subs_.push_back(node_handle_.subscribe<std_msgs::String>("chatter", 1000, boost::bind(&Listener::chatterCallback, this, _1, "User 3")));
}

void chatterCallback(const std_msgs::String::ConstPtr& msg, std::string user_string)
{
ROS_INFO("I heard: [%s] with user string [%s]", msg->data.c_str(), user_string.c_str());
}
};

int main(int argc, char **argv)
{
ros::init(argc, argv, "listener_with_userdata");
ros::NodeHandle n;

Listener l(n);
l.init();

ros::spin();

return 0;
}

定时器

1
ros::Timer timer = x.createTimer(ros::Duration(时间),callback);

JsonCpp库

安装依赖库:

1
2
3
 sudo apt-get install ros-<distro>-jsoncpp
~~~S
示例:

#include <jsoncpp/json/json.h>

Json::CharReaderBuilder readerBuilder;
Json::Value root;
std::string errs;

std::string jsonString = msg->data.c_str();
std::istringstream ss(jsonString);

if (Json::parseFromStream(readerBuilder, ss, &root, &errs)) 
{
    // 提取字段
    std::string imei = root["imei"].asString();
    std::string msgId = root["msgId"].asString();
    std::string controlType = root["controlType"].asString();

}

ros开机自启动

以下两种方案都基于bash脚本文件,首先我们先生成编写脚本文件:

1
2
3
sudo nano ros_start.sh

sudo vi ros_start.sh

编写脚本内容(例):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
#author Tree
#description:TEST

sleep 5s #此处要多做等待,等待系统接口都正常运行

PASSWORD="*****"

echo "$PASSWORD" | sudo -S chmod 777 /dev/ttyUSB0

# 启动 roscore
source /opt/ros/noetic/setup.bash
roscore & # 使用后台运行

# 等待 roscore 启动
sleep 5s # 初始等待,给 roscore 启动一些时间

# 启动节点
source /home/tree/robospace/devel/setup.bash
rosrun my_minimal_nodes my_minimal_nodes_node &
rostopic echo /imu # 直接在当前终端输出

添加权限:

1
sudo chmod 777 -R ros_start.sh

补:命令行式输出示范

1
gnome-terminal --tab --title="roscore" -- bash -c "source  /opt/ros/noetic/setup.bash;roscore; exec bash"

方案一:使用ubuntu自带程序管理器

此方案适用于带有图形桌面的linux系统,较为简单

先检查对应的软件包是否存在,一般都是自带的,没有可通过该指令下载

1
sudo apt-get install gnome-startup-applications

打开管理器:

1
gnome-session-properties

参考如下设置:
alt text
添加后即可完成自启动设置

方案二:使用 systemd 创建服务

使用linux自带的systemd服务管理器
此方案适用于没有图形显示的linux系统

在/etc/systemd/system新建service文件:

1
2
3
sudo nano my_ros_service.servoce

sudo vi my_ros_service.service

编写内容:

1
2
3
4
5
6
[Unit]
After=network.service
[Service]
ExecStart=/home/tree/ros_start.sh
[Install]
WantedBy=default.target

在etc/systemd/system路径下使用命令,添加权限:

1
2
3
sudo chmod +x my_ros_service.service

sudo chmod 777 my_ros_service.service

将service文件设置为开机启动:

1
sudo systemctl enable my_ros_service.service 

查看service文件启动状态:

1
sudo systemctl status my_ros_service.service

手动启动service文件,用于测试

1
sudo systemctl start my_ros_service.service

以上完成使用systemd服务管理器的自启动方式