VEINS_CARLA代码详解

基于GPT-3.5
在这里插入图片描述

examples/veins_carla

从examples/veins_carla开始:

  • CarlaExampleScenario.ned
    在这里插入图片描述
    这段代码定义了一个名为CarlaExampleScenario的OMNeT++网络模块。它扩展了CarlaScenario,这意味着它基于CarlaScenario进行了一些定制和扩展。以下是对这个代码的简要解释:

import语句导入了所需的模块和类,这些模块和类在后面的代码中被使用。
network CarlaExampleScenario extends CarlaScenario定义了一个名为CarlaExampleScenario的网络模块,它扩展了CarlaScenario,因此继承了CarlaScenario中的一些功能和属性。
parameters部分用于定义网络模块的参数。在这里,只定义了一个参数useVehicleObstacleShadowing,默认值为false。这个参数似乎用于控制是否启用车辆障碍阴影,以及在模拟中是否使用该功能。
submodules部分定义了网络模块的子模块。在这里,有一个子模块vehicleObstacles,它是VehicleObstacleControl类型的模块。这个子模块的创建受useVehicleObstacleShadowing参数的影响,只有当该参数为true时,才会创建并添加到网络模块中。子模块的位置在模拟中的可视化中使用@display注解指定。
总的来说,这段代码定义了一个基于CarlaScenario的网络模块,可以根据参数useVehicleObstacleShadowing的设置来决定是否添加VehicleObstacleControl子模块。这个模块似乎用于模拟车辆之间的障碍物阴影。

  • antenna.xml
    在这里插入图片描述
    这个名为 “antenna.xml” 的 XML 文件定义了三种不同类型的天线,可用于车辆通信场景。这些天线分别命名为 “monopole”、“panorama” 和 “patch”。每种天线类型都使用一组样本值来描述其辐射模式。

以下是XML内容的解释:

元素是XML文档的根元素。

三个 元素代表不同的天线类型,具有唯一的ID:“monopole”、“panorama” 和 “patch”。

每个 元素都有一个 type 属性,用于指定天线类型,比如 “SampledAntenna1D”。

在每个 元素内部,有一个 元素,用于定义天线的辐射模式。辐射模式表示为 value 属性中的一组样本值。这些样本是数值,用于描述不同方向上的天线行为。每个 value 属性中的具体数值对应于一维场景下天线的辐射模式。

例如,“monopole” 天线具有一组样本,用于描述其辐射模式,而 “panorama” 和 “patch” 天线则具有各自的样本集。

这些天线辐射模式对于在仿真中模拟车辆场景中的无线通信至关重要,因为它们确定了不同类型天线在车辆上如何传输和接收信号。value 属性中的数值表示相对于天线位置的各个方向上的信号强度。

这些天线特性用于在仿真中模拟真实的通信场景,从而决定了信号如何通过不同类型天线在车辆之间传输和接收。

  • config.xml
    在这里插入图片描述
    这个名为 “config.xml” 的 XML 文件包含了与仿真中的通信模型和决策器相关的配置信息。它主要用于定义通信模型和决策器的参数。

以下是XML内容的解释:

元素是XML文档的根元素。

元素用于定义不同的模拟模型。在此文件中,只有一个 元素被启用。

元素用于指定模拟模型的类型。在这里,有两个 元素,但其中一个是被注释掉的。

第一个 元素的类型是 “SimplePathlossModel”,它表示简单的路径损耗模型。该模型使用了一个参数 alpha,它的值为 2.0。

第二个 元素的类型是 “VehicleObstacleShadowing”,它表示车辆障碍物阴影模型。它使用了一个参数 carrierFrequency,其值为 5.890e+9。

元素定义了决策器的类型,这里使用的类型是 “Decider80211p”。它还包含了一个参数 centerFrequency,其值为 5.890e9,表示物理层监听的中心频率。

这些配置参数用于定义通信模型和决策器的行为,以便在仿真中模拟无线通信的特性。通信模型决定了信号如何传播和衰减,而决策器决定了如何处理接收到的信号以进行通信决策。在这个文件中,通信模型和决策器的参数都是用于配置仿真的关键组件。

  • doRun.sh
    在这里插入图片描述

这个脚本文件名为 “doRun.sh”,它是一个用于运行仿真的 Shell 脚本。下面是对其代码的解释:

set -e: 这是一个 shell 命令,用于在脚本执行过程中如果出现错误(即非零返回代码)时立即终止脚本。这可以帮助确保在出现问题时停止仿真流程。

make -C …/…/ -j12: 这是一个 make 命令,用于编译仿真所需的源代码。具体来说:

-C …/…/ 指定了 make 命令在执行时切换到上一级目录(…/…),这通常是源代码目录的根目录。
-j12 表示使用 12 个线程并行编译,以加快编译速度。这可以根据计算机的性能进行调整。
./run -u Cmdenv -c Default -r 0: 这是一个运行仿真的命令。具体来说:

./run 是仿真运行命令的路径,./ 表示在当前目录中查找该命令。
-u Cmdenv 指定了使用 Cmdenv 执行仿真。Cmdenv 是 OMNeT++ 中的命令行仿真环境。
-c Default 指定了要运行的仿真配置,这里使用了名为 “Default” 的配置。
-r 0 表示要运行的仿真运行号,这里使用了运行号 0。每个运行号对应一个独立的仿真实例,可以用来进行多次运行以获取统计结果。
总之,这个脚本首先编译仿真代码,然后使用指定的配置和运行号运行仿真。如果在编译过程中出现错误,脚本会终止仿真流程。否则,仿真将以默认配置在 Cmdenv 环境中执行,并使用运行号 0。

  • doRunShadowing.sh
    在这里插入图片描述

这个脚本文件名为 “doRunShadowing.sh”,它类似于之前提到的 “doRun.sh”,用于运行仿真,但使用的配置名称不同。下面是对其代码的解释:

set -e: 这是一个 shell 命令,用于在脚本执行过程中如果出现错误(即非零返回代码)时立即终止脚本。这可以帮助确保在出现问题时停止仿真流程。

make -C …/…/ -j12: 这是一个 make 命令,用于编译仿真所需的源代码,类似于之前的脚本。具体来说:

-C …/…/ 指定了 make 命令在执行时切换到上一级目录(…/…),通常是源代码目录的根目录。
-j12 表示使用 12 个线程并行编译,以加快编译速度。这可以根据计算机的性能进行调整。
./run -u Cmdenv -c DefaultVehicleShadowing -r 0: 这是一个运行仿真的命令,与之前的脚本类似。具体来说:

./run 是仿真运行命令的路径,./ 表示在当前目录中查找该命令。
-u Cmdenv 指定了使用 Cmdenv 执行仿真,Cmdenv 是 OMNeT++ 中的命令行仿真环境。
-c DefaultVehicleShadowing 指定了要运行的仿真配置,这里使用了名为 “DefaultVehicleShadowing” 的配置,这可能表示该配置包括了有关车辆遮挡(shadowing)的相关设置。
-r 0 表示要运行的仿真运行号,这里使用了运行号 0。每个运行号对应一个独立的仿真实例,可以用来进行多次运行以获取统计结果。
总之,这个脚本首先编译仿真代码,然后使用指定的配置和运行号运行仿真。如果在编译过程中出现错误,脚本会终止仿真流程。否则,仿真将以配置 “DefaultVehicleShadowing” 在 Cmdenv 环境中执行,并使用运行号 0。

  • omnetpp.ini
[General]
cmdenv-express-mode = true
cmdenv-autoflush = true
cmdenv-status-frequency = 1s
**.cmdenv-log-level = info

image-path = ../../images
network = CarlaExampleScenario

##########################################################
#            Simulation parameters                       #
##########################################################
debug-on-errors = true
print-undisposed = true

**.scalar-recording = true
**.vector-recording = true

*.playgroundSizeX = 2500000m
*.playgroundSizeY = 2500000m
*.playgroundSizeZ = 500m


##########################################################
# Annotation parameters                                  #
##########################################################
*.annotations.draw = true


##########################################################
# Obstacle parameters                                    #
##########################################################
#*.obstacles.obstacles = xmldoc("config.xml", "//AnalogueModel[@type='SimpleObstacleShadowing']/obstacles")


##########################################################
#            CarlaScenarioManager parameters             #
##########################################################
*.manager.updateInterval = 1s
*.manager.host = "localhost"
*.manager.port = 1337
*.manager.autoShutdown = true


##########################################################
#            11p specific parameters                     #
#                                                        #
#                    NIC-Settings                        #
##########################################################
*.connectionManager.sendDirect = true
*.connectionManager.maxInterfDist = 2600m
*.connectionManager.drawMaxIntfDist = false

*.**.nic.mac1609_4.useServiceChannel = false

*.**.nic.mac1609_4.txPower = 20mW
*.**.nic.mac1609_4.bitrate = 6Mbps
*.**.nic.phy80211p.minPowerLevel = -110dBm

*.**.nic.phy80211p.useNoiseFloor = true
*.**.nic.phy80211p.noiseFloor = -98dBm

*.**.nic.phy80211p.decider = xmldoc("config.xml")
*.**.nic.phy80211p.analogueModels = xmldoc("config.xml")
*.**.nic.phy80211p.usePropagationDelay = true

*.**.nic.phy80211p.antenna = xmldoc("antenna.xml", "/root/Antenna[@id='monopole']")
*.node[*].nic.phy80211p.antennaOffsetY = 0 m
*.node[*].nic.phy80211p.antennaOffsetZ = 1.895 m


##########################################################
#                      App Layer                         #
##########################################################
*.node[*].applType = "ExampleCarlaApplication"
*.node[*].appl.headerLength = 80 bit
*.node[*].appl.sendBeacons = false
*.node[*].appl.dataOnSch = false
*.node[*].appl.beaconInterval = 1s


##########################################################
#                      Mobility                          #
##########################################################
*.node[*].carlaMobility.x = 0
*.node[*].carlaMobility.y = 0
*.node[*].carlaMobility.z = 0
*.node[*].carlaMobility.setHostSpeed = false


[Config Default]
*.**.nic.phy80211p.analogueModels = xmldoc("config.xml")


[Config DefaultVehicleShadowing]
*.useVehicleObstacleShadowing = true
*.**.nic.phy80211p.analogueModels = xmldoc("configVehicleShadowing.xml")

这是一个名为 “omnetpp.ini” 的配置文件,用于配置 OMNeT++ 中的仿真参数。下面是对其内容的解释:

cmdenv-express-mode = true: 这个参数设置 Cmdenv(OMNeT++的命令行仿真环境)的 “express mode” 为 true,这意味着 Cmdenv 将以快速模式运行仿真,用于加速仿真进程。

