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
224 changes: 199 additions & 25 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,48 @@ on:
- cron: '38 2 * * *'

jobs:
build:
ubuntu_build:
name: ubuntu_build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Install build-tools
run: sudo apt-get update && sudo apt-get install -y build-essential cmake python3-pandas python3-lxml
- name: configure
run: >
mkdir build &&
cd build &&
cmake ..
-DBUILDING_TESTS=1
-DINTEGRATION_TESTS=1
-DWITH_ASAN=ON
-DPRIMARY_CLIENT_STRICT_PARSING_=ON
-DCMAKE_COMPILE_WARNING_AS_ERROR=ON
-DCHECK_RTDE_DOCS_RECIPE=ON
env:
CXXFLAGS: -g -O2 -fprofile-arcs -ftest-coverage
CFLAGS: -g -O2 -fprofile-arcs -ftest-coverage
LDFLAGS: -fprofile-arcs -ftest-coverage
- name: build
id: build
run: cmake --build build --config Debug
- name: Archive CMake build directory
if: steps.build.outcome == 'success'
run: tar -czf build.tar.gz build
- name: Upload CMake build archive
if: steps.build.outcome == 'success'
uses: actions/upload-artifact@v7
with:
path: build.tar.gz
if-no-files-found: error
retention-days: 5
archive: false

run_tests:
timeout-minutes: 60
runs-on: ubuntu-latest
name: build (${{matrix.env.URSIM_VERSION}}-${{matrix.env.ROBOT_MODEL}})
name: run_tests (${{matrix.env.URSIM_VERSION}}-${{matrix.env.ROBOT_MODEL}})
needs: ubuntu_build
strategy:
fail-fast: false
matrix:
Expand Down Expand Up @@ -46,8 +84,6 @@ jobs:
ROBOT_MODEL: ${{matrix.env.ROBOT_MODEL}}
URSIM_VERSION: ${{matrix.env.URSIM_VERSION}}
PROGRAM_FOLDER: ${{matrix.env.PROGRAM_FOLDER}}
- name: install-pips
run: pip install pandas lxml
- id: check_polyscopex
run: |
if [[ "${{matrix.env.URSIM_VERSION}}" == "10."* ]]; then
Expand All @@ -57,29 +93,21 @@ jobs:
fi
- name: setup chrome
uses: browser-actions/setup-chrome@v2
- name: configure
run: >
mkdir build &&
cd build &&
cmake ..
-DBUILDING_TESTS=1
-DINTEGRATION_TESTS=1
-DWITH_ASAN=ON
-DPRIMARY_CLIENT_STRICT_PARSING=ON
-DCMAKE_COMPILE_WARNING_AS_ERROR=ON
-DCHECK_RTDE_DOCS_RECIPE=ON
env:
CXXFLAGS: -g -O2 -fprofile-arcs -ftest-coverage
CFLAGS: -g -O2 -fprofile-arcs -ftest-coverage
LDFLAGS: -fprofile-arcs -ftest-coverage
- name: build
id: build
run: cmake --build build --config Debug
- name: Download CMake build archive
uses: actions/download-artifact@v8
with:
name: build.tar.gz
- name: Extract CMake build directory
run: tar -xzf build.tar.gz
- name: Create folder for test artifacts
run: mkdir -p test_artifacts
- name: Access PolyScope
if: ${{ steps.check_polyscopex.outputs.is_polyscopex == 'true' }}
run: chrome --no-sandbox --disable-settuid-sandbox --headless=new 192.168.56.101 &
- name: Install Python dependencies
run: sudo apt-get update && sudo apt-get install -y python3-pandas python3-lxml
- name: Generate rtde outputs lists
run: python3 tests/resources/generate_rtde_outputs.py
- name: test
run: cd build && ctest --output-on-failure --output-junit junit.xml
env:
Expand All @@ -96,13 +124,10 @@ jobs:
- name: run examples
run: ./run_examples.sh "192.168.56.101" 1
- name: install gcovr
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: sudo apt-get install -y gcovr
- name: gcovr
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
run: cd build && gcovr -r .. --xml coverage.xml --gcov-ignore-parse-errors negative_hits.warn_once_per_file --exclude "../3rdparty"
- name: Upload coverage reports to Codecov with GitHub Action
if: ${{ !cancelled() && steps.build.outcome == 'success' }}
uses: codecov/codecov-action@v6
with:
fail_ci_if_error: true
Expand Down Expand Up @@ -150,6 +175,155 @@ jobs:
if-no-files-found: warn
retention-days: 10

