前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >自动驾驶技术栈——SOME/IP协议

自动驾驶技术栈——SOME/IP协议

作者头像
Coder-ZZ
发布2023-02-23 16:41:26
1.8K0
发布2023-02-23 16:41:26
举报
文章被收录于专栏:C/C++进阶专栏

一,关于车载软件通信

传统的车载软件通信采用的是经典的总线协议(比如CAN、LIN、FlexRay),这些总线采用的是面向信号的数据传输(Signal-based),基于信号在双绞线中的传输来通信,但是这些协议的传输带宽和传输速率有限,且不容易实现基于无线网更新车载软件(OTA)的需求。因此,新一代的车载软件通信更多采用了SOA架构下的SOME/IP协议,该协议采用的是面向服务的数据传输(Service-Oriented),基于ECU的服务在车载以太网中被请求或订阅来通信。

二,SOME/IP简介

SOME/IP是基于以太网实现的中间件通信协议。SOME/IP 是"Scalable Service-Oriented Middleware over IP"的缩写。

SOME/IP在以太网模型的分层中,位于TCP/UDP传输层以上,属于应用层。

三,SOME/IP的特点

1.支持序列化操作。作为通信节点的ECU可能有不同的软件架构或者操作系统,为了保证传输机制的一致性,SOME/IP允许将UDP/TCP报文进行序列化操作。

2.支持远程过程调用 (RPC)。客户端可以远程地向服务器端请求数据,也可以远程地在服务器端执行某些函数。

3.服务发现(SD)。在面向服务的架构中,服务必须是可发现的,SOME/IP有个单独的SD模块负责服务的实现。

4.支持发布/订阅。客户端可以订阅服务器的内容,从而可以动态地接收来自服务器的更新数据。

四,SOME/IP消息格式

SOME/IP序列化消息的数据头格式如下:

Message ID: 用来标识参与远程调用的Method或者Event

Request ID: 用来标识不同的Client对象或者同一个Client对象发起的不同Session会话

Message Type: 用来区分消息体类型

常见的消息体类型:request/response/notification/error

Return Code: 通常返回E_OK(0x00),如果返回的是Response或Error消息体类型就不会是 0x0

Payload: 参与传输的数据段

五,SOME/IP的主要通信模式

1.Request/Response Methods

客户端发送请求到服务器,以及从服务器返回响应到客户端。服务器的错误响应也会返回给客户端。


2.Fire and Forget Methods

客户端向服务器发送请求,服务端不返回响应。


3.Notification Events

客户端订阅服务器的内容,每当服务器有数据变化或执行某任务后通知给订阅过的客户端。哪些客户端需要订阅由SOME/IP-SD来管理。


4.Field

一个字段表示一个状态,订阅该字段的客户端将字段值作为初始事件。字段值后面的每次更新都会通知给客户端。


六,SD 服务发现流程

1.SD有两种机制:

第一种机制是“提供服务”,服务器可以使用它向网络提供可用服务。另一种是“查找服务”,它使客户端能够请求到可用服务。

2.服务发现具体流程:

1.服务器通过广播发布消息

2.客户端通过广播查找消息

3.客户端找到消息后,进行订阅和确认(Subscribe – Ack)

3.SD过程的工作模式:

客户端的两种模式:请求和监听(Request and Listen)

服务器端的两种模式:提供和静默(Offer and Silent)

七,常见的开源实现--基于vSomeIP

BMW基于 SOME/IP 标准实现了开源的vsomeip框架,vsomeip能够独立集成到各种操作系统。

代码样例--Request/Response模式:

服务器端:

代码语言:javascript
复制
#include <iomanip>
#include <iostream>
#include <sstream>

#include <vsomeip/vsomeip.hpp>

#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x0421

std::shared_ptr<vsomeip::application> app;

void on_message(const std::shared_ptr<vsomeip::message> &_request) {
    std::shared_ptr<vsomeip::payload> its_payload = _request->get_payload();
    vsomeip::length_t l = its_payload->get_length();

    // Get payload
    std::stringstream ss;
    for (vsomeip::length_t i=0; i<l; i++) {
       ss << std::setw(2) << std::setfill('0') << std::hex
          << (int)*(its_payload->get_data()+i) << " ";
    }

    std::cout << "SERVICE: Received message with Client/Session ["
        << std::setw(4) << std::setfill('0') << std::hex << _request->get_client() << "/"
        << std::setw(4) << std::setfill('0') << std::hex << _request->get_session() << "] "
        << ss.str() << std::endl;

    // Create response
    std::shared_ptr<vsomeip::message> its_response = vsomeip::runtime::get()->create_response(_request);
    its_payload = vsomeip::runtime::get()->create_payload();
    std::vector<vsomeip::byte_t> its_payload_data;
    for (int i=9; i>=0; i--) {
        its_payload_data.push_back(i % 256);
    }
    its_payload->set_data(its_payload_data);
    its_response->set_payload(its_payload);
    app->send(its_response, true);
}

int main() {
   app = vsomeip::runtime::get()->create_application("World");
   app->init();
   app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, on_message);
   app->offer_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
   app->start();
}