cmdenv-autoflush = true: 启用 Cmdenv 的自动刷新功能,使仿真输出及时显示。

cmdenv-status-frequency = 1s: 设置 Cmdenv 的状态更新频率为 1 秒,以便查看仿真状态信息。

**.cmdenv-log-level = info: 将仿真输出的日志级别设置为 “info”,以便记录更多信息。

image-path = …/…/images: 设置图像文件的路径,这些图像文件可能在仿真中使用。

network = CarlaExampleScenario: 指定要运行的仿真网络配置,这里是 “CarlaExampleScenario”。

*.**.nic.phy80211p.analogueModels = xmldoc(“config.xml”): 设置物理层的模拟模型参数,从名为 “config.xml” 的 XML 文件中加载。这影响 802.11p 物理层的仿真参数。
[Config DefaultVehicleShadowing]: 这是另一个仿真配置,可能包含与车辆遮挡相关的参数。

*.useVehicleObstacleShadowing = true: 启用了车辆遮挡(shadowing)的功能,这将模拟车辆之间的遮挡效应。

*.**.nic.phy80211p.analogueModels = xmldoc(“configVehicleShadowing.xml”): 设置物理层的模拟模型参数,从名为 “configVehicleShadowing.xml” 的 XML 文件中加载。这可能包含与车辆遮挡相关的参数。

仿真参数:在文件中还定义了一系列仿真参数,如网络尺寸、注解参数、障碍物参数、CarlaScenarioManager 参数、NIC 设置、应用层参数和移动性参数。这些参数用于配置仿真的各个方面,包括网络设置、物理层模型、应用层行为和车辆移动性。

总之,这个配置文件 “omnetpp.ini” 包含了一系列仿真参数的设置,用于定义仿真的行为、特性和网络配置。不同的配置部分允许您在不同情况下运行仿真,例如,考虑车辆遮挡效应或不考虑。

  • run
    这是一个脚本文件,通常用于启动 OMNeT++ 仿真。该脚本调用了 veins_carla_run 可执行文件,并传递给它任何命令行参数(“$@” 表示将接受到的所有参数传递给被调用的程序)。通常,veins_carla_run 是一个 OMNeT++仿真的启动器,用于加载仿真配置并运行仿真。

这个脚本的作用是将执行的命令委托给 veins_carla_run 这个二进制可执行文件,从而启动 OMNeT++ 中的仿真。

您可以在命令行中运行此脚本,并将任何必要的参数传递给它,以便启动仿真过程。例如,您可以执行:

./run -u Cmdenv -c Default -r 0

这将运行 veins_carla_run,以 Cmdenv 模式执行默认配置(-c Default),并执行 0 号运行(-r 0)。

请注意,这个脚本的主要作用是简化 OMNeT++ 仿真的启动过程,以便更轻松地运行仿真。

proto

  • buildProto.sh

这个脚本 buildProto.sh 使用 grpc_tools.protoc 工具来生成 Python 代码,包括 gRPC 客户端和服务器的代码,以及协议缓冲区的代码,从 carla.proto 文件中。这是为了在 Python 中与 CARLA 通信而生成的 gRPC 代码。

具体来说,脚本的命令行参数和选项如下:

–python_out=.:生成的 Python 文件的输出目录为当前目录。
–grpc_python_out=.:生成的 gRPC Python 文件的输出目录为当前目录。
carla.proto:指定要处理的输入协议缓冲区定义文件,这是与 CARLA 通信相关的 gRPC 协议定义。
-I .:指定用于查找 carla.proto 文件的包含路径。在这里,. 表示当前目录。
通过执行此脚本,您可以生成与 CARLA 通信相关的 gRPC Python 代码,以便在您的 Python 项目中使用。这个代码文件将用于构建 gRPC 服务和客户端,实现与 CARLA 仿真平台的通信。

  • carla_pb2.py
    在这里插入图片描述
    这个文件 carla_pb2.py 是由 Protocol Buffers 编译器生成的 Python 代码。它包含了与 CARLA 通信相关的 gRPC 协议的定义和序列化/反序列化逻辑。

这个文件的主要内容包括:

导入了一些 Google Protocol Buffers 相关的模块,如 builder、descriptor 等。
定义了 CARLA 协议的消息和枚举类型,如 ActorIds、Number、Vehicle、Vector、Rotation、Transform 等。
构建了消息和枚举的描述符。
对消息和枚举的字段进行了序列化和反序列化的处理。
设置了一些协议的选项和参数,以及编码方式。
这个文件是 CARLA 仿真平台与 Python 通信的基础,它定义了 CARLA 中的实体和通信协议,以便您可以使用 gRPC 与 CARLA 进行交互。通过这个文件,您可以在 Python 项目中创建 CARLA 仿真中的车辆、获取车辆信息等操作。

  • carla_pb2_grpc.py
# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
"""Client and server classes corresponding to protobuf-defined services."""
import grpc

import carla_pb2 as carla__pb2
from google.protobuf import empty_pb2 as google_dot_protobuf_dot_empty__pb2


class CarlaAdapterStub(object):
    """Missing associated documentation comment in .proto file."""

    def __init__(self, channel):
        """Constructor.

        Args:
            channel: A grpc.Channel.
        """
        self.ExecuteOneTimeStep = channel.unary_unary(
                '/carla.CarlaAdapter/ExecuteOneTimeStep',
                request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
                response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
                )
        self.Finish = channel.unary_unary(
                '/carla.CarlaAdapter/Finish',
                request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
                response_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
                )
        self.GetManagedActorsIds = channel.unary_unary(
                '/carla.CarlaAdapter/GetManagedActorsIds',
                request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
                response_deserializer=carla__pb2.ActorIds.FromString,
                )
        self.GetManagedActorById = channel.unary_unary(
                '/carla.CarlaAdapter/GetManagedActorById',
                request_serializer=carla__pb2.Number.SerializeToString,
                response_deserializer=carla__pb2.Vehicle.FromString,
                )
        self.InsertVehicle = channel.unary_unary(
                '/carla.CarlaAdapter/InsertVehicle',
                request_serializer=carla__pb2.Vehicle.SerializeToString,
                response_deserializer=carla__pb2.Number.FromString,
                )
        self.GetRandomSpawnPoint = channel.unary_unary(
                '/carla.CarlaAdapter/GetRandomSpawnPoint',
                request_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
                response_deserializer=carla__pb2.Transform.FromString,
                )


class CarlaAdapterServicer(object):
    """Missing associated documentation comment in .proto file."""

    def ExecuteOneTimeStep(self, request, context):
        """Missing associated documentation comment in .proto file."""
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')

    def Finish(self, request, context):
        """Missing associated documentation comment in .proto file."""
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')

    def GetManagedActorsIds(self, request, context):
        """Missing associated documentation comment in .proto file."""
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')

    def GetManagedActorById(self, request, context):
        """Missing associated documentation comment in .proto file."""
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')

    def InsertVehicle(self, request, context):
        """Missing associated documentation comment in .proto file."""
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')

    def GetRandomSpawnPoint(self, request, context):
        """Missing associated documentation comment in .proto file."""
        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
        context.set_details('Method not implemented!')
        raise NotImplementedError('Method not implemented!')


def add_CarlaAdapterServicer_to_server(servicer, server):
    rpc_method_handlers = {
            'ExecuteOneTimeStep': grpc.unary_unary_rpc_method_handler(
                    servicer.ExecuteOneTimeStep,
                    request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
                    response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
            ),
            'Finish': grpc.unary_unary_rpc_method_handler(
                    servicer.Finish,
                    request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
                    response_serializer=google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
            ),
            'GetManagedActorsIds': grpc.unary_unary_rpc_method_handler(
                    servicer.GetManagedActorsIds,
                    request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
                    response_serializer=carla__pb2.ActorIds.SerializeToString,
            ),
            'GetManagedActorById': grpc.unary_unary_rpc_method_handler(
                    servicer.GetManagedActorById,
                    request_deserializer=carla__pb2.Number.FromString,
                    response_serializer=carla__pb2.Vehicle.SerializeToString,
            ),
            'InsertVehicle': grpc.unary_unary_rpc_method_handler(
                    servicer.InsertVehicle,
                    request_deserializer=carla__pb2.Vehicle.FromString,
                    response_serializer=carla__pb2.Number.SerializeToString,
            ),
            'GetRandomSpawnPoint': grpc.unary_unary_rpc_method_handler(
                    servicer.GetRandomSpawnPoint,
                    request_deserializer=google_dot_protobuf_dot_empty__pb2.Empty.FromString,
                    response_serializer=carla__pb2.Transform.SerializeToString,
            ),
    }
    generic_handler = grpc.method_handlers_generic_handler(
            'carla.CarlaAdapter', rpc_method_handlers)
    server.add_generic_rpc_handlers((generic_handler,))


 # This class is part of an EXPERIMENTAL API.