robot_model_check:
timeout-minutes: 60
runs-on: ubuntu-latest
needs: ubuntu_build
name: check_model (${{matrix.env.URSIM_VERSION}}-${{matrix.env.ROBOT_MODEL}})
strategy:
fail-fast: false
matrix:
env:
- ROBOT_MODEL: 'ur3'
URSIM_VERSION: '3.14.3'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/cb3'
- ROBOT_MODEL: 'ur5'
URSIM_VERSION: '3.15.8'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/cb3'
- ROBOT_MODEL: 'ur10'
URSIM_VERSION: '3.15.8'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/cb3'
- ROBOT_MODEL: 'ur3e'
URSIM_VERSION: '5.9.4'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur5e'
URSIM_VERSION: '5.12.8'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur7e'
URSIM_VERSION: '5.22.2'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur10e'
URSIM_VERSION: '5.15.2'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur12e'
URSIM_VERSION: '5.25.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur16e'
URSIM_VERSION: '5.25.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur8long'
URSIM_VERSION: '5.25.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur15'
URSIM_VERSION: '5.25.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur18'
URSIM_VERSION: '5.25.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur20'
URSIM_VERSION: '5.25.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur30'
URSIM_VERSION: '5.25.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/e-series'
- ROBOT_MODEL: 'ur3e'
URSIM_VERSION: '10.11.0'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur5e'
URSIM_VERSION: '10.11.0'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur7e'
URSIM_VERSION: '10.11.0'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur10e'
URSIM_VERSION: '10.11.0'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur12e'
URSIM_VERSION: '10.12.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur16e'
URSIM_VERSION: '10.12.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur8long'
URSIM_VERSION: '10.12.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur15'
URSIM_VERSION: '10.12.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur18'
URSIM_VERSION: '10.12.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur20'
URSIM_VERSION: '10.12.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'
- ROBOT_MODEL: 'ur30'
URSIM_VERSION: '10.12.1'
PROGRAM_FOLDER: 'tests/resources/dockerursim/programs/polyscopex'

steps:
- uses: actions/checkout@v6
- name: start ursim
run: |
scripts/start_ursim.sh -m $ROBOT_MODEL -v $URSIM_VERSION -p $PROGRAM_FOLDER -d -f DISABLED
env:
DOCKER_RUN_OPTS: --network ursim_net
ROBOT_MODEL: ${{matrix.env.ROBOT_MODEL}}
URSIM_VERSION: ${{matrix.env.URSIM_VERSION}}
PROGRAM_FOLDER: ${{matrix.env.PROGRAM_FOLDER}}
- name: Download CMake build archive
uses: actions/download-artifact@v8
with:
name: build.tar.gz
env:
DOCKER_RUN_OPTS: --network ursim_net
ROBOT_MODEL: ${{matrix.env.ROBOT_MODEL}}
URSIM_VERSION: ${{matrix.env.URSIM_VERSION}}
PROGRAM_FOLDER: ${{matrix.env.PROGRAM_FOLDER}}
- name: Extract CMake build directory
run: tar -xzf build.tar.gz
- name: inspect build folder
run: ls -la build && ls -la build/tests
- name: test robot type
run: cd build && ctest -R PrimaryClientTest.test_robot_type --verbose --output-junit junit.xml
env:
URSIM_VERSION: ${{matrix.env.URSIM_VERSION}}
ROBOT_MODEL: ${{matrix.env.ROBOT_MODEL}}
- name: install gcovr
run: sudo apt-get install -y gcovr
- name: gcovr
run: cd build && gcovr -r .. --xml coverage.xml --gcov-ignore-parse-errors negative_hits.warn_once_per_file --exclude "../3rdparty"
- name: Upload coverage reports to Codecov with GitHub Action
uses: codecov/codecov-action@v6
with:
fail_ci_if_error: true
files: build/coverage.xml
flags: check_version_${{ matrix.env.ROBOT_MODEL }}-${{ matrix.env.URSIM_VERSION }}
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- name: Generate URSim log files
if: ${{ always() && steps.check_polyscopex.outputs.is_polyscopex == 'false' }}
run: |
nc -q 1 192.168.56.101 29999 <<END
saveLog
END
mkdir -p ursim_logs
docker cp ursim:/ursim/URControl.log ursim_logs/URControl.log
docker cp ursim:/ursim/polyscope.log ursim_logs/polyscope.log
docker cp ursim:/ursim/log_history.txt ursim_logs/log_history.txt
- name: Copy flight reports
if: ${{ failure() && steps.check_polyscopex.outputs.is_polyscopex == 'false' }}
run: |
mkdir -p ursim_logs/flightreports
docker cp ursim:/ursim/flightreports/. ursim_logs/flightreports/
- name: Upload logfiles
uses: actions/upload-artifact@v7
if: ${{ always() && steps.check_polyscopex.outputs.is_polyscopex == 'false' }}
with:
name: ${{matrix.env.ROBOT_MODEL}}_${{matrix.env.URSIM_VERSION}}_model_check_URSim_Logs
path: ursim_logs
if-no-files-found: error
retention-days: 10

