Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ include(AddOppTarget)
include(CheckGitSubmodule)
include(GenerateOppMessage)
include(GNUInstallDirs)
include(CMakeDependentOption)

find_package(Boost 1.59 COMPONENTS date_time system REQUIRED)
if (Boost_VERSION_STRING VERSION_GREATER_EQUAL "1.75")
Expand Down Expand Up @@ -93,6 +94,7 @@ option(WITH_ENVMOD "Build Artery with environment model feature" ON)
option(WITH_STORYBOARD "Build Artery with storyboard feature" ON)
option(WITH_TRANSFUSION "Build Artery with transfusion feature" OFF)
option(WITH_TESTBED "Build Artery with testbed feature" OFF)
cmake_dependent_option(WITH_CPSERVICE "Build Artery with Collective Perception Service" ON "WITH_ENVMOD" OFF)

option(WITH_OTS "Build Artery with support for OpenTrafficSim" OFF)
if(WITH_OTS)
Expand Down
4 changes: 4 additions & 0 deletions src/artery/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ if(WITH_TESTBED)
add_subdirectory(testbed)
endif()

if(WITH_CPSERVICE)
add_subdirectory(application/cp)
endif()

install(TARGETS core LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
set_property(TARGET core APPEND PROPERTY INSTALL_NED_FOLDERS ${CMAKE_INSTALL_DATADIR}/ned/artery)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION share/ned/artery FILES_MATCHING PATTERN "*.ned")
Expand Down
25 changes: 25 additions & 0 deletions src/artery/application/CpService.ned
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//
// Artery V2X Simulation Framework
// Licensed under GPLv2, see COPYING file for detailed license and warranty terms.
//

package artery.application;

import artery.application.cp.*;


// CpService ITS-G5 Service Module
module CpService like ItsG5Service
{
parameters:
// Number of Redundancy Mitigation Rules to use
int numRedundancyMitigationRules = default(0);

submodules:
// Core implementation
core: Core;
// CPM Generation Rule
generation: <default("StaticGeneration")> like GenerationRule;
// Redundancy Mitigation Rules
redundancyMitigation[numRedundancyMitigationRules]: <> like RedundancyMitigationRule;
}
27 changes: 27 additions & 0 deletions src/artery/application/cp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
####################################
# Library of the CP Message Object #
####################################

add_artery_feature(cpm)

target_sources(cpm PRIVATE
CpObject.cc
)


###################################
# Actual CpService implementation #
###################################

add_artery_feature(cpservice)

target_sources(cpservice PRIVATE
CpService.cc
GenerationRule.cc
RedundancyMitigationRule.cc
Tracking.cc
Utility.cc
)

target_link_libraries(cpservice PUBLIC cpm)
target_link_libraries(cpservice PUBLIC envmod)
143 changes: 143 additions & 0 deletions src/artery/application/cp/Core.ned
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
//
// Artery V2X Simulation Framework
// Licensed under GPLv2, see COPYING file for detailed license and warranty terms.
//

package artery.application.cp;