class CarlaAdapter(object):
    """Missing associated documentation comment in .proto file."""

    @staticmethod
    def ExecuteOneTimeStep(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/carla.CarlaAdapter/ExecuteOneTimeStep',
            google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
            google_dot_protobuf_dot_empty__pb2.Empty.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

    @staticmethod
    def Finish(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/carla.CarlaAdapter/Finish',
            google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
            google_dot_protobuf_dot_empty__pb2.Empty.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

    @staticmethod
    def GetManagedActorsIds(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/carla.CarlaAdapter/GetManagedActorsIds',
            google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
            carla__pb2.ActorIds.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

    @staticmethod
    def GetManagedActorById(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/carla.CarlaAdapter/GetManagedActorById',
            carla__pb2.Number.SerializeToString,
            carla__pb2.Vehicle.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

    @staticmethod
    def InsertVehicle(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/carla.CarlaAdapter/InsertVehicle',
            carla__pb2.Vehicle.SerializeToString,
            carla__pb2.Number.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

    @staticmethod
    def GetRandomSpawnPoint(request,
            target,
            options=(),
            channel_credentials=None,
            call_credentials=None,
            insecure=False,
            compression=None,
            wait_for_ready=None,
            timeout=None,
            metadata=None):
        return grpc.experimental.unary_unary(request, target, '/carla.CarlaAdapter/GetRandomSpawnPoint',
            google_dot_protobuf_dot_empty__pb2.Empty.SerializeToString,
            carla__pb2.Transform.FromString,
            options, channel_credentials,
            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)

这个文件 carla_pb2_grpc.py 是由 gRPC Python 编译器生成的 Python 代码,用于定义 gRPC 服务的客户端和服务器类。它基于 carla.proto 文件中定义的 gRPC 服务生成了相应的 Python 类。

这个文件包含了以下内容:

CarlaAdapterStub 类:这是 gRPC 服务的客户端类,用于与 CARLA 仿真平台通信。它包含了与 gRPC 服务中定义的方法相对应的客户端方法,如 ExecuteOneTimeStep、Finish、GetManagedActorsIds 等。这些方法用于向服务器发送请求并接收响应。

CarlaAdapterServicer 类:这是 gRPC 服务的服务器类,定义了与 gRPC 服务中相应方法相对应的服务器方法,但它们的实现都是抛出未实现的异常。您需要在服务器端的代码中实现这些方法。

add_CarlaAdapterServicer_to_server 函数:用于将 CarlaAdapterServicer 与 gRPC 服务器相关联,以便服务器可以处理客户端的请求。

CarlaAdapter 类:这是一个静态类,提供了访问 gRPC 服务方法的静态方法,如 ExecuteOneTimeStep、Finish、GetManagedActorsIds 等。您可以在客户端代码中使用这些方法来与 CARLA 仿真平台进行通信。

总之,carla_pb2_grpc.py 文件定义了 gRPC 服务的客户端和服务器类,是与 CARLA 仿真平台进行通信的重要组件。

src/veins_carla/app

  • ExampleCarlaApplication.cc
#include "ExampleCarlaApplication.h"
#include "veins/modules/application/traci/TraCIDemo11pMessage_m.h"
using namespace veins_carla;
using namespace veins;
Define_Module(ExampleCarlaApplication);

void ExampleCarlaApplication::initialize(int stage)
{
    if (stage == 0) {
        txMessage = new cMessage();
        txMessage->setKind(1337);
        std::cout << getFullPath() << ": Initializing " << par("appName").stringValue() << std::endl;
    }
    else {
        scheduleAt(simTime() + intuniform(1, 10), txMessage);
    }
}

void ExampleCarlaApplication::finish()
{
    DemoBaseApplLayer::finish();
    // statistics recording goes here
}

void ExampleCarlaApplication::onBSM(DemoSafetyMessage* bsm)
{
    // Your application has received a beacon message from another car or RSU
    // code for handling the message goes here
}

void ExampleCarlaApplication::onWSM(BaseFrame1609_4* wsm)
{
    // Your application has received a data message from another car or RSU
    // code for handling the message goes here, see TraciDemo11p.cc for examples
}

void ExampleCarlaApplication::onWSA(DemoServiceAdvertisment* wsa)
{
    // Your application has received a service advertisement from another car or RSU
    // code for handling the message goes here, see TraciDemo11p.cc for examples
}
void ExampleCarlaApplication::handleUpperMsg(cMessage* msg)
{

}
void ExampleCarlaApplication::handleLowerMsg(cMessage* msg)
{

}

void ExampleCarlaApplication::handleSelfMsg(cMessage* msg)
{
    switch (msg->getKind()) {
    case SEND_BEACON_EVT: {
        return;
    }
    case SEND_WSA_EVT: {
        return;
    }
    case 1337: {
        TraCIDemo11pMessage* wsm = new TraCIDemo11pMessage();
        populateWSM(wsm, -1);
        wsm->setDemoData("demodata");
        send(wsm, "lowerLayerOut");
        std::cout << getFullPath() << ": Sending message" << std::endl;
        return;
    }
    }
    DemoBaseApplLayer::handleSelfMsg(msg);
    // this method is for self messages (mostly timers)
    // it is important to call the DemoBaseApplLayer function for BSM and WSM transmission

}

void ExampleCarlaApplication::handlePositionUpdate(cObject* obj)
{
    DemoBaseApplLayer::handlePositionUpdate(obj);
    // the vehicle has moved. Code that reacts to new positions goes here.
    // member variables such as currentPosition and currentSpeed are updated in the parent class
}

ExampleCarlaApplication.cc 文件是一个 Veins 模块,它定义了一个名为 ExampleCarlaApplication 的应用程序层,用于处理车辆之间的通信和消息传输。以下是对代码的简要解释:

initialize(int stage): 这是 ExampleCarlaApplication 的初始化函数。在阶段 0 中,它创建一个 txMessage 消息,设置其类型为 1337,并输出初始化消息。在后续阶段,它安排一个自我消息,以在一段时间后触发消息发送。

finish(): 这是在应用程序完成时调用的函数,用于记录统计信息。您可以在这里添加任何应用程序相关的完成任务。

onBSM(DemoSafetyMessage* bsm): 这是处理安全消息的函数。当应用程序接收到来自其他车辆或 RSU 的安全消息时,可以在这里添加处理该消息的代码。

onWSM(BaseFrame1609_4* wsm): 这是处理数据消息的函数。当应用程序接收到来自其他车辆或 RSU 的数据消息时,可以在这里添加处理消息的代码。

onWSA(DemoServiceAdvertisment* wsa): 这是处理服务广告的函数。当应用程序接收到来自其他车辆或 RSU 的服务广告时,可以在这里添加处理消息的代码。

handleSelfMsg(cMessage* msg): 该函数用于处理自我消息,这些消息通常用于计时器。在代码中,根据消息的类型,它可以创建和发送消息或执行其他应用程序逻辑。

handlePositionUpdate(cObject* obj): 当车辆位置更新时,此函数被调用。您可以在这里添加代码以响应车辆位置的变化。

这个应用程序模块是 Veins 中用于车辆通信和消息传输的一个示例。您可以根据需要修改和扩展它,以实现您自己的应用程序逻辑。

  • ExampleCarlaApplication.h
    在这里插入图片描述

ExampleCarlaApplication.h 是一个头文件,定义了名为 ExampleCarlaApplication 的 Veins 应用程序层模块的类。以下是对代码的简要解释:

class ExampleCarlaApplication : public DemoBaseApplLayer:这个类继承自 DemoBaseApplLayer,表示它是一个 Veins 应用程序模块,用于处理车辆间通信和消息传输。

void initialize(int stage) override:这是初始化函数的声明,它在应用程序模块初始化时被调用。override 关键字表示它是一个覆盖基类函数的函数。

void finish() override:这是完成函数的声明,它在应用程序模块完成时被调用。

void onBSM(DemoSafetyMessage* bsm) override:这是处理安全消息的函数的声明,它在接收到安全消息时被调用。

void onWSM(BaseFrame1609_4* wsm) override:这是处理数据消息的函数的声明,它在接收到数据消息时被调用。

void onWSA(DemoServiceAdvertisment* wsa) override:这是处理服务广告的函数的声明,它在接收到服务广告时被调用。

void handleSelfMsg(cMessage* msg) override:这是处理自我消息的函数的声明,它在接收到自我消息(通常用于计时器)时被调用。

void handlePositionUpdate(cObject* obj) override:这是处理位置更新的函数的声明,它在车辆位置更新时被调用。

cMessage* txMessage:这是一个指向消息的指针,用于在应用程序中安排消息发送。

这个头文件定义了 ExampleCarlaApplication 类的接口,实现了各种函数来处理不同类型的消息和事件。这些函数可以根据需要进行自定义实现。

  • ExampleCarlaApplication.ned
package veins_carla.app;

import org.car2x.veins.base.modules.IBaseApplLayer;
import org.car2x.veins.modules.application.ieee80211p.DemoBaseApplLayer;


simple ExampleCarlaApplication extends DemoBaseApplLayer
{
    parameters:
        @class(veins_carla::ExampleCarlaApplication);
        string appName = default("My first CARLA App!");
        headerLength = 88bit;
        

}

ExampleCarlaApplication.ned 是一个 NED(Network Description)文件,用于定义 Veins 中的应用程序模块。以下是对代码的简要解释:

package veins_carla.app;:这行指定了包的名称,将该应用程序模块放置在 veins_carla.app 包中。

simple ExampleCarlaApplication extends DemoBaseApplLayer:这行定义了一个名为 ExampleCarlaApplication 的简单模块,它继承自 DemoBaseApplLayer,表示它是一个 Veins 应用程序模块,用于车辆通信。

parameters::这是参数部分的开始标记,用于定义模块的参数。

@class(veins_carla::ExampleCarlaApplication);:这是一个注解,指定了应用程序模块的 C++ 类,即 veins_carla::ExampleCarlaApplication。

string appName = default(“My first CARLA App!”);:这是一个字符串参数,表示应用程序的名称,默认为 “My first CARLA App!”。

headerLength = 88bit;:这是参数 headerLength 的定义,表示消息头的长度为 88 位。

该 NED 文件定义了 ExampleCarlaApplication 模块,设置了一些参数,如应用程序名称和消息头长度。这个模块可以在 Veins 模拟中使用,用于处理车辆间通信和消息传输。

veins_carla/src/veins_carla/mobility

  • CarlaMobility.cc

这是名为CarlaMobility.cc的C++源代码文件,它似乎是与移动性模型相关的。以下是代码的简要解释:

initialize函数:初始化模块,在模拟开始时执行,设置一些模块参数和初始化数据结构。

handleMessage函数:处理消息,但在代码中是空的,没有具体的消息处理逻辑。

preInitialize函数:进行预初始化,设置车辆的外部ID、位置、速度和角度等参数。这个函数可能在车辆模拟之前调用,用于初始化车辆状态。

nextPosition函数:更新车辆的下一个位置,根据给定的位置、速度和角度。通常用于在车辆移动时更新位置信息。

changePosition函数:根据新的位置信息更改车辆的位置。这个函数会更新车辆的位置和速度信息,并记录一些统计数据。

fixIfHostGetsOutside函数:检查车辆是否超出了仿真场景的边界,如果超出了,会引发错误。

calculateHostPosition函数:根据车辆的位置和偏移量来计算车辆的位置。

这个文件似乎是一个用于模拟车辆移动性的组件,用于CARLA仿真环境。它处理车辆的位置、速度和角度,并确保车辆不会超出仿真场景的边界。

  • CarlaMobility.h
#include "veins_carla/veins_carla.h"
#include "veins/base/utils/Coord.h"
#include "veins/base/modules/BaseMobility.h"
#include "veins/base/utils/FindModule.h"
#include "veins/base/utils/Heading.h"
using namespace omnetpp;
using namespace veins;

namespace veins_carla {

class CarlaMobility : public BaseMobility {

protected:
    virtual void initialize(int stage) override;
    virtual void handleMessage(cMessage* msg) override;
    int numInitStages() const override
    {
        return std::max(cSimpleModule::numInitStages(), 2);
    }

public:
    CarlaMobility()
        : BaseMobility()
        , isPreInitialized(false)
    {

    }
    void preInitialize(std::string external_id, const Coord& position, double speed, double angle);
    virtual void changePosition();
    void nextPosition(const Coord& position, double speed, double angle);
protected:
    cOutVector currentPosXVec;   /**< vector plotting posx */
    cOutVector currentPosYVec;   /**< vector plotting posy */
    cOutVector currentSpeedVec;   /**< vector plotting speed */
    cOutVector currentAccelerationVec;   /**< vector plotting acceleration */
    cOutVector currentCO2EmissionVec;   /**< vector plotting current CO2 emission */

    bool isPreInitialized;   /**< true if preInitialize() has been called immediately before initialize() */

    std::string external_id;   /**< updated by setExternalId() */
    double hostPositionOffset;   /**< front offset for the antenna on this car */
    bool setHostSpeed;   /**< whether to update the speed of the host (along with its position)  */

    simtime_t lastUpdate;   /**< updated by nextPosition() */
    Coord roadPosition;   /**< position of front bumper, updated by nextPosition() */
    double speed;   /**< updated by nextPosition() */
    Heading heading;   /**< updated by nextPosition() */
private:

    /**
     * Calculates where the OMNeT++ module position of this UAV should be, given its front position
     */
    Coord calculateHostPosition(const Coord& vehiclePos) const;

    void fixIfHostGetsOutside() override;   /**< called after each read to check for (and handle) invalid positions */
};


class VEINS_API CarlaMobilityAccess {
public:
    CarlaMobility* get(cModule* host)
    {
        CarlaMobility* droci = FindModule<CarlaMobility*>::findSubModule(host);
        ASSERT(droci);
        return droci;
    };
};
}   // namespace airmobisim

这是名为CarlaMobility.h的C++头文件,它与移动性模型相关。以下是代码的简要解释:

initialize函数:虚拟函数,用于初始化模块,在模拟开始时执行,设置一些模块参数和初始化数据结构。

handleMessage函数:虚拟函数,用于处理消息,但在代码中是空的,没有具体的消息处理逻辑。

numInitStages函数:覆盖函数,用于指定初始化阶段的数量。

preInitialize函数:用于进行预初始化,设置车辆的外部ID、位置、速度和角度等参数。这个函数可能在车辆模拟之前调用,用于初始化车辆状态。

changePosition函数:虚拟函数,用于更改车辆的位置。通常用于在车辆移动时更新位置信息。

nextPosition函数:用于更新车辆的下一个位置,根据给定的位置、速度和角度。通常用于在车辆移动时更新位置信息。

类中包含一些用于记录位置、速度、加速度和其他数据的成员变量。

calculateHostPosition函数:用于计算车辆的位置,根据车辆位置和偏移量。

fixIfHostGetsOutside函数:虚拟函数,用于检查车辆是否超出了仿真场景的边界,如果超出了,会引发错误。

这个头文件定义了CarlaMobility类,它是一个用于模拟车辆移动性的组件,用于CARLA仿真环境。它处理车辆的位置、速度和角度,并确保车辆不会超出仿真场景的边界。

  • CarlaMobility.ned
package veins_carla.mobility;

import org.car2x.veins.base.modules.BaseMobility;

simple CarlaMobility extends BaseMobility
{
    @class(veins_carla::CarlaMobility);
    @display("i=block/cogwheel");
    double hostPositionOffset @unit("m") = default(0.0m);  // shift OMNeT++ module this far from front of the car
    bool setHostSpeed = default(false);  // whether to update the speed of the host (along with its position)        

}

这是名为 CarlaMobility.ned 的 NED 文件,定义了名为 CarlaMobility 的简单模块。以下是代码的简要解释:

package veins_carla.mobility:指定了模块的包路径。

simple CarlaMobility extends BaseMobility:定义了一个简单的移动性模块 CarlaMobility,继承自 BaseMobility。

@class(veins_carla::CarlaMobility):指定了该 NED 模块对应的 C++ 类。

@display(“i=block/cogwheel”):指定了在图形界面中如何显示该模块。

double hostPositionOffset @unit(“m”) = default(0.0m);:定义了模块的参数 hostPositionOffset,表示车辆模块在车辆前端的偏移量,默认为 0.0 米。

bool setHostSpeed = default(false);:定义了模块的参数 setHostSpeed,表示是否更新车辆的速度,默认为 false。

  • CarlaScenarioManager.cc
#include "CarlaScenarioManager.h"
using namespace omnetpp;
using namespace veins_carla;

Define_Module(CarlaScenarioManager);

void CarlaScenarioManager::initialize(int stage)
{
    if (stage == 0) {
        updateInterval = par("updateInterval").doubleValue();

        host = par("host").stdstringValue();
        port = par("port").intValue();
        moduleType = par("moduleType").stringValue();
        moduleName = par("moduleName").stringValue();
        moduleDisplayString = par("moduleDisplayString").stdstringValue();

        nextNodeVectorIndex = 0;
        hosts.clear();

        initMsg = new cMessage("init");
        startSimulationMsg = new cMessage();
        checkConnectionMsg = new cMessage();
        executeOneTimestepTrigger = new cMessage();
        checkConnectionMsg->setKind(checkConnectionMsgKind);
    }
    else {
        startCarlaAdapter();
    }
}

void CarlaScenarioManager::startCarlaAdapter()
{
    pid = fork();

    if (pid == 0) {
        signal(SIGINT, SIG_IGN);
        int runnumber = getSimulation()->getEnvir()->getConfigEx()->getActiveRunNumber();

        std::string sCommand = "cd ../../ && python3 ./carla_adapter.py";

        std::stringstream ssRunnumber;
        ssRunnumber << runnumber;
        std::string sRunnumber = ssRunnumber.str();
        sRunnumber = " -s " + sRunnumber;
        std::string sPort = std::string(" -p ") + std::to_string(port);
        std::cout << "update interval: " << updateInterval << std::endl;
        std::string sStepLength = std::string(" -l ") + std::to_string(updateInterval);

        std::cout << simTime().dbl() << ": executing: " << (sCommand + sRunnumber + sPort + sStepLength).c_str() << std::endl;

        int r = execl("/bin/sh", "sh", "-c", (sCommand + sRunnumber + sPort + sStepLength).c_str(), NULL);
        std::cout << simTime().dbl() << ": executing: " << sCommand << std::endl;

        if (r == -1) {
            throw cRuntimeError("system failed");
        }
        if (WEXITSTATUS(r) != 0) {
            throw cRuntimeError("cannot run");
        }
        throw cRuntimeError("returned from exec");
        exit(1);
    }
    scheduleAt(simTime() + updateInterval, startSimulationMsg);
    scheduleAt(simTime() + updateInterval, checkConnectionMsg);
}

void CarlaScenarioManager::handleMessage(cMessage* msg)
{
    if (msg == initMsg) {
        std::cout << simTime().dbl() << ": initMsg" << std::endl;
        startCarlaAdapter();
        return;
    }
    else if (msg == startSimulationMsg) {
        std::cout << simTime().dbl() << ": startSimulation" << std::endl;
        startSimulation();
        return;
    }
    else if (msg == executeOneTimestepTrigger) {
        std::cout << simTime().dbl() << ": executeOneTimestepTrigger" << std::endl;
        executeOneTimestep();
        return;
    }
}

void CarlaScenarioManager::startSimulation()
{
    std::cout <<"CarlaScenarioManager::startSimulation()" << std::endl;
    std::string hostAndPort = host+":" + std::to_string(port);
    channel = CreateChannel(hostAndPort, grpc::InsecureChannelCredentials());
    std::cout <<"CarlaScenarioManager::startSimulation(): Got a channel" << std::endl;
    stub = carla::CarlaAdapter::NewStub(channel);
    std::cout <<"CarlaScenarioManager::startSimulation(): Got new stub" << std::endl;
    auto state = channel->GetState(true);
    std::cout <<"CarlaScenarioManager::startSimulation(): Got a state" << std::endl;

    while (state != GRPC_CHANNEL_READY) {
        if (!channel->WaitForStateChange(state, std::chrono::system_clock::now() + std::chrono::seconds(15))) {
            error("Could not connect to gRPC");
        }
        state = channel->GetState(true);
        if (state == GRPC_CHANNEL_IDLE) {
            std::cout << "I do have a GRPC_CHANNEL_IDLE in WHILE -> " << state << std::endl;
        }
        else if (state == GRPC_CHANNEL_CONNECTING) {
            std::cout << "I do have a GRPC_CHANNEL_CONNECTING in WHILE -> " << state << std::endl;
        }
        else if (state == GRPC_CHANNEL_READY) {
            std::cout << "I do have a GRPC_CHANNEL_READY in WHILE -> " << state << std::endl;
        }
        else if (state == GRPC_CHANNEL_TRANSIENT_FAILURE) {
            std::cout << "I do have a GRPC_CHANNEL_TRANSIENT_FAILURE in WHILE -> " << state << std::endl;
        }
        else if (state == GRPC_CHANNEL_SHUTDOWN) {
            std::cout << "I do have a GRPC_CHANNEL_SHUTDOWN in WHILE -> " << state << std::endl;
        }
    }

    // Add all the Actors that are already part of the simulation
    carla::ActorIds actorIds = GetManagedHostIds();
    for (uint32_t i = 0; i < actorIds.actorid_size(); i++) {
        int actorId = actorIds.actorid(i);
        carla::Vehicle vehicle = GetManagedActorById(actorId);
        printVehicle(vehicle);
        Coord location;
        location.x = vehicle.location().x();
        location.y = vehicle.location().y();
        location.z = vehicle.location().z();
        std::cout << "Adding vehicle with location x = " << location.x << " y = " << location.y << " z = " << location.z << std::endl;

        addModule(std::to_string(vehicle.id()), moduleType.c_str(), moduleName.c_str(), moduleDisplayString, location, 0, 0, 4, 1.8, 4);// TODO
    }
    executeOneTimestep();
}

void CarlaScenarioManager::testInsertVehicle()
{
    carla::Vehicle vehicle;
    carla::Transform v = getRandomSpawnPoint();
    carla::Vector* pos = new carla::Vector();
    pos->set_x(v.location().x());
    pos->set_y(v.location().y());
    pos->set_z(v.location().z());

    vehicle.set_allocated_location(pos);
    insertVehicle(vehicle);
}
void CarlaScenarioManager::printVehicle(carla::Vehicle vehicle)
{
    std::cout << "=========================================" << std::endl;
    std::cout << vehicle.acceleration().x() << std::endl;
    std::cout << "Vehicle" << vehicle.id() << "\n"
        << "Acceleration.x = " << vehicle.acceleration().x() << "\n"
        << "Acceleration.y = " << vehicle.acceleration().y() << "\n"
        << "Acceleration.z = " << vehicle.acceleration().z() << "\n"
        << "Speed.x = " << vehicle.speed().x() << "\n"
        << "Speed.y = " << vehicle.speed().y() << "\n"
        << "Speed.z = " << vehicle.speed().z() << "\n"
        << "Position.x = " << vehicle.location().x() << "\n"
        << "Position.y = " << vehicle.location().y() << "\n"
        << "Position.z = " << vehicle.location().z() <<std::endl;
    std::cout << "=========================================" << std::endl;
}

carla::Vehicle CarlaScenarioManager::GetManagedActorById(int actorId)
{
    carla::Vehicle vehicle;
    carla::Number vehicleId;
    grpc::ClientContext clientContext;
    vehicleId.set_num(actorId);

    grpc::Status status = stub->GetManagedActorById(&clientContext, vehicleId, &vehicle);
    if (status.ok()) {
        return vehicle;
    }
    else {
        error((std::string("CarlaScenarioManager::GetManagedActorById() failed with error: " + std::string(status.error_message())).c_str()));
    }
}

void CarlaScenarioManager::insertVehicle(carla::Vehicle request)
{
    carla::Number vehicleId;
    grpc::ClientContext clientContext;
    std::cout << "Inserting vehicle at location: " << request.location().x() << "/" << request.location().y() << "/" << request.location().z() << std::endl;
    grpc::Status status = stub->InsertVehicle(&clientContext, request, &vehicleId);
    if (status.ok()) {
        std::cout << "Yay there is a new vehicle" << std::endl;
    }
    else {
        error((std::string("CarlaScenarioManager::insertVehicle() failed with error: " + std::string(status.error_message())).c_str()));
    }
    Coord pos;
    pos.x = request.location().x();
    pos.y = request.location().y();
    pos.z = request.location().z();

    addModule(std::to_string(vehicleId.num()), moduleType.c_str(), moduleName.c_str(), moduleDisplayString, pos, 0, 0, 4, 1.8, 4);// TODO
}

carla::Transform CarlaScenarioManager::getRandomSpawnPoint()
{
    google::protobuf::Empty request;
    carla::Transform response;
    grpc::ClientContext clientContext;
    grpc::Status status = stub->GetRandomSpawnPoint(&clientContext, request, &response);
    if (status.ok()) {
        std::cout << "getRandomSpawnPoint:" << response.location().x() << "/" << response.location().y() << "/" << response.location().z() << std::endl;
        return response;
    }
    else {
        error((std::string("CarlaScenarioManager::getRandomSpawnPoint() failed with error: " + std::string(status.error_message())).c_str()));
    }
}


void CarlaScenarioManager::executeOneTimestep()
{
    std::cout << simTime().dbl() << ": executeOneTimestep()" << std::endl;
    google::protobuf::Empty responseEmpty;
    google::protobuf::Empty empty;
    grpc::ClientContext clientContext;
    grpc::Status status = stub->ExecuteOneTimeStep(&clientContext, empty, &responseEmpty);

    if (status.ok()) {

        carla::ActorIds actors = GetManagedHostIds();
        for (uint32_t i = 0; i < actors.actorid_size(); i++) {
            auto actorId = actors.actorid(i);
            carla::Vehicle v = GetManagedActorById(actorId);
            Coord location;
            location.x = v.location().x();
            location.y = v.location().y();
            location.z = v.location().z();
            double speed = 0; // TODO
            double angle = 0;
            processVehicleSubscription(v.id(), location, speed, angle);

        }
        if (!executeOneTimestepTrigger->isScheduled()) {
            scheduleAt(simTime() + updateInterval, executeOneTimestepTrigger);
        }

    }
    else {
        error((std::string("CarlaScenarioManager::executeOneTimestep() failed with error: " + std::string(status.error_message())).c_str()));
    }
}

void CarlaScenarioManager::processVehicleSubscription(int actorId, Coord location, double speed, double angle)
{

    cModule* mod = getManagedModule(std::to_string(actorId));
    if (!mod) {

        carla::Vehicle vehicle = GetManagedActorById(actorId);
        printVehicle(vehicle);
        Coord location;
        location.x = vehicle.location().x();
        location.y = vehicle.location().y();
        location.z = vehicle.location().z();
        std::cout << "Adding vehicle with location x = " << location.x << " y = " << location.y << " z = " << location.z << std::endl;

        addModule(std::to_string(vehicle.id()), moduleType.c_str(), moduleName.c_str(),
            moduleDisplayString, location, 0, 0, 4, 1.8, 4);            // TODO
    }
    else {
        // module existed - update position

        /**********************************************/
        location.x = location.x + POSITIONOFFSET;
        location.y = location.y + POSITIONOFFSET;
        /**********************************************/

        EV_DEBUG << "module " << actorId << " moving to " << location.x << "," << location.y << " with heading" << angle << endl;
        std::cout << "module " << actorId << " moving to " << location.x << "," << location.y << " with heading" << angle << std::endl;


        updateModulePosition(mod, location, speed, angle);
    }
}
void CarlaScenarioManager::updateModulePosition(cModule* mod, const Coord& location, double speed, double angle)
{
    // update position in CarlaMobility
    auto mobilityModules = getSubmodulesOfType<CarlaMobility>(mod);
    for (auto mm : mobilityModules) {
        mm->nextPosition(location, speed, angle);
    }
}

cModule* CarlaScenarioManager::getManagedModule(std::string actorId)
{
    if (hosts.find(actorId) == hosts.end())
        return nullptr;
    return hosts[actorId];
}
carla::ActorIds CarlaScenarioManager::GetManagedHostIds()
{
    carla::ActorIds actorIds;
    google::protobuf::Empty empty;
    grpc::ClientContext clientContext;
    grpc::Status status = stub->GetManagedActorsIds(&clientContext, empty, &actorIds);

    if (status.ok()) {
        std::cout << "I got " << actorIds.actorid_size() << " actors with these ids: " << std::endl;
        for (uint32_t i = 0; i < actorIds.actorid_size(); i++) {
            std::cout << actorIds.actorid(i)<< std::endl;
        }
    }
    else {
        error((std::string("CarlaScenarioManager::GetManagedHostIds() failed with error: " + std::string(status.error_message())).c_str()));
    }
    return actorIds;
}


void CarlaScenarioManager::addModule(std::string nodeId, std::string moduleType, std::string moduleName, std::string displayString, veins::Coord& position, double speed, double angle, double length, double height, double width)
{
    std::cout << "addModule called for module id " << nodeId << std::endl;
    int32_t nodeVectorIndex = nextNodeVectorIndex++;

    cModule* parentmod = getParentModule();
    if (!parentmod)
        throw cRuntimeError("Parent Module not found");

    cModuleType* nodeType = cModuleType::get(moduleType.c_str());
    if (!nodeType)
        throw cRuntimeError("Module Type \"%s\" not found", moduleType.c_str());

#if OMNETPP_BUILDNUM >= 1525
    parentmod->setSubmoduleVectorSize(moduleName.c_str(), nodeVectorIndex + 1);
    cModule* mod = nodeType->create(moduleName.c_str(), parentmod, nodeVectorIndex);
#else
    cModule* mod = nodeType->create(moduleName.c_str(), parentmod, nodeVectorIndex, nodeVectorIndex);
#endif
    mod->finalizeParameters();
    std::cout << "Display string is: " << displayString << std::endl;
    if (displayString.length() > 0) {
        mod->getDisplayString().parse(displayString.c_str());
    }
    mod->buildInside();
    mod->scheduleStart(simTime() + updateInterval);

    /**********************************************/
    position.x = position.x + POSITIONOFFSET;
    position.y = position.y + POSITIONOFFSET;
    /**********************************************/
    preInitializeModule(mod, nodeId, position, speed, angle);

    mod->callInitialize();
    hosts[nodeId] = mod;
}



void CarlaScenarioManager::preInitializeModule(cModule* mod, const std::string& nodeId, const Coord& position, double speed, double angle)
{
    // pre-initialize Mobility
    auto mobilityModules = getSubmodulesOfType<CarlaMobility>(mod);
    for (auto mm : mobilityModules) {
        mm->preInitialize(nodeId, position, speed, angle);
    }
}

这是名为 CarlaScenarioManager.cc 的 C++ 代码文件,它实现了一个名为 CarlaScenarioManager 的模块。以下是代码的简要解释:

#include 语句:包含所需的头文件。

Define_Module(CarlaScenarioManager):使用 OMNeT++ 宏定义了模块。

void CarlaScenarioManager::initialize(int stage):初始化函数,根据 stage 的不同执行初始化步骤。

void CarlaScenarioManager::startCarlaAdapter():启动 Carla 仿真适配器的函数,使用 fork 创建子进程,并执行 Python 脚本 carla_adapter.py。

void CarlaScenarioManager::handleMessage(cMessage* msg):消息处理函数,根据接收到的消息类型执行相应的操作。

void CarlaScenarioManager::startSimulation():启动仿真函数,建立 gRPC 通道,获取车辆信息,并在仿真环境中添加相应的模块。

void CarlaScenarioManager::testInsertVehicle():测试函数,插入一个车辆。

void CarlaScenarioManager::printVehicle(carla::Vehicle vehicle):打印车辆信息。

carla::Vehicle CarlaScenarioManager::GetManagedActorById(int actorId):根据车辆 ID 获取车辆信息。

void CarlaScenarioManager::insertVehicle(carla::Vehicle request):插入车辆信息。

carla::Transform CarlaScenarioManager::getRandomSpawnPoint():获取随机生成的车辆初始位置。

void CarlaScenarioManager::executeOneTimestep():执行仿真的一个时间步。

void CarlaScenarioManager::processVehicleSubscription(int actorId, Coord location, double speed, double angle):处理车辆订阅。

void CarlaScenarioManager::updateModulePosition(cModule* mod, const Coord& location, double speed, double angle):更新模块的位置。

cModule* CarlaScenarioManager::getManagedModule(std::string actorId):根据车辆 ID 获取管理的模块。

carla::ActorIds CarlaScenarioManager::GetManagedHostIds():获取管理的车辆 ID。

void CarlaScenarioManager::addModule(…):添加模块。

void CarlaScenarioManager::preInitializeModule(cModule* mod, const std::string& nodeId, const Coord& position, double speed, double angle):预初始化模块。

这个文件实现了一个用于管理 CARLA 仿真场景的模块,包括与 CARLA 仿真适配器的通信、车辆的插入和更新等功能。

  • CarlaScenarioManager.h
#include <omnetpp.h>
#include <google/protobuf/empty.pb.h>
#include <grpcpp/grpcpp.h>
#include <signal.h>

#include "../proto/carla.grpc.pb.h"
#include "veins/base/utils/Coord.h"
#include "veins/modules/mobility/traci/TraCICoordinateTransformation.h"

#include "CarlaMobility.h"

using namespace omnetpp;
// using namespace veins;

namespace veins_carla {
class CarlaScenarioManager : public cSimpleModule {
protected:
    virtual void initialize(int stage) override;
    virtual void handleMessage(cMessage* msg) override;
    int numInitStages() const override
    {
        return std::max(cSimpleModule::numInitStages(), 2);
    }

    void startCarlaAdapter();
    void startSimulation();
    void insertVehicle(carla::Vehicle request);
    carla::ActorIds GetManagedHostIds();
    carla::Vehicle GetManagedActorById(int actorId);
    carla::Transform getRandomSpawnPoint();

private:
    void executeOneTimestep();
    void addModule(std::string nodeId, std::string moduleType, std::string moduleName, std::string displayString, veins::Coord& position, double speed, double angle, double length, double height, double width);
    void printVehicle(carla::Vehicle vehicle);
    void preInitializeModule(cModule* mod, const std::string& nodeId, const Coord& position, double speed, double angle);
    void processVehicleSubscription(int actorId, Coord location, double speed, double angle);
    cModule* getManagedModule(std::string actorId);
    void updateModulePosition(cModule* mod, const Coord& location, double speed, double angle);
    void testInsertVehicle();
private:
    std::shared_ptr<grpc::Channel> channel;
    // std::unique_ptr<carla::Carla::Stub> stub;
    std::unique_ptr<carla::CarlaAdapter::Stub> stub;
    double updateInterval;
    double simTimeLimit;

    int POSITIONOFFSET = 2000;

    int port;
    std::string host;

    omnetpp::cMessage* initMsg;
    omnetpp::cMessage* startSimulationMsg;
    omnetpp::cMessage* executeOneTimestepTrigger;
    omnetpp::cMessage* checkConnectionMsg;
    int checkConnectionMsgKind = 1337;
    size_t nextNodeVectorIndex; /**< next OMNeT++ module vector index to use */

    std::map<std::string, cModule*> hosts; /**< vector of all hosts managed by us */

    std::string moduleDisplayString;
    std::string moduleType;
    std::string moduleName;

    pid_t pid;


    std::unique_ptr<TraCICoordinateTransformation> coordinateTransformation;
};

} // namespace veins_carla

这是名为 CarlaScenarioManager.h 的 C++ 头文件,定义了一个名为 CarlaScenarioManager 的类。以下是代码的简要解释:

#include 语句:包含所需的头文件。

using namespace omnetpp;:使用 OMNeT++ 命名空间。

namespace veins_carla:定义了一个名为 veins_carla 的命名空间。

class CarlaScenarioManager : public cSimpleModule:定义了一个继承自 cSimpleModule 的类 CarlaScenarioManager。

protected 部分:包含类的保护成员和方法,包括初始化、消息处理和其他辅助函数。

private 部分:包含类的私有成员,如 gRPC 通道、仿真参数、消息等。

POSITIONOFFSET:一个整数常量,表示位置的偏移。

updateInterval、simTimeLimit、port、host 等变量:用于存储仿真参数、通信端口和主机信息。

std::shared_ptrgrpc::Channel channel:gRPC 通道的共享指针。

std::unique_ptrcarla::CarlaAdapter::Stub stub:用于与 CARLA 仿真适配器通信的 gRPC 存根的唯一指针。

nextNodeVectorIndex:下一个 OMNeT++ 模块向量索引。

hosts:一个映射,将车辆 ID 映射到其相应的 OMNeT++ 模块。

moduleDisplayString、moduleType、moduleName:用于定义添加的模块的显示字符串、类型和名称。

pid:用于存储 fork 启动的子进程的进程 ID。

TraCICoordinateTransformation:TraCI 坐标转换的唯一指针。

类的方法包括初始化、消息处理、启动 CARLA 适配器、开始仿真、插入车辆、获取车辆信息、获取随机生成的车辆初始位置等。

namespace veins_carla 闭合了类的定义。

这个头文件定义了管理 CARLA 仿真场景的模块的类,包括与 CARLA 仿真适配器的通信、车辆的插入和更新等功能。

  • CarlaScenarioManager.ned
package veins_carla.mobility;

simple CarlaScenarioManager
{
    parameters:
    	@class(veins_carla::CarlaScenarioManager);
        double connectAt @unit("s") = default(0s);  // when to connect to TraCI server (must be the initial timestep of the server)
        double updateInterval @unit("s") = default(1s);  // time interval of hosts' position updates
        string moduleType = default("veins_carla.nodes.CarlaCar");  // module type to be used in the simulation for each managed vehicle
        string moduleName = default("node");  // module name to be used in the simulation for each managed vehicle
        string moduleDisplayString = default("i=veins/node/car;is=vs'");
        string host = default("localhost");  // GRPC server hostname
        int port = default(1337);  
}

这是名为 CarlaScenarioManager.ned 的 NED 文件,定义了一个名为 CarlaScenarioManager 的简单模块。以下是代码的简要解释:

package veins_carla.mobility;:定义了命名空间为 veins_carla.mobility。

simple CarlaScenarioManager:定义了一个简单模块,即 CarlaScenarioManager。

parameters 部分:包含模块的参数,可以在模拟配置中配置。这些参数包括:

connectAt:连接到 TraCI 服务器的时间(默认为 0 秒)。
updateInterval:主机位置更新的时间间隔(默认为 1 秒)。
moduleType:在仿真中用于每个受管理车辆的模块类型(默认为 “veins_carla.nodes.CarlaCar”)。
moduleName:在仿真中用于每个受管理车辆的模块名称(默认为 “node”)。
moduleDisplayString:每个受管理车辆在仿真中的显示字符串(默认为 “i=veins/node/car;is=vs’”)。
host:gRPC 服务器的主机名(默认为 “localhost”)。
port:gRPC 服务器的端口号(默认为 1337)。
@class(veins_carla::CarlaScenarioManager);:指定了该模块对应的 C++ 类为 veins_carla::CarlaScenarioManager。

这个 NED 文件定义了一个模块,用于管理 CARLA 仿真场景,包括连接到 TraCI 服务器、更新主机位置、配置模块类型和显示字符串等功能。

veins_carla/src/veins_carla/nodes

  • CarlaCar.ned
package veins_carla.nodes;


module CarlaCar
{
 parameters:
        string applType = default("ExampleCarlaApplication"); //type of the application layer
        string nicType  = default("Nic80211p"); // type of network interface card
        string mobilityType = default("CarlaMobility"); //type of the mobility module
    gates:
        input veinsradioIn;
    submodules:
        appl: <applType> like org.car2x.veins.base.modules.IBaseApplLayer {
            parameters:
                @display("p=60,50");
        }

        nic: <nicType> like org.car2x.veins.modules.nic.INic80211p {
          parameters:
               @display("p=60,166");
        }
        carlaMobility: <mobilityType> like org.car2x.veins.base.modules.IMobility {
            parameters:
                @display("p=130,172;i=block/cogwheel");
        }
        
     connections:
        nic.upperLayerOut --> appl.lowerLayerIn;
        nic.upperLayerIn <-- appl.lowerLayerOut;
        nic.upperControlOut --> appl.lowerControlIn;
        nic.upperControlIn <-- appl.lowerControlOut;
        veinsradioIn --> nic.radioIn;
}

这是一个定义仿真车辆模块的NED文件(Network Description)。让我解释一下其中的主要部分:

参数部分:

applType:定义应用层的类型,默认为"ExampleCarlaApplication"。
nicType:定义网络接口卡的类型,默认为"Nic80211p"。
mobilityType:定义移动性模块的类型,默认为"CarlaMobility"。
门(Gates)部分:

input veinsradioIn;:定义一个输入门,表示仿真中车辆接收到的无线电信号。
子模块部分:

appl:定义一个应用层模块,类型由applType指定,遵循org.car2x.veins.base.modules.IBaseApplLayer接口。
nic:定义一个网络接口卡模块,类型由nicType指定,遵循org.car2x.veins.modules.nic.INic80211p接口。
carlaMobility:定义一个移动性模块,类型由mobilityType指定,遵循org.car2x.veins.base.modules.IMobility接口。
连接部分:

nic.upperLayerOut --> appl.lowerLayerIn;:连接网络接口卡的上层输出到应用层的下层输入。
nic.upperLayerIn <-- appl.lowerLayerOut;:连接网络接口卡的上层输入到应用层的下层输出。
nic.upperControlOut --> appl.lowerControlIn;:连接网络接口卡的上层控制输出到应用层的下层控制输入。
nic.upperControlIn <-- appl.lowerControlOut;:连接网络接口卡的上层控制输入到应用层的下层控制输出。
veinsradioIn --> nic.radioIn;:连接仿真中车辆收到的无线电信号到网络接口卡的无线电信号输入。
这个模块描述了一个仿真中的车辆,定义了它的应用层、网络接口卡和移动性模块,并模拟了它们之间的连接关系。

  • CarlaScenario.ned
package veins_carla.nodes;

import org.car2x.veins.base.connectionManager.ConnectionManager;
import org.car2x.veins.base.modules.BaseWorldUtility;
import org.car2x.veins.modules.world.annotations.AnnotationManager;
import org.car2x.veins.modules.obstacle.ObstacleControl;
import org.car2x.veins.nodes.Car;
import org.car2x.veins.visualizer.roads.RoadsCanvasVisualizer;
import veins_carla.mobility.CarlaScenarioManager;

network CarlaScenario {
     parameters:
        double playgroundSizeX @unit(m); // x size of the area the nodes are in (in meters)
        double playgroundSizeY @unit(m); // y size of the area the nodes are in (in meters)
        double playgroundSizeZ @unit(m); // z size of the area the nodes are in (in meters)
        @display("bgb=$playgroundSizeX,$playgroundSizeY");
    submodules:
        obstacles: ObstacleControl {
            @display("p=240,50");
        }
        annotations: AnnotationManager {
            @display("p=260,50");
        }
        connectionManager: ConnectionManager {
            parameters:
                @display("p=150,0;i=abstract/multicast");
        }
        manager: CarlaScenarioManager {
        
        }
        world: BaseWorldUtility {
            parameters:
                playgroundSizeX = veins_eval_by_version(veins_omnetpp_buildnum(), "playgroundSizeX", 1525, "parent.playgroundSizeX");
                playgroundSizeY = veins_eval_by_version(veins_omnetpp_buildnum(), "playgroundSizeY", 1525, "parent.playgroundSizeY");
                playgroundSizeZ = veins_eval_by_version(veins_omnetpp_buildnum(), "playgroundSizeZ", 1525, "parent.playgroundSizeZ");
                @display("p=30,0;i=misc/globe");
        }
        node[0]: Car {
        }

    connections allowunconnected:
}

这是一个描述仿真场景的NED文件。以下是对代码的简要解释:

网络类型定义:

network CarlaScenario:定义了一个名为CarlaScenario的网络。
网络参数部分:

playgroundSizeX、playgroundSizeY、playgroundSizeZ:定义了仿真场景的尺寸,即节点所在区域的长、宽、高。
@display:通过此注解设置仿真场景的背景显示大小。
子模块部分:

obstacles:定义了障碍物控制模块,用于处理仿真中的障碍物。
annotations:定义了注释管理器模块,用于管理注释。
connectionManager:定义了连接管理器模块,用于处理节点之间的连接。
manager:使用了之前定义的CarlaScenarioManager模块,负责管理Carla仿真的场景。
world:定义了基础世界实用程序模块,用于设置仿真场景的大小。
node[0]: Car:定义了一个名为Car的节点。这是仿真中的车辆,类型为Car。
Connections部分:

connections allowunconnected:表示允许未连接的部分,即允许节点之间没有直接连接。
这个NED文件描述了一个Carla仿真场景,包括车辆节点、障碍物、注释管理等组件。CarlaScenarioManager模块被用于管理Carla仿真的场景。

veins_carla/src/veins_carla/proto

  • carla.grpc.pb.cc
#include "carla.pb.h"
#include "carla.grpc.pb.h"

#include <functional>
#include <grpcpp/impl/codegen/async_stream.h>
#include <grpcpp/impl/codegen/async_unary_call.h>
#include <grpcpp/impl/codegen/channel_interface.h>
#include <grpcpp/impl/codegen/client_unary_call.h>
#include <grpcpp/impl/codegen/client_callback.h>
#include <grpcpp/impl/codegen/message_allocator.h>
#include <grpcpp/impl/codegen/method_handler.h>
#include <grpcpp/impl/codegen/rpc_service_method.h>
#include <grpcpp/impl/codegen/server_callback.h>
#include <grpcpp/impl/codegen/server_callback_handlers.h>
#include <grpcpp/impl/codegen/server_context.h>
#include <grpcpp/impl/codegen/service_type.h>
#include <grpcpp/impl/codegen/sync_stream.h>
namespace carla {

static const char* CarlaAdapter_method_names[] = {
    "/carla.CarlaAdapter/ExecuteOneTimeStep",
    "/carla.CarlaAdapter/Finish",
    "/carla.CarlaAdapter/GetManagedActorsIds",
    "/carla.CarlaAdapter/GetManagedActorById",
    "/carla.CarlaAdapter/InsertVehicle",
    "/carla.CarlaAdapter/GetRandomSpawnPoint",
};

std::unique_ptr<CarlaAdapter::Stub> CarlaAdapter::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options)
{
    (void)options;
    std::unique_ptr<CarlaAdapter::Stub> stub(new CarlaAdapter::Stub(channel, options));
    return stub;
}

CarlaAdapter::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options)
    : channel_(channel)
    , rpcmethod_ExecuteOneTimeStep_(CarlaAdapter_method_names[0], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
    , rpcmethod_Finish_(CarlaAdapter_method_names[1], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
    , rpcmethod_GetManagedActorsIds_(CarlaAdapter_method_names[2], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
    , rpcmethod_GetManagedActorById_(CarlaAdapter_method_names[3], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
    , rpcmethod_InsertVehicle_(CarlaAdapter_method_names[4], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
    , rpcmethod_GetRandomSpawnPoint_(CarlaAdapter_method_names[5], options.suffix_for_stats(), ::grpc::internal::RpcMethod::NORMAL_RPC, channel)
{}

::grpc::Status CarlaAdapter::Stub::ExecuteOneTimeStep(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::Empty* response)
{
    return ::grpc::internal::BlockingUnaryCall< ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_ExecuteOneTimeStep_, context, request, response);
}

void CarlaAdapter::Stub::experimental_async::ExecuteOneTimeStep(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, std::function<void(::grpc::Status)> f)
{
    ::grpc::internal::CallbackUnaryCall< ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_ExecuteOneTimeStep_, context, request, response, std::move(f));
}

void CarlaAdapter::Stub::experimental_async::ExecuteOneTimeStep(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, ::grpc::experimental::ClientUnaryReactor* reactor)
{
    ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_ExecuteOneTimeStep_, context, request, response, reactor);
}

::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* CarlaAdapter::Stub::PrepareAsyncExecuteOneTimeStepRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq)
{
    return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_ExecuteOneTimeStep_, context, request);
}

::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* CarlaAdapter::Stub::AsyncExecuteOneTimeStepRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq)
{
    auto* result =
        this->PrepareAsyncExecuteOneTimeStepRaw(context, request, cq);
    result->StartCall();
    return result;
}

::grpc::Status CarlaAdapter::Stub::Finish(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::Empty* response)
{
    return ::grpc::internal::BlockingUnaryCall< ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_Finish_, context, request, response);
}

void CarlaAdapter::Stub::experimental_async::Finish(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, std::function<void(::grpc::Status)> f)
{
    ::grpc::internal::CallbackUnaryCall< ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Finish_, context, request, response, std::move(f));
}

void CarlaAdapter::Stub::experimental_async::Finish(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, ::grpc::experimental::ClientUnaryReactor* reactor)
{
    ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_Finish_, context, request, response, reactor);
}