test_start_ursim:
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 2 additions & 0 deletions include/ur_client_library/helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,7 @@ void clampToUnitRange(std::array<T, N>& values)
*/
RobotSeries robotSeriesFromTypeAndVersion(const RobotType type, const VersionInformation& version);

RobotType robotTypeFromString(const std::string& robot_type_str);

} // namespace urcl
#endif // ifndef UR_CLIENT_LIBRARY_HELPERS_H_INCLUDED
8 changes: 7 additions & 1 deletion scripts/start_ursim.sh
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,13 @@ strip_robot_model()
if [[ "$robot_model" = @(ur3e|ur5e|ur10e|ur16e) ]]; then
ROBOT_MODEL=$(echo "${ROBOT_MODEL:0:$((${#ROBOT_MODEL}-1))}")
elif [[ "$robot_model" = @(ur7e|ur12e) ]]; then
ROBOT_MODEL=$(echo "${ROBOT_MODEL:0:$((${#ROBOT_MODEL}-1))}e")
# PolyScope X uses UR7e and UR12e, but PolyScope 5 uses UR7 and UR12. So we
# need to strip the "e" for PolyScope 5
if [[ "$robot_series" == "polyscopex" ]]; then
ROBOT_MODEL=$(echo "${ROBOT_MODEL:0:$((${#ROBOT_MODEL}-1))}e")
else
ROBOT_MODEL=$(echo "${ROBOT_MODEL:0:$((${#ROBOT_MODEL}-1))}")
fi
fi
fi
}
Expand Down
65 changes: 65 additions & 0 deletions src/helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,4 +203,69 @@ RobotSeries robotSeriesFromTypeAndVersion(const RobotType type, const VersionInf
return RobotSeries::UNDEFINED;
}

RobotType robotTypeFromString(const std::string& robot_type_str)
{
if (robot_type_str == "ur3")
{
return RobotType::UR3;
}
else if (robot_type_str == "ur3e")
{
return RobotType::UR3;
}
else if (robot_type_str == "ur5")
{
return RobotType::UR5;
}
else if (robot_type_str == "ur5e")
{
return RobotType::UR5;
}
else if (robot_type_str == "ur7e")
{ // UR7e reports as UR5
return RobotType::UR5;
}
else if (robot_type_str == "ur10")
{
return RobotType::UR10;
}
else if (robot_type_str == "ur10e")
{
return RobotType::UR10;
}
else if (robot_type_str == "ur12e")
{ // UR12e reports as UR10
return RobotType::UR10;
}
else if (robot_type_str == "ur16e")
{
return RobotType::UR16;
}
else if (robot_type_str == "ur15")
{
return RobotType::UR15;
}
else if (robot_type_str == "ur18")
{
return RobotType::UR18;
}
else if (robot_type_str == "ur20")
{
return RobotType::UR20;
}
else if (robot_type_str == "ur30")
{
return RobotType::UR30;
}
else if (robot_type_str == "ur8long")
{
return RobotType::UR8LONG;
}
else
{
return RobotType::UR5;
throw std::invalid_argument("Unknown robot type: " + robot_type_str);
}
}

} // namespace urcl
21 changes: 21 additions & 0 deletions tests/test_primary_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,27 @@ TEST_F(PrimaryClientTest, test_configuration_data)
EXPECT_NE(client_->getRobotType(), RobotType::UNDEFINED);
}

TEST_F(PrimaryClientTest, test_robot_type)
{
if (std::getenv("ROBOT_MODEL") == nullptr)
{
GTEST_SKIP() << "ROBOT_MODEL environment variable not set. Skipping test.";
}
EXPECT_NO_THROW(client_->start());

// Wait until we have received configuration data so that the robot type is known.
auto start_time = std::chrono::system_clock::now();
const auto timeout = std::chrono::seconds(10);
while (client_->getConfigurationData() == nullptr && std::chrono::system_clock::now() - start_time < timeout)
{
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
ASSERT_NE(client_->getConfigurationData(), nullptr);
const std::string robot_model_env = std::getenv("ROBOT_MODEL");
const RobotType expected_series_from_env = robotTypeFromString(robot_model_env);
EXPECT_EQ(client_->getRobotType(), expected_series_from_env);
}

TEST_F(PrimaryClientTest, test_kinematics_info)
{
EXPECT_NO_THROW(client_->start());
Expand Down
Loading
Loading