// CpService core implementation
simple Core
{
parameters:
@class(CpService);

@signal[CpmReceived](type=CpObject);
@signal[CpmSent](type=CpObject);


@signal[CpmSent_positionX](type=double);
@statistic[CpmSent_positionX](title="CPM: X-Position while sending CPM segment"; source="CpmSent_positionX"; record=vector; interpolationmode=none);

@signal[CpmSent_positionY](type=double);
@statistic[CpmSent_positionY](title="CPM: Y-Position while sending CPM segment"; source="CpmSent_positionY"; record=vector; interpolationmode=none);

@signal[CpmSent_sender](type=unsigned long);
@statistic[CpmSent_sender](title="CPM: Sender of sent CPM"; source="CpmSent_sender"; record=vector?; interpolationmode=none);

@signal[CpmSent_generatedPocCount](type=unsigned long);
@statistic[CpmSent_generatedPocCount](title="CPM: Number of perceived objects selected for CPM inclusion by generation rule"; source="CpmSent_generatedPocCount"; record=vector; interpolationmode=none);

@signal[CpmSent_mitigatedPocCount](type=unsigned long);
@statistic[CpmSent_mitigatedPocCount](title="CPM: Number of perceived objects selected for CPM inclusion after redundancy mitigation"; source="CpmSent_mitigatedPocCount"; record=vector; interpolationmode=none);

@signal[CpmSent_channelBusyRatio](type=double);
@statistic[CpmSent_channelBusyRatio](title="CPM: Channel Busy Ratio at the sender"; source="CpmSent_channelBusyRatio"; record=vector; interpolationmode=none);

@signal[CpmSent_segmentCount](type=unsigned long);
@statistic[CpmSent_segmentCount](title="CPM: Number of generated CPM segments"; source="CpmSent_segmentCount"; record=vector; interpolationmode=none);

@signal[CpmSent_pocIncluded](type=bool);
@statistic[CpmSent_pocIncluded](title="CPM: Perceived Objects Container included flag"; source="CpmSent_pocIncluded"; record=vector?; interpolationmode=none);

@signal[CpmSent_poCountSegment](type=unsigned long);
@statistic[CpmSent_poCountSegment](title="CPM: Number of POs included in sent CPM segment"; source="CpmSent_poCountSegment"; record=vector; interpolationmode=none);

@signal[CpmSent_sicIncludedInSegmentNr](type=unsigned long);
@statistic[CpmSent_sicIncludedInSegmentNr](title="CPM: Sensor Information Container included flag"; source="CpmSent_sicIncludedInSegmentNr"; record=vector?; interpolationmode=none);

@signal[CpmSent_msgSize](type=unsigned long);
@statistic[CpmSent_msgSize](title="CPM: Size of sent segment"; source="CpmSent_msgSize"; record=vector; interpolationmode=none);


@signal[CpService_10Hz_numSeenByRadar](type=unsigned long);
@statistic[CpService_10Hz_numSeenByRadar](title="CPM: Number of radar objects currently in the LEM during"; source="CpService_10Hz_numSeenByRadar"; record=vector; interpolationmode=none);

@signal[CpService_10Hz_numSeenByCam](type=unsigned long);
@statistic[CpService_10Hz_numSeenByCam](title="CPM: Number of CAM objects currently in the LEM during"; source="CpService_10Hz_numSeenByCam"; record=vector; interpolationmode=none);

@signal[CpService_10Hz_numSeenByCpm](type=unsigned long);
@statistic[CpService_10Hz_numSeenByCpm](title="CPM: Number of CPM objects currently known"; source="CpService_10Hz_numSeenByCpm"; record=vector; interpolationmode=none);

@signal[CpService_10Hz_numSeenByAll](type=unsigned long);
@statistic[CpService_10Hz_numSeenByAll](title="CPM: Number of unique objects that are simultaneously seen by radar, CAM and CPM"; source="CpService_10Hz_numSeenByAll"; record=vector; interpolationmode=none);


@signal[CpmRecv_positionX](type=double);
@statistic[CpmRecv_positionX](title="CPM: X-Position while receiving CPM segment"; source="CpmRecv_positionX"; record=vector; interpolationmode=none);

@signal[CpmRecv_positionY](type=double);
@statistic[CpmRecv_positionY](title="CPM: Y-Position while receiving CPM segment"; source="CpmRecv_positionY"; record=vector; interpolationmode=none);

@signal[CpmRecv_sender](type=unsigned long);
@statistic[CpmRecv_sender](title="CPM: Sender of received CPM"; source="CpmRecv_sender"; record=vector?; interpolationmode=none);

@signal[CpmRecv_delay](type=long);
@statistic[CpmRecv_delay](title="Communication delay between sending and receiving CPM, i.e., beetween request() and indicate()"; source="CpmRecv_delay"; record=vector?; interpolationmode=none);

@signal[CpmRecv_distToSender](type=double);
@statistic[CpmRecv_distToSender](title="CPM: Distance from receiver to sender of this CPM"; source="CpmRecv_distToSender"; record=vector?; interpolationmode=none);

@signal[CpmRecv_objId](type=unsigned long);
@statistic[CpmRecv_objId](title="CPM: IDs of received PO"; source="CpmRecv_objId"; record=vector?; interpolationmode=none);

@signal[CpmRecv_age](type=long);
@statistic[CpmRecv_age](title="CPM: Overall age of received PO"; source="CpmRecv_age"; record=vector; interpolationmode=none);

@signal[CpmRecv_distance](type=double);
@statistic[CpmRecv_distance](title="CPM: Distance to received PO"; source="CpmRecv_distance"; record=vector; interpolationmode=none);

@signal[CpmRecv_poCountSegment](type=unsigned long);
@statistic[CpmRecv_poCountSegment](title="CPM: Number of POs included in received CPM segment"; source="CpmRecv_poCountSegment"; record=vector; interpolationmode=none);

@signal[CpmRecv_poTimeSinceLastUpdate](type=long);
@statistic[CpmRecv_poTimeSinceLastUpdate](title="CPM: Time passed since information about this PO was received last"; source="CpmRecv_poTimeSinceLastUpdate"; record=vector; interpolationmode=none);

@signal[CpmRecv_poDistanceSinceLastUpdate](type=double);
@statistic[CpmRecv_poDistanceSinceLastUpdate](title="CPM: Distance the PO traveled between is was included in this and the last CPM"; source="CpmRecv_poDistanceSinceLastUpdate"; record=vector; interpolationmode=none);

@signal[CpmRecv_poRedundancy](type=unsigned long);
@statistic[CpmRecv_poRedundancy](title="CPM: Number of CPMs received in the validity period including information about this object"; source="CpmRecv_poRedundancy"; record=vector; interpolationmode=none);

@signal[CpmRecv_senderRedundancy](type=unsigned long);
@statistic[CpmRecv_senderRedundancy](title="CPM: Number of senders in the validity period that sent information about this object"; source="CpmRecv_senderRedundancy"; record=vector; interpolationmode=none);

@signal[CpmRecv_senderHistoryOverflow](type=unsigned long);
@statistic[CpmRecv_senderHistoryOverflow](title="CPM: ID of sender that caused a history buffer sourced by sender overflow in the validity period"; source="CpmRecv_senderHistoryOverflow"; record=vector?; interpolationmode=none);

@signal[CpmRecv_objectHistoryOverflow](type=unsigned long);
@statistic[CpmRecv_objectHistoryOverflow](title="CPM: ID of sender that caused a history buffer sourced by object overflow in the validity period"; source="CpmRecv_objectHistoryOverflow"; record=vector?; interpolationmode=none);

@signal[CpmRecv_senderDupeDrop](type=unsigned long);
@statistic[CpmRecv_senderDupeDrop](title="CPM: ID of sender that sent a duplicate CPM that got dropped"; source="CpmRecv_senderDupeDrop"; record=vector?; interpolationmode=none);

@signal[CpmRecv_objectDupeDrop](type=unsigned long);
@statistic[CpmRecv_objectDupeDrop](title="CPM: ID of object that is part of a sent duplicate CPM that got dropped"; source="CpmRecv_objectDupeDrop"; record=vector?; interpolationmode=none);

@signal[CpmRecv_senderDupeReplace](type=unsigned long);
@statistic[CpmRecv_senderDupeReplace](title="CPM: ID of sender that sent a duplicate CPM that replaced the previous CPM"; source="CpmRecv_senderDupeReplace"; record=vector?; interpolationmode=none);

@signal[CpmRecv_objectDupeReplace](type=unsigned long);
@statistic[CpmRecv_objectDupeReplace](title="CPM: ID of object that is part of a sent duplicate CPM that replaced the previous CPM"; source="CpmRecv_objectDupeReplace"; record=vector?; interpolationmode=none);


// Minimum interval for CPM generation
int genCpmMin @unit(ms) = default(100ms);
// Maximum interval for CPM generation
int genCpmMax @unit(ms) = default(1000ms);
// Interval for SensorInformationContainer inclusion
int addSensorInformation @unit(ms) = default(1000ms);

// Maximum CPM size
int mtuCpm @unit(byte) = default(1394byte);
// DCC Profile to use
// The numbers 0 - 3 map to DP0 - DP3
int dccProfile @enum(0, 1, 2, 3) = default(2);
// Apply DCC transmission interval restrictions
bool withDccRestriction = default(false);

// If true enable redundancy mitigation dynamically, otherwise ignore redundancy parameters and enable always
bool dynamicRedundancyMitigation = default(false);
// Network channel load (Channel Busy Ratio) that needs to get exceeded to use redundancy mitigation
double redundancyLoad = default(0.25);
}
70 changes: 70 additions & 0 deletions src/artery/application/cp/CpObject.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*
* Artery V2X Simulation Framework
* Licensed under GPLv2, see COPYING file for detailed license and warranty terms.
*/