::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* CarlaAdapter::Stub::PrepareAsyncFinishRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq)
{
    return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_Finish_, context, request);
}

::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* CarlaAdapter::Stub::AsyncFinishRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq)
{
    auto* result =
        this->PrepareAsyncFinishRaw(context, request, cq);
    result->StartCall();
    return result;
}

::grpc::Status CarlaAdapter::Stub::GetManagedActorsIds(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::carla::ActorIds* response)
{
    return ::grpc::internal::BlockingUnaryCall< ::google::protobuf::Empty, ::carla::ActorIds, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GetManagedActorsIds_, context, request, response);
}

void CarlaAdapter::Stub::experimental_async::GetManagedActorsIds(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::carla::ActorIds* response, std::function<void(::grpc::Status)> f)
{
    ::grpc::internal::CallbackUnaryCall< ::google::protobuf::Empty, ::carla::ActorIds, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetManagedActorsIds_, context, request, response, std::move(f));
}

void CarlaAdapter::Stub::experimental_async::GetManagedActorsIds(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::carla::ActorIds* response, ::grpc::experimental::ClientUnaryReactor* reactor)
{
    ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetManagedActorsIds_, context, request, response, reactor);
}

::grpc::ClientAsyncResponseReader< ::carla::ActorIds>* CarlaAdapter::Stub::PrepareAsyncGetManagedActorsIdsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq)
{
    return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::carla::ActorIds, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GetManagedActorsIds_, context, request);
}

