Skip to content

Commit

Permalink
eCAL v5.5.3:
Browse files Browse the repository at this point in the history
* core
  * shared memory layer can be configured to use iceoryx implementation alternative to eCAL one's
    * use CMake option 'ECAL_LAYER_ICEORYX = ON'
    * all eCAL eco system tools (record, replay, monitoring, language bindings) tested with iceoryx
    * core automatically switches between iceoryx and udp multicast for local and network subscriptions
  * message frequency min/max observation feature removed (should be implemnented outside eCAL core if needed)
* message protocols
  * compatibility to capnproto 0.7.0 fixed
* common:
  * lot's of warnings fixed
  * Readme.md documentation improved (transport layer configuration)

Co-authored-by: Rex Schilasky <[email protected]>
  • Loading branch information
Kerstin-Keller and rex-schilasky committed Feb 13, 2020
1 parent 18072f7 commit ceeef2a
Show file tree
Hide file tree
Showing 79 changed files with 1,012 additions and 1,284 deletions.
12 changes: 11 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ option(BUILD_TIME "Build the eCAL time interfaces"
option(BUILD_PY_BINDING "Build eCAL python binding" OFF)
option(BUILD_TESTS "Build the eCAL google tests" OFF)

option(ECAL_LAYER_ICEORYX "Provide iceoryx as communication layer" OFF)
option(ECAL_LAYER_ICEORYX "Use iceoryx shared memory as local communication layer" OFF)

option(ECAL_INCLUDE_PY_SAMPLES "Include python language sample projects into CMake" OFF)
option(ECAL_INSTALL_SAMPLE_SOURCES "Install the sources of eCAL samples" ON)
Expand Down Expand Up @@ -77,6 +77,13 @@ file(TO_CMAKE_PATH "${CMAKE_PREFIX_PATH}" CMAKE_PREFIX_PATH)
message(STATUS "Module Path: ${CMAKE_MODULE_PATH}")
message(STATUS "Prefix Path: ${CMAKE_PREFIX_PATH}")

# --------------------------------------------------------
# check options
# --------------------------------------------------------
if(WIN32 AND ECAL_LAYER_ICEORYX)
message(FATAL_ERROR "Iceoryx transport layer not available for windows os. \
Please disable the layer by setting ECAL_LAYER_ICEORYX to OFF.")
endif()

# --------------------------------------------------------
# third party dependencies as requested
Expand Down Expand Up @@ -113,6 +120,7 @@ endif()

if (ECAL_THIRDPARTY_BUILD_SPDLOG)
list(APPEND as_subproject spdlog)
set(SPDLOG_BUILD_TESTING OFF CACHE BOOL "My option" FORCE)
add_subdirectory(thirdparty/spdlog)
add_library(spdlog::spdlog ALIAS spdlog)
endif ()
Expand Down Expand Up @@ -431,7 +439,9 @@ if(BUILD_TESTS)
add_subdirectory(testing/ecal/core_test/src)
add_subdirectory(testing/ecal/event_test/src)
add_subdirectory(testing/ecal/expmap_test/src)
if(NOT ECAL_LAYER_ICEORYX)
add_subdirectory(testing/ecal/io_memfile_test/src)
endif(NOT ECAL_LAYER_ICEORYX)
add_subdirectory(testing/ecal/pubsub_inproc_test/src)
add_subdirectory(testing/ecal/pubsub_proto_test/src)
add_subdirectory(testing/ecal/pubsub_test/src)
Expand Down
10 changes: 10 additions & 0 deletions NOTICE.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,16 @@ This project has dependencies - list with dependency name and license follows.
2.3.3 convert_utf.cpp/.h
- Copyright 2001-2004 Unicode, Inc.

2.3.4 Spdlog
- Copyright (c) 2016 Gabi Melman
- URL: https://github.com/gabime/spdlog
- License: MIT License - https://github.com/gabime/spdlog/blob/v1.x/LICENSE

2.3.5 Termocolor
- Copyright (c) 2013, Ihor Kalnytskyi
- URL: https://github.com/ikalnytskyi/termcolor
- License: BSD License - https://github.com/ikalnytskyi/termcolor/blob/master/LICENSE


2.4 GUI

Expand Down
32 changes: 20 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@


# eCAL - enhanced Communication Abstraction Layer

Copyright (c) 2019, Continental Corporation.
Expand Down Expand Up @@ -56,7 +57,6 @@ eCAL is using CMake as build system. When configuring with CMake, you can turn o
- `HAS_CAPNPROTO`, default: `OFF`
Platform supports Cap'n Proto library, necessary to use capnp serialization as message system and to enable eCAL monitoring capnp message reflection
eCAL does not add Cap'n Proto as a submodule. If you set this option to `ON`, please make sure that the library is installed on your system and CMake can find it (consider setting CMAKE_PREFIX_PATH to point to the library).
Currently Version 0.6.1 is supported and has been tested, to use 0.7.0 some adaptations in CMakeLists.txt files needs to be made to make the samples compile.
- `BUILD_DOCS`, default `ON`
Build the eCAL documentation, requires the installation of doxygen and a recent CMake version (>= 3.14 preferred, but some lower versions might work)
- `BUILD_APPS`, default `ON`,
Expand All @@ -70,7 +70,7 @@ eCAL is using CMake as build system. When configuring with CMake, you can turn o
- `BUILD_TESTS', default `OFF`
Build the eCAL google tests
- `ECAL_LAYER_ICEORYX`, default `OFF`
Provide iceoryx as communication layer, requires [eclipse/iceoryx](https://github.com/eclipse/iceoryx) installation
Use iceoryx shared memory as local communication layer, requires [eclipse/iceoryx](https://github.com/eclipse/iceoryx) installation
- `ECAL_INCLUDE_PY_SAMPLES`, default: `OFF`
Include python language sample projects into CMake
- `ECAL_INSTALL_SAMPLE_SOURCES`, default: `ON`
Expand Down Expand Up @@ -294,20 +294,29 @@ There are different ways to configure these layers. They can be set up for a who
|-----------------|--------------------------|--------------------|-------------------------------------------------------------------------------------------|
| inproc | [publisher/use_inproc] | inner process | inner process, zeroy copy communication (pointer forwarding) |
| shm | [publisher/use_shm] | shared memory | interprocess, shared memory communication, supports N:M connections, 2 memory copies |
| iceoryx | [publisher/use_iceoryx] | shared memory | interprocess, shared memory communication, supports 1:1 connections, 1 memory copy |
| udp_mc | [publisher/use_udp_mc] | udp multicast | interhost, topic name based dynamic multicast grouping to optimize pub/sub socket payload |

Every layer can set up in 3 different activation modes. Every mode can be configured as default in the ecal.ini file and can be overwritten by the C++/Python publisher API. This is the activation logic

• off: layer will not be used for any communication

• on: layer will be used independently if there is any local or host outside subscription
• off: layer is swicthed off

auto: layer will be used on demand (shm = 2 and udp_mc = 2 means shm layer will be used if there is any local subscription, udp_multicast will be used if there is a subscription outside the current host)
on: layer is always switched on (i.e. payload will be send no matter if there is any local or network subscription)

The "auto" mode is currently working for inproc, shm and udp_mc only (planned for iceoryx with the next release). In this mode a publisher send call will return without wasting any CPU time if there is no innerprocess, local host or network subscription.
• auto: layer will be switched on autmatically

- inproc = 2 : layer used automatically for inner process subscribers

- shm = 2 : layer used automatically for inter process subscribers

- udp_mc = 2 : layer used autmatically for inter host (network) subcribers

Independent from this publisher setting you can switch on/off the receiving (subscription) logic for every layer. That means you can prevent incoming payload on specific layers. This can be done in the ecal.ini file [network] section.

Independent from this publisher setting you can switch on/off the receiving logic for every layer. This can be done in the ecal.ini file [network] section. By default inproc (inproc_rec_enabled), shm (shm_rec_enabled) and udp_mc (udp_mc_rec_enabled) is switched on. If you want to experiment with iceoryx please set iceoryx_rec_enabled to true. For example switching off the udp multicast layer for a machine or a single process can avoid that the process will process incoming socket traffic even it is not interested in publications outside it's host.
• inproc_rec_enabled = true / false : enable / disable inner process subscriptions

• shm_rec_enabled = true / false : enable / disable inter process subscriptions

• udp_mc_rec_enabled = true / false : enable / disable inter host subscriptions

## Applications

Expand Down Expand Up @@ -349,7 +358,7 @@ The following image shows a running replay, publishing 2 messages in realtime.

## Performance

The following table shows the latency in µs between a single publisher / subscriber connection for different payload sizes (two different processes running on the same host). You can simply measure the latency on your own machine by running the ecal_latency_snd and ecal_latency_rec_cb sample applications. The first two columns are showing the performance for the eCAL builtin shared memory layer and the last column for the iceoryx shared memory layer (configured by adating the ecal configuration file only).
The following table shows the latency in µs between a single publisher / subscriber connection for different payload sizes (two different processes running on the same host). You can simply measure the latency on your own machine by running the ecal_latency_snd and ecal_latency_rec_cb sample applications. The first two columns are showing the performance for the eCAL builtin shared memory layer and the last column for the iceoryx shared memory layer (configured by cmake option ECAL_LAYER_ICEORYX).

First start ecal_sample_latency_rec_cb. This application will receive the published payloads, send them back to the sender and print out the average receive time, the message frequency and the data throughput over all received messages. The sending application ecal_latency_snd can be configured that way ..

Expand Down Expand Up @@ -642,8 +651,7 @@ The currently supported layers are
enum eTransportLayer
{
tlayer_udp_mc = 1, // udp multicast (eCAL - using multiple multicast groups for high efficient data transport)
tlayer_shm = 4, // shared memory (eCAL)
tlayer_iceoryx = 7, // iceoryx (Bosch zero copy shared memory layer)
tlayer_shm = 4, // shared memory (eCAL or Iceoryx)
tlayer_inproc = 42, // inner process (eCAL - deterministic inner process communication)
};
```
Expand Down
3 changes: 2 additions & 1 deletion app/mon/eCALMon/src/Ecalmon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include <QDesktopWidget>
#include <QDesktopServices>
#include <QDateTime>
#include <QScreen>

#include <QDebug>

Expand Down Expand Up @@ -523,7 +524,7 @@ void Ecalmon::resetLayout()

setParseTimeEnabled(initial_parse_time_);

move(QApplication::desktop()->availableGeometry(screen_number).center() - rect().center());
move(QGuiApplication::screens().at(screen_number)->availableGeometry().center() - rect().center());

log_widget_ ->resetLayout();
topic_widget_ ->resetLayout();
Expand Down
2 changes: 1 addition & 1 deletion app/mon/eCALMon/src/Plugin/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ QList<QPair<PluginWrapper::PluginData, eCAL::mon::PluginWidgetInterface*>> Plugi
}

