消息库zeromq的源码编译及其简单使用

作为一个致力于研究机器人仿真软件的机器人工程师,研究一下进程间通信是很有必要的。
当前机器人技术在各行各业的渗透处于快速上升阶段,诸多传统行业的公司都在转型升级中,尤其是今年(2020年)的新冠疫情,让我们看到了机器人和无人工厂的另外一个优势。我们会看到地产商成立了机器人公司,卖饮料的成立了机器人公司,传统生产重型装备的开始研发机器人。中国的医患关系紧张,矛盾短期难以调和,医生们冒着被患者家属伤害的风险给患者做手术,研发手术机器人来接管医生的部分工作,让医生不再那么辛苦那么累已然成为一种趋势。
个人感觉,当前和未来的一个阶段,机器人的易用性依然很差,虽然近年来协作机器人市场发展迅速,国内布局协作机器人的厂商不少,但是协作机器人的优势更多的是体现在人机协作的安全性上。协作机器人跟传统的工业机器人各有优劣。
传统工业机器人速度快、惯量大、精度高、故障率低,但是不够安只能在围栏里使用。协作机器人对传统工业机器人在安性方面进行了改进,使之可以与人协同作业的同时保证人的安全性。协作机器人为了达到安全的目的:1、需要限制速度、刚度、本体质量;2、具有碰撞检测(电流/力传感器)功能和拖动示教功能。3、符合相关协作机器人的安全标准。
根据个人的了解的实际情况,协作机器人的故障率比传统工业机器人高多了。
有时候工作时间久了,协作机器人指不定哪个关节就出现问题了,然后就要拆关节,返厂维修,再快递寄回来,再装上去,这个过程机器人的位置出现了变化,又需要示教、标定什么的,目前很多视觉应用通常跟机器人相结合,手眼标定大概率是要做的,整个过程挺麻烦的,并且费用蛮高的,所以未来协作机器人维修工程师应该还是蛮有市场的。有时候感慨,如果我们人类也能像机器人那样,身体的任何一个零部件坏了拆下来换个新的装上就好了。

不知不觉罗嗦了那么多,现在回归正题。要想让机器人变得好用,那就必须尽量多的让机器人系统软件来接管当前需要人来做的工作,就像A380等大型客机如果没有先进的航电系统,很多工作要飞行原来操作的话,那就太难搞了。因此,可以发现,最近几年国内不少机器人初创公司都在机器人易用性上做工作。
就个人经验来说,要使机器人好用,必须要在软件、硬件和算法方面做协同,协同就意味着各模块之间需要进行通信,所以进程间通信是机器人系统软件必要的技术,这一点也可以从很多机器人公司在招聘软件开发人员的招聘需求中略知一二。硬件包括:机器人本体、控制柜、末端夹具、六维力传感器、工控机、工业相机等
算法:主要是各种上层的机器人和视觉相关的算法,如机器人的运动学正逆解、动力学正逆解、运动规划、轨迹插补、碰撞检测、柔顺控制等,视觉相关的图像分类、目标检测、语义分割、实例分割、缺陷检测,点云相关的尺寸测量、模型ICP匹配、6D抓取位姿估计,以及涉及到的各种算法加速问题
软件:软件是关联硬件和算法的枢纽,机器人系统软件,或者说是机器人操作系统,学过ROS的同学都知道ROS就是机器人操作系统的全称,可能很多同学一听到操作系统,脑海中第一印象就是WindowsXP/7/8/8.1/10,或者Ubuntu14/16/18/20等,这些是真正意义上的通用计算机操作系统,而我们这里所说的机器人操作系统更多的是一个中间件的角色,区分一个机器人软件包是机器人操作系统还是机器人工具箱的最重要的点即是否集成了进程间通信的功能。如果没有进程间通信的功能,那么就只是一个机器人工具箱,比如Peter Corke的MATLAB机器人工具箱,或者南丹麦大学开发维护的RobWork机器人工具箱,RobWork是基于C++开发的。
相反,ROS或者ROS2就是机器人操作系统,为啥,因为ROS实现了节点之间的发布订阅的通信功能,其底层使用的xmlrpc库,ROS2也实现了节点之间的发布订阅的通信功能,其底层使用的是Fast-RTPS库。
与ROS/ROS2类似的机器人操作系统还有比较著名的Yarp,即另外一个机器人平台,本质上就是一个机器人通信中间件,它提供了多种通信功能。此外,还有德国慕尼黑工业大学开发维护的RoboticsLibrary,简称RL,也提供了简单的通讯功能。