::grpc::ClientAsyncResponseReader< ::carla::ActorIds>* CarlaAdapter::Stub::AsyncGetManagedActorsIdsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq)
{
    auto* result =
        this->PrepareAsyncGetManagedActorsIdsRaw(context, request, cq);
    result->StartCall();
    return result;
}

::grpc::Status CarlaAdapter::Stub::GetManagedActorById(::grpc::ClientContext* context, const ::carla::Number& request, ::carla::Vehicle* response)
{
    return ::grpc::internal::BlockingUnaryCall< ::carla::Number, ::carla::Vehicle, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GetManagedActorById_, context, request, response);
}

void CarlaAdapter::Stub::experimental_async::GetManagedActorById(::grpc::ClientContext* context, const ::carla::Number* request, ::carla::Vehicle* response, std::function<void(::grpc::Status)> f)
{
    ::grpc::internal::CallbackUnaryCall< ::carla::Number, ::carla::Vehicle, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetManagedActorById_, context, request, response, std::move(f));
}

void CarlaAdapter::Stub::experimental_async::GetManagedActorById(::grpc::ClientContext* context, const ::carla::Number* request, ::carla::Vehicle* response, ::grpc::experimental::ClientUnaryReactor* reactor)
{
    ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetManagedActorById_, context, request, response, reactor);
}