// Sort return vector by priority
qSort(supported_plugins.begin(), supported_plugins.end(), [](const auto& lhs, const auto& rhs)
std::sort(supported_plugins.begin(), supported_plugins.end(), [](const auto& lhs, const auto& rhs)
{
return lhs.first.meta_data.priority < rhs.first.meta_data.priority;
});
Expand Down
9 changes: 0 additions & 9 deletions app/mon/eCALMon/src/Widgets/EcalmonTreeWidget/TopicWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,6 @@ void TopicWidget::autoSizeColumns()
example_topic_pb.set_message_drops(999999);
example_topic_pb.set_dclock(99999999999);
example_topic_pb.set_dfreq(999999);
example_topic_pb.set_dfreq_min(999999);
example_topic_pb.set_dfreq_max(999999);
example_topic_pb.set_dfreq_min_err(999999);
example_topic_pb.set_dfreq_max_err(999999);


TopicTreeItem* example_topic_item = new TopicTreeItem(example_topic_pb);
GroupTreeItem* example_group_item = new GroupTreeItem("CameraSensorMapFusionCAF___", "", "", QVariant::Invalid, "");
Expand Down Expand Up @@ -278,10 +273,6 @@ void TopicWidget::autoSizeColumns()
(int)TopicTreeModel::Columns::MESSAGE_DROPS,
(int)TopicTreeModel::Columns::DATA_CLOCK,
(int)TopicTreeModel::Columns::DATA_FREQUENCY,
(int)TopicTreeModel::Columns::DATA_FREQUENCY_MIN,
(int)TopicTreeModel::Columns::DATA_FREQUENCY_MAX,
(int)TopicTreeModel::Columns::DATA_FREQUENCY_MIN_ERR,
(int)TopicTreeModel::Columns::DATA_FREQUENCY_MAX_ERR,
};