终于讲完了本文的铺垫,下面进入今天的主角ZeroMQ,下面主要记录如何源码编译安装和使用ZeroMQ,感兴趣的同学可以自己去研究一下。
首先,我们下载和编译libzmq这个库:

git clone git@github.com:zeromq/libzmq.git
cd libzmq && mkdir build && cd build
cmake ..
sudo make -j4 install

其实,只需要安装libzmq就可以使用ZeroMQ的通信功能了,但是由于libzmq本身是用C写的,为了方便C++用户,官方有做了一个针对C++的接口封装,方便C++用户使用C++类和对象进行编程。

接着,我们下载和编译cppzmq这个库:

git clone git@github.com:zeromq/cppzmq.git
cd cppzmq
mkdir build
cd build
cmake ..
sudo make -j4 install

编写服务器代码:

cmake_minimum_required(VERSION 3.5)

project(zmq_server LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(cppzmq)
include_directories(${cppzmq_INCLUDE_DIR})
add_executable(zmq_server zmq_server.cpp)
target_link_libraries(zmq_server cppzmq)

zmq_server.cpp

#include <string>
#include <chrono>
#include <thread>
#include <iostream>

#include <zmq.hpp>

int main() {
    using namespace std::chrono_literals;
    // initialize the zmq context with a single IO thread
    zmq::context_t context{1};
    // construct a REP (reply) socket and bind to interface
    zmq::socket_t socket{context, ZMQ_REP};
    socket.bind("tcp://*:5555");
    // prepare some static data for responses
    const std::string data{"World"};
    for (;;) {
        zmq::message_t request;
        // receive a request from client
        socket.recv(request, zmq::recv_flags::none);
        std::cout << "Received " << request.to_string() << std::endl;
        // simulate work
        std::this_thread::sleep_for(1s);
        // construct a reply message
        zmq::message_t reply{data.cbegin(), data.cend()};
        // send the reply to the client
        socket.send(reply, zmq::send_flags::none);
    }
    return 0;
}

编写客户端代码:

cmake_minimum_required(VERSION 3.5)

project(zmq_client LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(cppzmq)
include_directories(${cppzmq_INCLUDE_DIR})
add_executable(zmq_client zmq_client.cpp)
target_link_libraries(zmq_client cppzmq)

zmq_client.cpp

#include <string>
#include <iostream>

#include <zmq.hpp>

int main() {
    // initialize the zmq context with a single IO thread
    zmq::context_t context{1};
    // construct a REQ (request) socket and connect to interface
    zmq::socket_t socket{context, ZMQ_REQ};
    socket.connect("tcp://localhost:5555");
    // set up some static data to send
    const std::string data{"Hello"};
    for (auto request_num = 0; request_num < 10; ++request_num) {
        // initialize a request message
        zmq::message_t request{data.cbegin(), data.cend()};
        // send the request message
        std::cout << "Sending Hello " << request_num << "..." << std::endl;
        socket.send(request, zmq::send_flags::none);
        // wait for reply from server
        zmq::message_t reply{};
        socket.recv(reply, zmq::recv_flags::none);
        std::cout << "Received " << reply.to_string();
        std::cout << " (" << request_num << ")";
        std::cout << std::endl;
    }
    return 0;
}

编译运行,进行测试:
先启动服务器,进行端口监听

./zmq_server

然后启动客户端,发送和接收数据并打印

./zmq_client

测试效果如下:
在这里插入图片描述
在这里插入图片描述

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 精致技术 设计师:CSDN官方博客 返回首页