::grpc::ClientAsyncResponseReader< ::carla::Vehicle>* CarlaAdapter::Stub::PrepareAsyncGetManagedActorByIdRaw(::grpc::ClientContext* context, const ::carla::Number& request, ::grpc::CompletionQueue* cq)
{
    return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::carla::Vehicle, ::carla::Number, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GetManagedActorById_, context, request);
}

::grpc::ClientAsyncResponseReader< ::carla::Vehicle>* CarlaAdapter::Stub::AsyncGetManagedActorByIdRaw(::grpc::ClientContext* context, const ::carla::Number& request, ::grpc::CompletionQueue* cq)
{
    auto* result =
        this->PrepareAsyncGetManagedActorByIdRaw(context, request, cq);
    result->StartCall();
    return result;
}

::grpc::Status CarlaAdapter::Stub::InsertVehicle(::grpc::ClientContext* context, const ::carla::Vehicle& request, ::carla::Number* response)
{
    return ::grpc::internal::BlockingUnaryCall< ::carla::Vehicle, ::carla::Number, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_InsertVehicle_, context, request, response);
}

void CarlaAdapter::Stub::experimental_async::InsertVehicle(::grpc::ClientContext* context, const ::carla::Vehicle* request, ::carla::Number* response, std::function<void(::grpc::Status)> f)
{
    ::grpc::internal::CallbackUnaryCall< ::carla::Vehicle, ::carla::Number, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_InsertVehicle_, context, request, response, std::move(f));
}