for (int column : columns_to_resize)
Expand Down
29 changes: 1 addition & 28 deletions app/mon/eCALMon/src/Widgets/Models/TopicTreeItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,22 +170,6 @@ QVariant TopicTreeItem::data(Columns column, Qt::ItemDataRole role) const
{
return topic_.dfreq();
}
else if (column == Columns::DFREQ_MIN)
{
return topic_.dfreq_min();
}
else if (column == Columns::DFREQ_MAX)
{
return topic_.dfreq_max();
}
else if (column == Columns::DFREQ_MIN_ERR)
{
return topic_.dfreq_min_err();
}
else if (column == Columns::DFREQ_MAX_ERR)
{
return topic_.dfreq_max_err();
}
else
{
return QVariant();
Expand Down Expand Up @@ -221,9 +205,6 @@ QVariant TopicTreeItem::data(Columns column, Qt::ItemDataRole role) const
case eCAL::pb::eTLayerType::tl_ecal_shm:
this_layer_string = "shm";
break;
case eCAL::pb::eTLayerType::tl_iceoryx:
this_layer_string = "iceoryx";
break;
case eCAL::pb::eTLayerType::tl_inproc:
this_layer_string = "inproc";
break;
Expand All @@ -245,11 +226,7 @@ QVariant TopicTreeItem::data(Columns column, Qt::ItemDataRole role) const
return layer_string;
}