客户端:

代码语言:javascript
复制
#include <iomanip>
#include <iostream>
#include <sstream>

#include <condition_variable>
#include <thread>

#include <vsomeip/vsomeip.hpp>

#define SAMPLE_SERVICE_ID 0x1234
#define SAMPLE_INSTANCE_ID 0x5678
#define SAMPLE_METHOD_ID 0x0421

std::shared_ptr< vsomeip::application > app;
std::mutex mutex;
std::condition_variable condition;

void run() {
  std::unique_lock<std::mutex> its_lock(mutex);
  condition.wait(its_lock);

  std::shared_ptr< vsomeip::message > request;
  request = vsomeip::runtime::get()->create_request();
  request->set_service(SAMPLE_SERVICE_ID);
  request->set_instance(SAMPLE_INSTANCE_ID);
  request->set_method(SAMPLE_METHOD_ID);

  std::shared_ptr< vsomeip::payload > its_payload = vsomeip::runtime::get()->create_payload();
  std::vector< vsomeip::byte_t > its_payload_data;
  for (vsomeip::byte_t i=0; i<10; i++) {
      its_payload_data.push_back(i % 256);
  }
  its_payload->set_data(its_payload_data);
  request->set_payload(its_payload);
  app->send(request, true);
}

void on_message(const std::shared_ptr<vsomeip::message> &_response) {

  std::shared_ptr<vsomeip::payload> its_payload = _response->get_payload();
  vsomeip::length_t l = its_payload->get_length();

  // Get payload
  std::stringstream ss;
  for (vsomeip::length_t i=0; i<l; i++) {
     ss << std::setw(2) << std::setfill('0') << std::hex
        << (int)*(its_payload->get_data()+i) << " ";
  }

  std::cout << "CLIENT: Received message with Client/Session ["
      << std::setw(4) << std::setfill('0') << std::hex << _response->get_client() << "/"
      << std::setw(4) << std::setfill('0') << std::hex << _response->get_session() << "] "
      << ss.str() << std::endl;
}

void on_availability(vsomeip::service_t _service, vsomeip::instance_t _instance, bool _is_available) {
    std::cout << "CLIENT: Service ["
            << std::setw(4) << std::setfill('0') << std::hex << _service << "." << _instance
            << "] is "
            << (_is_available ? "available." : "NOT available.")
            << std::endl;
    condition.notify_one();
}

int main() {
    app = vsomeip::runtime::get()->create_application("Hello");
    app->init();
    app->register_availability_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, on_availability);
    app->request_service(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID);
    app->register_message_handler(SAMPLE_SERVICE_ID, SAMPLE_INSTANCE_ID, SAMPLE_METHOD_ID, on_message);
    std::thread sender(run);
    app->start();
}

服务器端的配置:

代码语言:javascript
复制
{
    "unicast" : "172.17.0.2",
    "logging" :
    { 
        "level" : "debug",
        "console" : "true",
        "file" : { "enable" : "false", "path" : "/tmp/vsomeip.log" },
        "dlt" : "false"
    },
    "applications" : 
    [
        {
            "name" : "World",
            "id" : "0x1212"
        }
    ],
    "services" :
    [
        {
            "service" : "0x1234",
            "instance" : "0x5678",
            "unreliable" : "30509"
        }
    ],
    "routing" : "World",
    "service-discovery" :
    {
        "enable" : "true",
        "multicast" : "224.224.224.245",
        "port" : "30490",
        "protocol" : "udp",
        "initial_delay_min" : "10",
        "initial_delay_max" : "100",
        "repetitions_base_delay" : "200",
        "repetitions_max" : "3",
        "ttl" : "3",
        "cyclic_offer_delay" : "2000",
        "request_response_delay" : "1500"
    }
}

客户端的配置:

代码语言:javascript
复制
{
    "unicast" : "172.17.0.1",
    "logging" :
    {
        "level" : "debug",
        "console" : "true",
        "file" : { "enable" : "false", "path" : "/var/log/vsomeip.log" },
        "dlt" : "false"
    },
    "applications" : 
    [
        {
            "name" : "Hello",
            "id" : "0x1313"
        } 
    ],
    "routing" : "Hello",
    "service-discovery" :
    {
        "enable" : "true",
        "multicast" : "224.224.224.245",
        "port" : "30490",
        "protocol" : "udp",
        "initial_delay_min" : "10",
        "initial_delay_max" : "100",
        "repetitions_base_delay" : "200",
        "repetitions_max" : "3",
        "ttl" : "3",
        "cyclic_offer_delay" : "2000",
        "request_response_delay" : "1500"
    }
}

参考阅读:

1.https://inspiredhobbyist.org/what-is-some-ip-in-autosar/

2.https://mdnice.com/writing/6c21d60b8e74456b8d84004ced9baae2

3.https://github.com/COVESA/vsomeip/wiki/vsomeip-in-10-minutes

慢慢进步吧,waiting and hope.

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-08-29,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 程序员与背包客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Payload: 参与传输的数据段
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档