void CarlaAdapter::Stub::experimental_async::InsertVehicle(::grpc::ClientContext* context, const ::carla::Vehicle* request, ::carla::Number* response, ::grpc::experimental::ClientUnaryReactor* reactor)
{
    ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_InsertVehicle_, context, request, response, reactor);
}

::grpc::ClientAsyncResponseReader< ::carla::Number>* CarlaAdapter::Stub::PrepareAsyncInsertVehicleRaw(::grpc::ClientContext* context, const ::carla::Vehicle& request, ::grpc::CompletionQueue* cq)
{
    return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::carla::Number, ::carla::Vehicle, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_InsertVehicle_, context, request);
}

::grpc::ClientAsyncResponseReader< ::carla::Number>* CarlaAdapter::Stub::AsyncInsertVehicleRaw(::grpc::ClientContext* context, const ::carla::Vehicle& request, ::grpc::CompletionQueue* cq)
{
    auto* result =
        this->PrepareAsyncInsertVehicleRaw(context, request, cq);
    result->StartCall();
    return result;
}

::grpc::Status CarlaAdapter::Stub::GetRandomSpawnPoint(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::carla::Transform* response)
{
    return ::grpc::internal::BlockingUnaryCall< ::google::protobuf::Empty, ::carla::Transform, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GetRandomSpawnPoint_, context, request, response);
}