#include "artery/application/cp/CpObject.h"

#include <omnetpp.h>

#include <cassert>


namespace artery
{

Register_Abstract_Class(CpObject);

CpObject::CpObject(vanetza::asn1::Cpm&& cpm) : m_wrapper(std::make_shared<vanetza::asn1::Cpm>(std::move(cpm)))
{
}

CpObject& CpObject::operator=(vanetza::asn1::Cpm&& cpm)
{
m_wrapper = std::make_shared<vanetza::asn1::Cpm>(std::move(cpm));
return *this;
}


CpObject::CpObject(const vanetza::asn1::Cpm& cpm) : m_wrapper(std::make_shared<vanetza::asn1::Cpm>(cpm))
{
}

CpObject& CpObject::operator=(const vanetza::asn1::Cpm& cpm)
{
m_wrapper = std::make_shared<vanetza::asn1::Cpm>(cpm);
return *this;
}


CpObject::CpObject(std::shared_ptr<const vanetza::asn1::Cpm> ptr) : m_wrapper(ptr)
{
assert(m_wrapper);
}

CpObject& CpObject::operator=(std::shared_ptr<const vanetza::asn1::Cpm> ptr)
{
m_wrapper = ptr;
assert(m_wrapper);
return *this;
}


const vanetza::asn1::Cpm& CpObject::asn1() const
{
return *m_wrapper;
}


std::shared_ptr<const vanetza::asn1::Cpm> CpObject::shared_ptr()
{
return m_wrapper;
}


omnetpp::cObject* CpObject::dup() const
{
return new CpObject{*this};
}

} // namespace artery
68 changes: 68 additions & 0 deletions src/artery/application/cp/CpObject.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/*
* Artery V2X Simulation Framework
* Licensed under GPLv2, see COPYING file for detailed license and warranty terms.
*/