else if ((column == Columns::DFREQ)
|| (column == Columns::DFREQ_MIN)
|| (column == Columns::DFREQ_MAX)
|| (column == Columns::DFREQ_MIN_ERR)
|| (column == Columns::DFREQ_MAX_ERR))
else if (column == Columns::DFREQ)
{
long long raw_data = data(column, (Qt::ItemDataRole)ItemDataRoles::RawDataRole).toLongLong(); //-V1016
return toFrequencyString(raw_data);
Expand Down Expand Up @@ -294,10 +271,6 @@ QVariant TopicTreeItem::data(Columns column, Qt::ItemDataRole role) const
|| (column == Columns::MESSAGE_DROPS)
|| (column == Columns::DCLOCK)
|| (column == Columns::DFREQ)
|| (column == Columns::DFREQ_MIN)
|| (column == Columns::DFREQ_MAX)
|| (column == Columns::DFREQ_MIN_ERR)
|| (column == Columns::DFREQ_MAX_ERR)
)
{
return Qt::AlignmentFlag::AlignRight;
Expand Down
4 changes: 0 additions & 4 deletions app/mon/eCALMon/src/Widgets/Models/TopicTreeItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,6 @@ class TopicTreeItem :
MESSAGE_DROPS,
DCLOCK,
DFREQ,
DFREQ_MIN,
DFREQ_MAX,
DFREQ_MIN_ERR,
DFREQ_MAX_ERR
};

TopicTreeItem();
Expand Down
12 changes: 0 additions & 12 deletions app/mon/eCALMon/src/Widgets/Models/TopicTreeModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ class TopicTreeModel : public GroupTreeModel
MESSAGE_DROPS,
DATA_CLOCK,
DATA_FREQUENCY,
DATA_FREQUENCY_MIN,
DATA_FREQUENCY_MAX,
DATA_FREQUENCY_MIN_ERR,
DATA_FREQUENCY_MAX_ERR,

