-
Notifications
You must be signed in to change notification settings - Fork 127
feat(holocat): Add EtherCAT application #1284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
1ce6b92
4cc9b7b
549c582
eb53a42
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,30 @@ | ||||||||||||||||||
| # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||||||||||||||||||
| # SPDX-License-Identifier: Apache-2.0 | ||||||||||||||||||
| # | ||||||||||||||||||
| # Licensed under the Apache License, Version 2.0 (the "License"); | ||||||||||||||||||
| # you may not use this file except in compliance with the License. | ||||||||||||||||||
| # You may obtain a copy of the License at | ||||||||||||||||||
| # | ||||||||||||||||||
| # http://www.apache.org/licenses/LICENSE-2.0 | ||||||||||||||||||
| # | ||||||||||||||||||
| # Unless required by applicable law or agreed to in writing, software | ||||||||||||||||||
| # distributed under the License is distributed on an "AS IS" BASIS, | ||||||||||||||||||
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||||||||||||||
| # See the License for the specific language governing permissions and | ||||||||||||||||||
| # limitations under the License. | ||||||||||||||||||
|
|
||||||||||||||||||
| cmake_minimum_required(VERSION 3.20) | ||||||||||||||||||
|
|
||||||||||||||||||
| # Check if EC-Master SDK is available before building | ||||||||||||||||||
| list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) | ||||||||||||||||||
| find_package(EcMaster QUIET) | ||||||||||||||||||
|
|
||||||||||||||||||
| if(EcMaster_FOUND) | ||||||||||||||||||
| message(STATUS "Building HoloCat application with EC-Master SDK") | ||||||||||||||||||
| add_subdirectory(cpp) | ||||||||||||||||||
| else() | ||||||||||||||||||
| message(FATAL_ERROR "EC-Master SDK not found") | ||||||||||||||||||
|
|
||||||||||||||||||
| # Exit with failure | ||||||||||||||||||
| exit(1) | ||||||||||||||||||
| endif() | ||||||||||||||||||
|
Comment on lines
+26
to
+30
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove invalid exit() command.
Apply this diff: else()
message(FATAL_ERROR "EC-Master SDK not found")
-
- # Exit with failure
- exit(1)
endif()📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,71 @@ | ||||||||||||||||||
| # HoloCat EtherCAT Application Dockerfile | ||||||||||||||||||
|
|
||||||||||||||||||
| ARG BASE_SDK_VERSION | ||||||||||||||||||
|
||||||||||||||||||
| ARG BASE_SDK_VERSION | |
| ARG BASE_IMAGE |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing ARG BASE_IMAGE declaration causes build failure.
BASE_IMAGE is used in the FROM instruction but is not declared as an ARG. Additionally, BASE_SDK_VERSION is declared but never used in this Dockerfile. This will cause the Docker build to fail.
Apply this diff to fix the ARG declarations:
# HoloCat EtherCAT Application Dockerfile
-ARG BASE_SDK_VERSION
+ARG BASE_IMAGE
FROM ${BASE_IMAGE}
+
+ARG BASE_SDK_VERSIONIf BASE_SDK_VERSION is truly unused, consider removing it entirely.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ARG BASE_SDK_VERSION | |
| FROM ${BASE_IMAGE} | |
| # HoloCat EtherCAT Application Dockerfile | |
| ARG BASE_IMAGE | |
| FROM ${BASE_IMAGE} | |
| ARG BASE_SDK_VERSION |
🤖 Prompt for AI Agents
In applications/holocat/Dockerfile around lines 3-4, the Dockerfile uses the
build ARG BASE_IMAGE in the FROM instruction but never declares ARG BASE_IMAGE
(and declares BASE_SDK_VERSION which is unused), causing builds to fail; add an
ARG BASE_IMAGE declaration before the FROM line (and either remove ARG
BASE_SDK_VERSION if truly unused or use it where intended), ensuring ARGs are
declared in correct order so BASE_IMAGE is available to FROM.
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Dockerfile grants the holocat user passwordless sudo access to /usr/sbin/setcap, which allows that user (and any code running as it) to assign arbitrary Linux capabilities to any binary in the container. If an attacker gains code execution as holocat, they can use sudo setcap to escalate privileges and grant powerful capabilities (e.g., raw network, sys_admin) to other binaries, breaking the intended least-privilege isolation. Consider removing this sudoers entry and instead setting the minimal required capabilities at build time or via the container runtime, without allowing arbitrary setcap invocation from inside the container.
| usermod -aG sudo holocat && \ | |
| echo "holocat ALL=(ALL) NOPASSWD: /usr/sbin/setcap" >> /etc/sudoers | |
| usermod -aG sudo holocat |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,155 @@ | ||||||||||||||||||||||
| # FindEcMaster.cmake | ||||||||||||||||||||||
| # Find the acontis EC-Master SDK | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # This module defines: | ||||||||||||||||||||||
| # ECMASTER_FOUND - True if EC-Master SDK is found | ||||||||||||||||||||||
| # ECMASTER_INCLUDE_DIRS - Include directories for EC-Master | ||||||||||||||||||||||
| # ECMASTER_LIBRARIES - Libraries to link against | ||||||||||||||||||||||
| # ECMASTER_VERSION - Version of EC-Master SDK | ||||||||||||||||||||||
| # | ||||||||||||||||||||||
| # Environment variables used: | ||||||||||||||||||||||
| # ECMASTER_ROOT - Root directory of EC-Master installation | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Handle CMake policy for environment variables | ||||||||||||||||||||||
| if(POLICY CMP0144) | ||||||||||||||||||||||
| cmake_policy(SET CMP0144 NEW) | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Get ECMASTER_ROOT from environment if not set as CMake variable | ||||||||||||||||||||||
| if(NOT ECMASTER_ROOT AND DEFINED ENV{ECMASTER_ROOT}) | ||||||||||||||||||||||
| set(ECMASTER_ROOT $ENV{ECMASTER_ROOT}) | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Find include directory | ||||||||||||||||||||||
| find_path(ECMASTER_INCLUDE_DIR | ||||||||||||||||||||||
| NAMES EcMaster.h | ||||||||||||||||||||||
| PATHS | ||||||||||||||||||||||
| ${ECMASTER_ROOT}/SDK/INC | ||||||||||||||||||||||
| /opt/acontis/ecmaster/SDK/INC | ||||||||||||||||||||||
| ${CMAKE_SOURCE_DIR}/../ethercat/ecm/SDK/INC | ||||||||||||||||||||||
| /usr/local/include/ecmaster | ||||||||||||||||||||||
| DOC "EC-Master include directory" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Determine library directory based on architecture | ||||||||||||||||||||||
| if(CMAKE_SIZEOF_VOID_P EQUAL 8) | ||||||||||||||||||||||
| set(ECMASTER_ARCH "x64") | ||||||||||||||||||||||
| else() | ||||||||||||||||||||||
| set(ECMASTER_ARCH "x86") | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Find main EC-Master library | ||||||||||||||||||||||
| find_library(ECMASTER_LIBRARY | ||||||||||||||||||||||
| NAMES EcMaster libEcMaster.so | ||||||||||||||||||||||
| PATHS | ||||||||||||||||||||||
| ${ECMASTER_ROOT}/SDK/LIB/Linux/${ECMASTER_ARCH} | ||||||||||||||||||||||
| ${ECMASTER_ROOT}/Bin/Linux/${ECMASTER_ARCH} | ||||||||||||||||||||||
| /opt/acontis/ecmaster/lib | ||||||||||||||||||||||
| ${CMAKE_SOURCE_DIR}/../ethercat/ecm/Bin/Linux/${ECMASTER_ARCH} | ||||||||||||||||||||||
| /usr/local/lib | ||||||||||||||||||||||
| DOC "EC-Master library" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Get library directory for finding link layer libraries | ||||||||||||||||||||||
| if(ECMASTER_LIBRARY) | ||||||||||||||||||||||
| get_filename_component(ECMASTER_LIBRARY_DIR ${ECMASTER_LIBRARY} DIRECTORY) | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Find all available link layer libraries | ||||||||||||||||||||||
| set(ECMASTER_LINK_LIBRARIES) | ||||||||||||||||||||||
| set(ECMASTER_LINK_LAYER_NAMES | ||||||||||||||||||||||
| emllSockRaw | ||||||||||||||||||||||
| emllDpdk | ||||||||||||||||||||||
| emllIntelGbe | ||||||||||||||||||||||
| emllRTL8169 | ||||||||||||||||||||||
| emllVlan | ||||||||||||||||||||||
| emllRemote | ||||||||||||||||||||||
| emllCCAT | ||||||||||||||||||||||
| emllBcmNetXtreme | ||||||||||||||||||||||
| emllLAN743x | ||||||||||||||||||||||
| emllDW3504 | ||||||||||||||||||||||
| emllAlteraTSE | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| foreach(lib_name IN LISTS ECMASTER_LINK_LAYER_NAMES) | ||||||||||||||||||||||
| find_library(ECMASTER_${lib_name}_LIBRARY | ||||||||||||||||||||||
| NAMES ${lib_name} lib${lib_name}.so | ||||||||||||||||||||||
| PATHS ${ECMASTER_LIBRARY_DIR} | ||||||||||||||||||||||
| NO_DEFAULT_PATH | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| if(ECMASTER_${lib_name}_LIBRARY) | ||||||||||||||||||||||
| list(APPEND ECMASTER_LINK_LIBRARIES ${ECMASTER_${lib_name}_LIBRARY}) | ||||||||||||||||||||||
| message(STATUS "Found EC-Master link layer: ${lib_name}") | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
| endforeach() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Try to determine version from EcVersion.h | ||||||||||||||||||||||
| if(ECMASTER_INCLUDE_DIR) | ||||||||||||||||||||||
| set(ECVERSION_FILE "${ECMASTER_INCLUDE_DIR}/EcVersion.h") | ||||||||||||||||||||||
| if(EXISTS ${ECVERSION_FILE}) | ||||||||||||||||||||||
| file(READ ${ECVERSION_FILE} ECVERSION_CONTENT) | ||||||||||||||||||||||
| string(REGEX MATCH "#define EC_VERSION_MAJ[ \t]+([0-9]+)" _ ${ECVERSION_CONTENT}) | ||||||||||||||||||||||
| set(ECMASTER_VERSION_MAJOR ${CMAKE_MATCH_1}) | ||||||||||||||||||||||
| string(REGEX MATCH "#define EC_VERSION_MIN[ \t]+([0-9]+)" _ ${ECVERSION_CONTENT}) | ||||||||||||||||||||||
| set(ECMASTER_VERSION_MINOR ${CMAKE_MATCH_1}) | ||||||||||||||||||||||
| string(REGEX MATCH "#define EC_VERSION_SERVICEPACK[ \t]+([0-9]+)" _ ${ECVERSION_CONTENT}) | ||||||||||||||||||||||
| set(ECMASTER_VERSION_PATCH ${CMAKE_MATCH_1}) | ||||||||||||||||||||||
| string(REGEX MATCH "#define EC_VERSION_BUILD[ \t]+([0-9]+)" _ ${ECVERSION_CONTENT}) | ||||||||||||||||||||||
| set(ECMASTER_VERSION_BUILD ${CMAKE_MATCH_1}) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| if(ECMASTER_VERSION_MAJOR AND ECMASTER_VERSION_MINOR AND ECMASTER_VERSION_PATCH) | ||||||||||||||||||||||
| set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}.${ECMASTER_VERSION_BUILD}") | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
Comment on lines
+100
to
+102
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Version string may include empty component if BUILD is not found. If Consider conditionally including the build number: if(ECMASTER_VERSION_MAJOR AND ECMASTER_VERSION_MINOR AND ECMASTER_VERSION_PATCH)
- set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}.${ECMASTER_VERSION_BUILD}")
+ if(ECMASTER_VERSION_BUILD)
+ set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}.${ECMASTER_VERSION_BUILD}")
+ else()
+ set(ECMASTER_VERSION "${ECMASTER_VERSION_MAJOR}.${ECMASTER_VERSION_MINOR}.${ECMASTER_VERSION_PATCH}")
+ endif()
endif()📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Handle standard CMake find_package arguments | ||||||||||||||||||||||
| include(FindPackageHandleStandardArgs) | ||||||||||||||||||||||
| find_package_handle_standard_args(EcMaster | ||||||||||||||||||||||
| REQUIRED_VARS ECMASTER_INCLUDE_DIR ECMASTER_LIBRARY | ||||||||||||||||||||||
| VERSION_VAR ECMASTER_VERSION | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Set output variables | ||||||||||||||||||||||
| if(EcMaster_FOUND) | ||||||||||||||||||||||
| set(ECMASTER_LIBRARIES ${ECMASTER_LIBRARY} ${ECMASTER_LINK_LIBRARIES}) | ||||||||||||||||||||||
| set(ECMASTER_INCLUDE_DIRS ${ECMASTER_INCLUDE_DIR}) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Also check for Linux-specific include directory | ||||||||||||||||||||||
| if(EXISTS "${ECMASTER_INCLUDE_DIR}/Linux") | ||||||||||||||||||||||
| list(APPEND ECMASTER_INCLUDE_DIRS "${ECMASTER_INCLUDE_DIR}/Linux") | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Create imported target | ||||||||||||||||||||||
| if(NOT TARGET EcMaster::EcMaster) | ||||||||||||||||||||||
| add_library(EcMaster::EcMaster SHARED IMPORTED) | ||||||||||||||||||||||
| set_target_properties(EcMaster::EcMaster PROPERTIES | ||||||||||||||||||||||
| IMPORTED_LOCATION ${ECMASTER_LIBRARY} | ||||||||||||||||||||||
| INTERFACE_INCLUDE_DIRECTORIES "${ECMASTER_INCLUDE_DIRS}" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Add link layer libraries as dependencies | ||||||||||||||||||||||
| if(ECMASTER_LINK_LIBRARIES) | ||||||||||||||||||||||
| set_target_properties(EcMaster::EcMaster PROPERTIES | ||||||||||||||||||||||
| INTERFACE_LINK_LIBRARIES "${ECMASTER_LINK_LIBRARIES}" | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| message(STATUS "Found EC-Master SDK:") | ||||||||||||||||||||||
| message(STATUS " Version: ${ECMASTER_VERSION}") | ||||||||||||||||||||||
| message(STATUS " Include: ${ECMASTER_INCLUDE_DIRS}") | ||||||||||||||||||||||
| message(STATUS " Library: ${ECMASTER_LIBRARY}") | ||||||||||||||||||||||
| message(STATUS " Link layers: ${ECMASTER_LINK_LIBRARIES}") | ||||||||||||||||||||||
| endif() | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| # Mark variables as advanced | ||||||||||||||||||||||
| mark_as_advanced( | ||||||||||||||||||||||
| ECMASTER_INCLUDE_DIR | ||||||||||||||||||||||
| ECMASTER_LIBRARY | ||||||||||||||||||||||
| ECMASTER_LIBRARY_DIR | ||||||||||||||||||||||
| ) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| foreach(lib_name IN LISTS ECMASTER_LINK_LAYER_NAMES) | ||||||||||||||||||||||
| mark_as_advanced(ECMASTER_${lib_name}_LIBRARY) | ||||||||||||||||||||||
| endforeach() | ||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,94 @@ | ||||||
| # HoloCat - EtherCAT Real-time Integration | ||||||
|
|
||||||
|  | ||||||
|
|
||||||
| HoloCat is an EtherCAT master application that integrates the acontis EC-Master SDK with NVIDIA's Holoscan platform. | ||||||
|
|
||||||
| ## Overview | ||||||
|
|
||||||
| HoloCat provides deterministic EtherCAT communication capabilities within the Holoscan ecosystem, enabling: | ||||||
|
|
||||||
| - **Real-time Control** | ||||||
| - **Holoscan Native** | ||||||
|
|
||||||
| ## Prerequisites | ||||||
|
|
||||||
| ### Required Dependencies | ||||||
|
|
||||||
| 1. **acontis EC-Master SDK** (Commercial License) | ||||||
| - Version 3.2.3 or later | ||||||
|
|
||||||
| ## Usage | ||||||
|
|
||||||
| ### Prerequisites | ||||||
| ```bash | ||||||
| # Set EC-Master SDK path | ||||||
| export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm | ||||||
|
||||||
| export ECMASTER_ROOT=/home/hking/devel/ethercat/ecm | |
| export ECMASTER_ROOT=/opt/acontis/ecmaster # Adjust to your EC-Master install path |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix troubleshooting section numbering.
The numbering jumps from issue 1 to issue 3, skipping 2.
Apply this diff:
-3. **EC-Master SDK Not Found**
+2. **EC-Master SDK Not Found**🤖 Prompt for AI Agents
In applications/holocat/README.md around lines 83 to 89, the troubleshooting
list numbering skips from "1. Permission Denied" to "3. EC-Master SDK Not
Found"; update the ordered list so entries are sequential (1, 2, 3) by
renumbering the affected items or converting to an auto-numbered markdown list
so the second issue becomes "2. EC-Master SDK Not Found" (or use a continuous
numbered sequence) to restore correct ordering and consistency.
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List numbering is incorrect. The list jumps from "1. Permission Denied" to "3. EC-Master SDK Not Found", skipping item 2. Either add the missing item 2 or renumber item 3 as item 2.
| 3. **EC-Master SDK Not Found** | |
| 2. **EC-Master SDK Not Found** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add architecture overview section.
Per coding guidelines, the README should include an architecture overview. Add a section explaining the operator architecture (HolocatOp, HcDataTxOp, HcDataRxOp) and how they interact with the EtherCAT master and Holoscan framework.
As per coding guidelines, README.md must include architecture overview.
🤖 Prompt for AI Agents
applications/holocat/README.md lines 1-94: The README lacks the required
"Architecture Overview" section; add a concise subsection titled "Architecture
Overview" describing the operator architecture: list and briefly describe
HolocatOp, HcDataTxOp, and HcDataRxOp, explain that HolocatOp manages lifecycle
and interfaces with the acontis EC‑Master SDK (initialization, ENI loading,
cycle scheduling), HcDataTxOp handles outgoing process data to EtherCAT slaves
and timing control, and HcDataRxOp handles incoming process data and publishes
to Holoscan; include a simple diagram or sequence description of how data flows
between Holoscan application -> HolocatOp -> (HcDataTxOp -> EtherCAT master ->
slaves) and (slaves -> EtherCAT master -> HcDataRxOp -> Holoscan), and mention
real‑time considerations (cycle timing and priorities) and configuration points
(adapter_name, eni_file, cycle_time_us).
Large diffs are not rendered by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The exit(1) command on line 29 is unreachable because message(FATAL_ERROR) on line 26 already terminates the CMake configuration process. Remove lines 28-29 as they serve no purpose.