#ifndef ARTERY_CPOBJECT_H_
#define ARTERY_CPOBJECT_H_

/**
* @file CpObject.h
* @brief Collective Perception Message wrapper object
*/

#include <omnetpp/cobject.h>
#include <vanetza/asn1/cpm.hpp>

#include <memory>


namespace artery
{

/**
* @brief Collective Perception Message wrapper object
*
* Stores and owns a CPM so that it can be passed to other modules using OMNeT++ infrastructure.
*/
class CpObject : public omnetpp::cObject
{
public:
CpObject(const CpObject&) = default;
CpObject& operator=(const CpObject&) = default;

CpObject(vanetza::asn1::Cpm&&);
CpObject& operator=(vanetza::asn1::Cpm&&);

CpObject(const vanetza::asn1::Cpm&);
CpObject& operator=(const vanetza::asn1::Cpm&);

CpObject(std::shared_ptr<const vanetza::asn1::Cpm>);
CpObject& operator=(std::shared_ptr<const vanetza::asn1::Cpm>);

/**
* @brief Returns a reference of the stored CPM
*
* @return Reference of the stored CPM
*/
const vanetza::asn1::Cpm& asn1() const;

/**
* @brief Returns a shared_ptr of the stored CPM
*
* @return shared_ptr of the stored CPM
*/
std::shared_ptr<const vanetza::asn1::Cpm> shared_ptr();

omnetpp::cObject* dup() const override;

private:
/**
* @brief The stored CPM
*/
std::shared_ptr<const vanetza::asn1::Cpm> m_wrapper;
};

} // namespace artery

#endif /* ARTERY_CPOBJECT_H_ */
Loading