COLUMN_COUNT
};
Expand Down Expand Up @@ -109,10 +105,6 @@ class TopicTreeModel : public GroupTreeModel
{ Columns::MESSAGE_DROPS, "Drops" },
{ Columns::DATA_CLOCK, "Data Clock" },
{ Columns::DATA_FREQUENCY, "Frequency [Hz]" },
{ Columns::DATA_FREQUENCY_MIN, "Min Ref. Freq. [Hz]" },
{ Columns::DATA_FREQUENCY_MAX, "Max Ref. Freq. [Hz]" },
{ Columns::DATA_FREQUENCY_MIN_ERR, "Min Ref. Freq. Error [Hz]" },
{ Columns::DATA_FREQUENCY_MAX_ERR, "Max Ref. Freq. Error [Hz]" },
};

std::map<Columns, int> topic_tree_item_column_mapping =
Expand All @@ -136,10 +128,6 @@ class TopicTreeModel : public GroupTreeModel
{ Columns::MESSAGE_DROPS, (int)TopicTreeItem::Columns::MESSAGE_DROPS },
{ Columns::DATA_CLOCK, (int)TopicTreeItem::Columns::DCLOCK },
{ Columns::DATA_FREQUENCY, (int)TopicTreeItem::Columns::DFREQ },
{ Columns::DATA_FREQUENCY_MIN, (int)TopicTreeItem::Columns::DFREQ_MIN },
{ Columns::DATA_FREQUENCY_MAX, (int)TopicTreeItem::Columns::DFREQ_MAX },
{ Columns::DATA_FREQUENCY_MIN_ERR, (int)TopicTreeItem::Columns::DFREQ_MIN_ERR },
{ Columns::DATA_FREQUENCY_MAX_ERR, (int)TopicTreeItem::Columns::DFREQ_MAX_ERR },
};

std::map<std::string, TopicTreeItem*> topic_tree_item_map_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <QSettings>
#include <QDesktopWidget>
#include <QKeyEvent>
#include <QScreen>


VisualisationWindow::VisualisationWindow(const QString& topic_name, const QString& topic_type, QWidget *parent)
Expand Down Expand Up @@ -50,7 +51,7 @@ void VisualisationWindow::resetLayout(int target_screen)
{
showNormal();
resize(450, 500);
move(QApplication::desktop()->availableGeometry(target_screen).center() - rect().center());
move(QGuiApplication::screens().at(target_screen)->availableGeometry().center() - rect().center());

visualisation_widget->resetLayout();
}
Expand Down
3 changes: 2 additions & 1 deletion app/play/eCALPlayGUI/src/EcalPlayGui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <QDesktopWidget>
#include <QDesktopServices>
#include <QMimeData>
#include <QScreen>

#ifdef WIN32
#include <QWinTaskbarButton>
Expand Down Expand Up @@ -626,7 +627,7 @@ void EcalplayGui::resetLayout()
int screen_number = QApplication::desktop()->screenNumber(this);
restoreGeometry(initial_geometry_);
restoreState(initial_state_);
move(QApplication::desktop()->availableGeometry(screen_number).center() - rect().center());
move(QGuiApplication::screens().at(screen_number)->availableGeometry().center() - rect().center());
}

////////////////////////////////////////////////////////////////////////////////
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,15 @@ HostPicker::HostPicker(const QStringList& available_hosts, const QStringList& in
host_list_model_ = new QStandardItemModel(this);

// Merge available hosts and initial selections
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
QSet<QString> host_set = QSet<QString>::fromList(available_hosts + initial_selection);
QStringList host_stringlist = host_set.toList();
host_stringlist.sort(Qt::CaseSensitivity::CaseInsensitive);
#else
QStringList host_list = available_hosts + initial_selection;
QSet<QString> host_set = QSet<QString>(host_list.begin(), host_list.end());
QStringList host_stringlist = host_set.values();
#endif

// Add available hosts
for (const auto& host : host_stringlist)
Expand Down
Loading

0 comments on commit ceeef2a

Please sign in to comment.