void CarlaAdapter::Stub::experimental_async::GetRandomSpawnPoint(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::carla::Transform* response, std::function<void(::grpc::Status)> f)
{
    ::grpc::internal::CallbackUnaryCall< ::google::protobuf::Empty, ::carla::Transform, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetRandomSpawnPoint_, context, request, response, std::move(f));
}

void CarlaAdapter::Stub::experimental_async::GetRandomSpawnPoint(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::carla::Transform* response, ::grpc::experimental::ClientUnaryReactor* reactor)
{
    ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GetRandomSpawnPoint_, context, request, response, reactor);
}

::grpc::ClientAsyncResponseReader< ::carla::Transform>* CarlaAdapter::Stub::PrepareAsyncGetRandomSpawnPointRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq)
{
    return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::carla::Transform, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GetRandomSpawnPoint_, context, request);
}

::grpc::ClientAsyncResponseReader< ::carla::Transform>* CarlaAdapter::Stub::AsyncGetRandomSpawnPointRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq)
{
    auto* result =
        this->PrepareAsyncGetRandomSpawnPointRaw(context, request, cq);
    result->StartCall();
    return result;
}

CarlaAdapter::Service::Service()
{
    AddMethod(new ::grpc::internal::RpcServiceMethod(
            CarlaAdapter_method_names[0],
            ::grpc::internal::RpcMethod::NORMAL_RPC,
            new ::grpc::internal::RpcMethodHandler<CarlaAdapter::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
                [](CarlaAdapter::Service* service,
                ::grpc::ServerContext* ctx,
                const ::google::protobuf::Empty* req,
                ::google::protobuf::Empty* resp) {
            return service->ExecuteOneTimeStep(ctx, req, resp);
        }, this)));
    AddMethod(new ::grpc::internal::RpcServiceMethod(
            CarlaAdapter_method_names[1],
            ::grpc::internal::RpcMethod::NORMAL_RPC,
            new ::grpc::internal::RpcMethodHandler<CarlaAdapter::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
                [](CarlaAdapter::Service* service,
                ::grpc::ServerContext* ctx,
                const ::google::protobuf::Empty* req,
                ::google::protobuf::Empty* resp) {
            return service->Finish(ctx, req, resp);
        }, this)));
    AddMethod(new ::grpc::internal::RpcServiceMethod(
            CarlaAdapter_method_names[2],
            ::grpc::internal::RpcMethod::NORMAL_RPC,
            new ::grpc::internal::RpcMethodHandler<CarlaAdapter::Service, ::google::protobuf::Empty, ::carla::ActorIds, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
                [](CarlaAdapter::Service* service,
                ::grpc::ServerContext* ctx,
                const ::google::protobuf::Empty* req,
                ::carla::ActorIds* resp) {
            return service->GetManagedActorsIds(ctx, req, resp);
        }, this)));
    AddMethod(new ::grpc::internal::RpcServiceMethod(
            CarlaAdapter_method_names[3],
            ::grpc::internal::RpcMethod::NORMAL_RPC,
            new ::grpc::internal::RpcMethodHandler<CarlaAdapter::Service, ::carla::Number, ::carla::Vehicle, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
                [](CarlaAdapter::Service* service,
                ::grpc::ServerContext* ctx,
                const ::carla::Number* req,
                ::carla::Vehicle* resp) {
            return service->GetManagedActorById(ctx, req, resp);
        }, this)));
    AddMethod(new ::grpc::internal::RpcServiceMethod(
            CarlaAdapter_method_names[4],
            ::grpc::internal::RpcMethod::NORMAL_RPC,
            new ::grpc::internal::RpcMethodHandler<CarlaAdapter::Service, ::carla::Vehicle, ::carla::Number, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
                [](CarlaAdapter::Service* service,
                ::grpc::ServerContext* ctx,
                const ::carla::Vehicle* req,
                ::carla::Number* resp) {
            return service->InsertVehicle(ctx, req, resp);
        }, this)));
    AddMethod(new ::grpc::internal::RpcServiceMethod(
            CarlaAdapter_method_names[5],
            ::grpc::internal::RpcMethod::NORMAL_RPC,
            new ::grpc::internal::RpcMethodHandler<CarlaAdapter::Service, ::google::protobuf::Empty, ::carla::Transform, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(
                [](CarlaAdapter::Service* service,
                ::grpc::ServerContext* ctx,
                const ::google::protobuf::Empty* req,
                ::carla::Transform* resp) {
            return service->GetRandomSpawnPoint(ctx, req, resp);
        }, this)));
}

CarlaAdapter::Service::~Service()
{
}

::grpc::Status CarlaAdapter::Service::ExecuteOneTimeStep(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response)
{
    (void) context;
    (void) request;
    (void) response;
    return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}

::grpc::Status CarlaAdapter::Service::Finish(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response)
{
    (void) context;
    (void) request;
    (void) response;
    return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}

::grpc::Status CarlaAdapter::Service::GetManagedActorsIds(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::carla::ActorIds* response)
{
    (void) context;
    (void) request;
    (void) response;
    return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}

::grpc::Status CarlaAdapter::Service::GetManagedActorById(::grpc::ServerContext* context, const ::carla::Number* request, ::carla::Vehicle* response)
{
    (void) context;
    (void) request;
    (void) response;
    return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}

::grpc::Status CarlaAdapter::Service::InsertVehicle(::grpc::ServerContext* context, const ::carla::Vehicle* request, ::carla::Number* response)
{
    (void) context;
    (void) request;
    (void) response;
    return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}

::grpc::Status CarlaAdapter::Service::GetRandomSpawnPoint(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::carla::Transform* response)
{
    (void) context;
    (void) request;
    (void) response;
    return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
}


}  // namespace carla

这是一个使用 gRPC(Google Remote Procedure Call)框架生成的 C++ 代码文件,用于与名为 CarlaAdapter 的 gRPC 服务进行通信。以下是代码的主要部分的简要解释:

包含的头文件:

#include “carla.pb.h”: 包含 Protocol Buffers 自动生成的 Carla 数据类型的头文件。
#include “carla.grpc.pb.h”: 包含 Protocol Buffers 自动生成的 Carla gRPC 服务的头文件。
CarlaAdapter 类:

CarlaAdapter::Stub: 该类用于在 gRPC 客户端上调用远程过程调用(RPC)。
构造函数中创建了多个与 gRPC 方法相对应的对象,如 rpcmethod_ExecuteOneTimeStep_,用于处理具体的 gRPC 调用。
异步调用:

CarlaAdapter::Stub::experimental_async::ExecuteOneTimeStep: 异步版本的 ExecuteOneTimeStep 方法,允许提供回调函数,以便在调用完成时异步处理结果。
RPC 服务实现:

CarlaAdapter::Service: 该类实现了 gRPC 服务的各个方法,如 ExecuteOneTimeStep、Finish、GetManagedActorsIds 等。
每个方法对应一个 gRPC 方法,并在其中执行相应的操作。
这些代码片段是一个 gRPC 服务端和客户端的实现,用于与名为 CarlaAdapter 的服务进行通信。服务定义了一组方法,而客户端则使用 Stub 对象调用这些方法。异步调用提供了非阻塞的方式执行 gRPC 调用,允许在调用完成时执行回调。

  • src/veins_carla/package.ned

  • src/veins_carla/veins_carla.h

#pragma once

#include "veins/veins.h"

// Version number of last release ("major.minor.patch") or an alpha version, if nonzero
#define VEINS_CARLA_VERSION_MAJOR 1
#define VEINS_CARLA_VERSION_MINOR 0
#define VEINS_CARLA_VERSION_PATCH 0
#define VEINS_CARLA_VERSION_ALPHA 0

// Explicitly check Veins version number
#if !(VEINS_VERSION_MAJOR == 5 && VEINS_VERSION_MINOR >= 1)
#error Veins version 5.1 or compatible required
#endif


// VEINS_CARLA_API macro. Allows us to use the same .h files for both building a .dll and linking against it
#if defined(VEINS_CARLA_EXPORT)
#define VEINS_CARLA_API OPP_DLLEXPORT
#elif defined(VEINS_CARLA_IMPORT)
#define VEINS_CARLA_API OPP_DLLIMPORT
#else
#define VEINS_CARLA_API
#endif

这是一个 C++ 头文件,其中定义了与 Veins Carla 模块相关的一些宏和版本信息。以下是代码的主要解释:

版本信息:

VEINS_CARLA_VERSION_MAJOR, VEINS_CARLA_VERSION_MINOR, VEINS_CARLA_VERSION_PATCH, VEINS_CARLA_VERSION_ALPHA: 定义了 Veins Carla 模块的版本号,包括主版本、次版本、修订版本和 alpha 版本。
Veins 版本检查:

#if !(VEINS_VERSION_MAJOR == 5 && VEINS_VERSION_MINOR >= 1): 检查 Veins 版本是否符合要求。如果 Veins 的主版本号不是 5,或者次版本号小于 1,则产生编译错误。
VEINS_CARLA_API 宏:

VEINS_CARLA_API OPP_DLLEXPORT: 如果定义了 VEINS_CARLA_EXPORT,则表示正在构建 Veins Carla 模块的 DLL,使用 OPP_DLLEXPORT 宏进行导出。
VEINS_CARLA_API OPP_DLLIMPORT: 如果定义了 VEINS_CARLA_IMPORT,则表示正在链接到 Veins Carla 模块的 DLL,使用 OPP_DLLIMPORT 宏进行导入。
如果既没有定义 VEINS_CARLA_EXPORT 也没有定义 VEINS_CARLA_IMPORT,则不进行特殊的导出或导入处理,直接定义为 VEINS_CARLA_API。
这个头文件的主要目的是在编译时提供一些关于 Veins Carla 模块版本和导出/导入的宏定义,以便在编写其他代码时能够根据这些信息进行条件编译和链接。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值