From bfcbdcd9a32417cc7bf3648adf1c6c24fc52931c Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 19:12:41 +0100 Subject: [PATCH 01/26] Add coverage report uploading --- .coveragerc | 8 ++++++++ .travis.yml | 2 ++ coverage.sh | 6 ++++++ 3 files changed, 16 insertions(+) create mode 100644 .coveragerc create mode 100755 coverage.sh diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..78d956e --- /dev/null +++ b/.coveragerc @@ -0,0 +1,8 @@ +[report] +include = + *march_rqt_gait_selection* + *march_rqt_input_device* + *march_rqt_note_taker* +omit = + *test* + *__init__.py diff --git a/.travis.yml b/.travis.yml index c8c8d5a..98ce213 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,6 +22,8 @@ env: - ROS_REPO=ros - BUILDER=colcon - CATKIN_LINT=pedantic + - CATKIN_TEST_COVERAGE=1 + - AFTER_RUN_TARGET_TEST="cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z -f coverage.xml" jobs: include: diff --git a/coverage.sh b/coverage.sh new file mode 100755 index 0000000..8521162 --- /dev/null +++ b/coverage.sh @@ -0,0 +1,6 @@ +#!/usr/bin/env sh + +cd build/march_rqt_note_taker || return +coverage xml --rcfile ../../src/monitor/.coveragerc +cp coverage.xml ../.. +cd ../.. || return From 12453313d0bb63c0e34c7a6891118ba8f08a07ee Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 19:13:11 +0100 Subject: [PATCH 02/26] Fix double quotes --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 98ce213..2af80f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ env: - BUILDER=colcon - CATKIN_LINT=pedantic - CATKIN_TEST_COVERAGE=1 - - AFTER_RUN_TARGET_TEST="cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z -f coverage.xml" + - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z -f coverage.xml' jobs: include: From 1278d2d830a68e1a5da3b5d1d53f264f009c8265 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 19:50:08 +0100 Subject: [PATCH 03/26] Add pip install coverage --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2af80f7..bd004e3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ env: - BUILDER=colcon - CATKIN_LINT=pedantic - CATKIN_TEST_COVERAGE=1 - - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z -f coverage.xml' + - AFTER_RUN_TARGET_TEST='cd "$target_ws" && pip install coverage && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z -f coverage.xml' jobs: include: From 1a98cba4f92092e07e9056e68165f16b817c228d Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 19:59:57 +0100 Subject: [PATCH 04/26] Fix after script --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index bd004e3..eeaf74f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,9 +20,10 @@ git: env: global: - ROS_REPO=ros + - ADDITIONAL_DEBS=curl - BUILDER=colcon - CATKIN_LINT=pedantic - - CATKIN_TEST_COVERAGE=1 + - DOCKER_RUN_OPTS='-e CATKIN_TEST_COVERAGE=1' - AFTER_RUN_TARGET_TEST='cd "$target_ws" && pip install coverage && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z -f coverage.xml' jobs: From 43a1c9d87cae02a7c93606a00703d306398b93e1 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 20:23:24 +0100 Subject: [PATCH 05/26] Move coverage uploading out of container --- .travis.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index eeaf74f..da9f567 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,8 +23,9 @@ env: - ADDITIONAL_DEBS=curl - BUILDER=colcon - CATKIN_LINT=pedantic - - DOCKER_RUN_OPTS='-e CATKIN_TEST_COVERAGE=1' - - AFTER_RUN_TARGET_TEST='cd "$target_ws" && pip install coverage && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z -f coverage.xml' + - DOCKER_RUN_OPTS='-e CATKIN_TEST_COVERAGE=1 -v "/root/shared:/shared"' + - AFTER_INSTALL_TARGET_DEPENDENCIES='pip install coverage' + - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && mv coverage.xml /shared' jobs: include: @@ -40,5 +41,11 @@ jobs: # clone and run industrial_ci install: - git clone --quiet --depth 1 https://github.com/ros-industrial/industrial_ci.git .industrial_ci -b master + - mkdir /root/shared + script: - .industrial_ci/travis.sh + +after_success: + - cd /root/shared + - bash <(curl -s https://codecov.io/bash) -Z From cbeb9df3a3357837ea1482fd02422828359c8153 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 20:34:36 +0100 Subject: [PATCH 06/26] Move coverage uploading inside container --- .travis.yml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index da9f567..a4fac9f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,9 +23,10 @@ env: - ADDITIONAL_DEBS=curl - BUILDER=colcon - CATKIN_LINT=pedantic - - DOCKER_RUN_OPTS='-e CATKIN_TEST_COVERAGE=1 -v "/root/shared:/shared"' + - CI_ENV=`bash <(curl -s https://codecov.io/env)` + - DOCKER_RUN_OPTS='$CI_ENV -e CATKIN_TEST_COVERAGE=1' - AFTER_INSTALL_TARGET_DEPENDENCIES='pip install coverage' - - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && mv coverage.xml /shared' + - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z' jobs: include: @@ -41,11 +42,6 @@ jobs: # clone and run industrial_ci install: - git clone --quiet --depth 1 https://github.com/ros-industrial/industrial_ci.git .industrial_ci -b master - - mkdir /root/shared script: - .industrial_ci/travis.sh - -after_success: - - cd /root/shared - - bash <(curl -s https://codecov.io/bash) -Z From 2c54d57aaf1ce54873199943c76a827e47f7bef4 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 20:48:08 +0100 Subject: [PATCH 07/26] Add path fixes --- codecov.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..55f2b7b --- /dev/null +++ b/codecov.yml @@ -0,0 +1,2 @@ +fixes: + - "src/monitor/::" From 43c9a128db3bd398c76ccdff702bf0a48654bd89 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 21:52:54 +0100 Subject: [PATCH 08/26] Add imports to init so they are included in coverage --- march_rqt_note_taker/src/march_rqt_note_taker/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/march_rqt_note_taker/src/march_rqt_note_taker/__init__.py b/march_rqt_note_taker/src/march_rqt_note_taker/__init__.py index e69de29..6f3d89f 100644 --- a/march_rqt_note_taker/src/march_rqt_note_taker/__init__.py +++ b/march_rqt_note_taker/src/march_rqt_note_taker/__init__.py @@ -0,0 +1,5 @@ +from .entry import Entry +from .entry_model import EntryModel +from .filter_map import FilterMap +from .notes_plugin import NotesPlugin +from .notes_widget import NotesWidget From 430496a0166b57a7106c3d2d9d01e2d9ed77218b Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 21:53:29 +0100 Subject: [PATCH 09/26] Add python-coverage as test depend --- .travis.yml | 3 +-- march_rqt_note_taker/package.xml | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index a4fac9f..3d1935d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,7 @@ env: - BUILDER=colcon - CATKIN_LINT=pedantic - CI_ENV=`bash <(curl -s https://codecov.io/env)` - - DOCKER_RUN_OPTS='$CI_ENV -e CATKIN_TEST_COVERAGE=1' - - AFTER_INSTALL_TARGET_DEPENDENCIES='pip install coverage' + - DOCKER_RUN_OPTS='$CI_ENV -e CATKIN_TEST_COVERAGE=1 -e NOSE_COVER_BRANCES=True' - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z' jobs: diff --git a/march_rqt_note_taker/package.xml b/march_rqt_note_taker/package.xml index 0bb2d48..a2b1978 100644 --- a/march_rqt_note_taker/package.xml +++ b/march_rqt_note_taker/package.xml @@ -16,6 +16,7 @@ rqt_gui_py rosunit + python-coverage From 9da5866490ca6d7707bf443b0ea69f6198ac87fe Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 22:00:56 +0100 Subject: [PATCH 10/26] Add nose cover inclusive and branch --- .travis.yml | 3 ++- march_rqt_note_taker/package.xml | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3d1935d..5a108b9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,8 @@ env: - BUILDER=colcon - CATKIN_LINT=pedantic - CI_ENV=`bash <(curl -s https://codecov.io/env)` - - DOCKER_RUN_OPTS='$CI_ENV -e CATKIN_TEST_COVERAGE=1 -e NOSE_COVER_BRANCES=True' + - DOCKER_RUN_OPTS='$CI_ENV -e CATKIN_TEST_COVERAGE=1 -e NOSE_COVER_INCLUSIVE=True -e NOSE_COVER_BRANCHES=True' + - AFTER_INSTALL_TARGET_DEPENDENCIES='pip install coverage' - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z' jobs: diff --git a/march_rqt_note_taker/package.xml b/march_rqt_note_taker/package.xml index a2b1978..0bb2d48 100644 --- a/march_rqt_note_taker/package.xml +++ b/march_rqt_note_taker/package.xml @@ -16,7 +16,6 @@ rqt_gui_py rosunit - python-coverage From c9297cb21b6796d423cbb8f8ffe035d172f7127e Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 14 Jan 2020 22:31:28 +0100 Subject: [PATCH 11/26] Ignore flake8 init --- .flake8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.flake8 b/.flake8 index 536403d..b23ecc7 100644 --- a/.flake8 +++ b/.flake8 @@ -2,7 +2,7 @@ show-source = true max-line-length = 120 format = ${cyan}%(path)s${reset}:${yellow_bold}%(row)d${reset}:${green_bold}%(col)d${reset}: ${red_bold}%(code)s${reset} %(text)s -exclude = .git +exclude = .git, __init__.py application-package-names = march_rqt_gait_selection, march_rqt_input_device, From 20d1dc37675c5a064b46c607ec45c2755df57589 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Wed, 15 Jan 2020 12:02:28 +0100 Subject: [PATCH 12/26] Increase test coverage --- march_rqt_note_taker/test/entry_model_test.py | 24 ++++++++++++++++++- march_rqt_note_taker/test/entry_test.py | 5 ++++ march_rqt_note_taker/test/filter_map_test.py | 5 ++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/march_rqt_note_taker/test/entry_model_test.py b/march_rqt_note_taker/test/entry_model_test.py index 975cd17..f49e50f 100644 --- a/march_rqt_note_taker/test/entry_model_test.py +++ b/march_rqt_note_taker/test/entry_model_test.py @@ -1,5 +1,6 @@ import unittest +from python_qt_binding.QtCore import QDateTime, Qt from rosgraph_msgs.msg import Log from march_rqt_note_taker.entry import Entry @@ -14,10 +15,20 @@ def test_empty_model(self): self.assertEqual(self.model.rowCount(), 0) self.assertEqual(self.model.columnCount(), 2) + def test_horizontal_model_header(self): + self.assertEqual(self.model.headerData(0, Qt.Horizontal, Qt.DisplayRole), 'Time') + self.assertEqual(self.model.headerData(1, Qt.Horizontal, Qt.DisplayRole), 'Entry') + def test_insert_single_row(self): - self.model.insert_row(Entry('test')) + entry = Entry('test', QDateTime.fromSecsSinceEpoch(5)) + self.model.insert_row(entry) self.assertEqual(self.model.rowCount(), 1) + time_index = self.model.createIndex(0, 0) + content_index = self.model.createIndex(0, 1) + self.assertEqual(self.model.data(time_index), entry.time_string()) + self.assertEqual(self.model.data(content_index), entry.content) + def test_insert_multiple_row(self): self.model.insert_row(Entry('test1')) self.model.insert_row(Entry('test2')) @@ -61,3 +72,14 @@ def test_get_row_out_of_bounds(self): def test_get_column_out_of_bounds(self): self.assertIsNone(self.model.data(self.model.createIndex(0, len(self.model.columns)))) + + def test_empty_model_to_string(self): + self.assertEqual(str(self.model), '') + + def test_entry_model_to_string(self): + entry = Entry('test1', QDateTime.fromSecsSinceEpoch(5)) + self.model.insert_row(entry) + self.model.insert_row(entry) + self.model.insert_row(entry) + + self.assertEqual(str(self.model), '{0}\n{0}\n{0}'.format(entry)) diff --git a/march_rqt_note_taker/test/entry_test.py b/march_rqt_note_taker/test/entry_test.py index e10923a..dd0e1b9 100644 --- a/march_rqt_note_taker/test/entry_test.py +++ b/march_rqt_note_taker/test/entry_test.py @@ -56,3 +56,8 @@ def test_to_string(self): entry = Entry(content, date_time) self.assertEqual(str(entry), '[{0}] {1}'.format(date_time.toString(), content)) + + def test_to_time_string(self): + date_time = QDateTime.fromSecsSinceEpoch(5) + entry = Entry('', date_time) + self.assertEqual(entry.time_string(), '01:00:05') diff --git a/march_rqt_note_taker/test/filter_map_test.py b/march_rqt_note_taker/test/filter_map_test.py index 4ddb9d2..3b584b1 100644 --- a/march_rqt_note_taker/test/filter_map_test.py +++ b/march_rqt_note_taker/test/filter_map_test.py @@ -50,6 +50,11 @@ def test_reject_log_level_filter(self): self.filter_map.add_filter_on_level(lambda _: True, level) self.assertIsNone(self.filter_map(self.log_msg)) + def test_info_level_filter(self): + self.log_msg.level = Log.INFO + self.filter_map.add_filter_info_level(lambda _: True) + self.assertIsNotNone(self.filter_map(self.log_msg)) + def test_accept_and_map(self): mapped_msg = 'test' self.filter_map.add_filter(lambda _: True, lambda _: mapped_msg) From 5d790ffa224cda36aa29e92da178ff0f54bd56f1 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Wed, 15 Jan 2020 12:15:29 +0100 Subject: [PATCH 13/26] Add timezone for consistent test results --- march_rqt_note_taker/test/entry_test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/march_rqt_note_taker/test/entry_test.py b/march_rqt_note_taker/test/entry_test.py index dd0e1b9..3116a54 100644 --- a/march_rqt_note_taker/test/entry_test.py +++ b/march_rqt_note_taker/test/entry_test.py @@ -1,6 +1,6 @@ import unittest -from python_qt_binding.QtCore import QDateTime +from python_qt_binding.QtCore import QDateTime, QTimeZone from rosgraph_msgs.msg import Log import rospy @@ -58,6 +58,6 @@ def test_to_string(self): '[{0}] {1}'.format(date_time.toString(), content)) def test_to_time_string(self): - date_time = QDateTime.fromSecsSinceEpoch(5) + date_time = QDateTime.fromSecsSinceEpoch(5, QTimeZone.utc()) entry = Entry('', date_time) - self.assertEqual(entry.time_string(), '01:00:05') + self.assertEqual(entry.time_string(), '00:00:05') From 87d7536bf5f8819025718b78a2d4fdf5e414cff4 Mon Sep 17 00:00:00 2001 From: JorisWeeda <45165354+JorisWeeda@users.noreply.github.com> Date: Tue, 28 Jan 2020 11:18:20 +0100 Subject: [PATCH 14/26] Feature/pm 249 mock rockerswitch (#17) * Created a more MVC (model, view, controller) based program. The structure is better readable and easier to change in the future. Also added two new buttons to simulate the rocker switch input and reordered the button layout to be more logical. The model of the MVC has not been separately created because this GUI is relatively easy and an extra file would only make it less readable. * Removed the deprecated files and changed the reference of the GUI in the plugin to the newly created program. * Fixed flake8 errors * changed the rocker switch publish to use the increment or decrement variable. * Added the new gait instruction msg variable to send feedback on incrementing and decrementing using the rocker switch. Co-authored-by: Olav de Haas --- march_rqt_input_device/plugin.xml | 2 +- .../march_rqt_input_device/LayoutBuilder.py | 80 ----- .../src/march_rqt_input_device/MarchButton.py | 21 -- .../march_rqt_input_device/input_device.py | 251 --------------- .../input_device_controller.py | 59 ++++ .../input_device_view.py | 301 ++++++++++++++++++ 6 files changed, 361 insertions(+), 353 deletions(-) delete mode 100644 march_rqt_input_device/src/march_rqt_input_device/LayoutBuilder.py delete mode 100644 march_rqt_input_device/src/march_rqt_input_device/MarchButton.py delete mode 100644 march_rqt_input_device/src/march_rqt_input_device/input_device.py create mode 100644 march_rqt_input_device/src/march_rqt_input_device/input_device_controller.py create mode 100644 march_rqt_input_device/src/march_rqt_input_device/input_device_view.py diff --git a/march_rqt_input_device/plugin.xml b/march_rqt_input_device/plugin.xml index 3c27912..3192e6c 100644 --- a/march_rqt_input_device/plugin.xml +++ b/march_rqt_input_device/plugin.xml @@ -1,5 +1,5 @@ - + An example Python GUI plugin to create a great user interface. diff --git a/march_rqt_input_device/src/march_rqt_input_device/LayoutBuilder.py b/march_rqt_input_device/src/march_rqt_input_device/LayoutBuilder.py deleted file mode 100644 index 3131d3b..0000000 --- a/march_rqt_input_device/src/march_rqt_input_device/LayoutBuilder.py +++ /dev/null @@ -1,80 +0,0 @@ -import os - -from python_qt_binding.QtWidgets import QGridLayout -from python_qt_binding.QtWidgets import QPushButton -import rospkg - -from .MarchButton import MarchButton - - -class LayoutBuilder: - """Builds a layout from a 2d array of MarchButtons.""" - - def __init__(self, button_layout): - """Stores the 2d array of MarchButtons.""" - self.button_layout = button_layout - - def build(self): - """Loops through the 2d array and create a qt_button if the entry is not None.""" - qt_button_layout = QGridLayout() - for i in range(len(self.button_layout)): - for j in range(len(self.button_layout[i])): - - march_button = self.button_layout[i][j] - if march_button is not None: - qt_button = self.create_qt_button(march_button) - qt_button_layout.addWidget(qt_button, i, j, march_button.row_span, march_button.column_span) - else: - qt_button = self.create_qt_default_button() - qt_button_layout.addWidget(qt_button, i, j) - - return qt_button_layout - - def create_qt_button(self, march_button): - """Creates a qt_button from a MarchButton. - - Sets all the specified callback, text and other properties on the qt_button. - """ - qt_button = QPushButton(march_button.text) - if march_button.callback is not None: - qt_button.clicked.connect(march_button.callback) - qt_button.setStyleSheet( - self.create_button_css(self.get_image_path(march_button.image))) - if march_button.text != '': - qt_button.setText(march_button.text) - qt_button.setMinimumSize(march_button.size) - - return qt_button - - def create_qt_default_button(self): - """Creates an invisible qt_default button to act as placeholder in the grid.""" - qt_button = QPushButton() - qt_button.setStyleSheet(self.get_empty_css()) - qt_button.setFixedSize(MarchButton.default_size) - qt_button.setVisible(False) - return qt_button - - @staticmethod - def get_empty_css(): - """CSS of a hidden button.""" - return """ - display: hidden; - """ - - @staticmethod - def create_button_css(img_path): - """CSS of a button with a background-image.""" - css_base = """ - background: url() no-repeat center center; - background-color:#1F1E24; - color: #FFFFFF; - """ - return css_base.replace('', img_path) - - @staticmethod - def get_image_path(img_name): - """Create an absolute image path to an image.""" - return os.path.join( - rospkg.RosPack().get_path('march_rqt_input_device'), - 'resource', - 'img{0}'.format(img_name)) diff --git a/march_rqt_input_device/src/march_rqt_input_device/MarchButton.py b/march_rqt_input_device/src/march_rqt_input_device/MarchButton.py deleted file mode 100644 index dd46f10..0000000 --- a/march_rqt_input_device/src/march_rqt_input_device/MarchButton.py +++ /dev/null @@ -1,21 +0,0 @@ -from python_qt_binding.QtCore import QSize - - -class MarchButton: - """Button that can have a custom callback and other configurable properties.""" - - """Default size of a button, is used if no other size is given.""" - default_size = QSize(150, 150) - - def __init__(self, name, text='', image='', callback=None, size=None, row_span=1, column_span=1): - self.name = name - self.text = text - self.image = image - self.callback = callback - self.row_span = row_span - self.column_span = column_span - - if size is not None: - self.size = size - else: - self.size = MarchButton.default_size diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device.py b/march_rqt_input_device/src/march_rqt_input_device/input_device.py deleted file mode 100644 index 51af08e..0000000 --- a/march_rqt_input_device/src/march_rqt_input_device/input_device.py +++ /dev/null @@ -1,251 +0,0 @@ -import os - -from python_qt_binding import loadUi -from python_qt_binding.QtWidgets import QWidget -from qt_gui.plugin import Plugin -import rospkg -import rospy -import std_msgs.msg -from std_msgs.msg import Time - -from march_shared_resources.msg import Error, GaitInstruction - -from .LayoutBuilder import LayoutBuilder -from .MarchButton import MarchButton - - -class InputDevicePlugin(Plugin): - - def __init__(self, context): - super(InputDevicePlugin, self).__init__(context) - # Give QObjects reasonable names - self.setObjectName('InputDevicePlugin') - - # Create QWidget - self._widget = QWidget() - # Get path to UI file which should be in - # the 'resource' folder of this package - ui_file = os.path.join( - rospkg.RosPack().get_path('march_rqt_input_device'), 'resource', - 'input_device.ui') - - # Extend the widget with all attributes and children from UI file - loadUi(ui_file, self._widget) - # Give QObjects reasonable names - self._widget.setObjectName('Input Device') - # Show _widget.windowTitle on left-top of each plugin (when - # it's set in _widget). This is useful when you open multiple - # plugins at once. Also if you open multiple instances of your - # plugin at once, these lines add number to make it easy to - # tell from pane to pane. - if context.serial_number() > 1: - self._widget.setWindowTitle('{0} ({1})'.format(self._widget.windowTitle(), - context.serial_number())) - # Add widget to the user interface - context.add_widget(self._widget) - - # Create buttons here - home_sit_button = MarchButton(name='home_sit', image='/home_sit.png', - callback=lambda: self.publish_gait( - 'home_sit')) - home_stand_button = MarchButton(name='home_stand', - image='/home_stand.png', - callback=lambda: self.publish_gait( - 'home_stand')) - gait_sit_button = MarchButton(name='gait_sit', image='/gait_sit.png', - callback=lambda: self.publish_gait( - 'gait_sit')) - gait_walk_button = MarchButton(name='gait_walk', - image='/gait_walk_normal.png', - callback=lambda: self.publish_gait( - 'gait_walk')) - gait_walk_small_button = MarchButton(name='gait_walk_small', - image='/gait_walk_small.png', - callback=lambda: self.publish_gait( - 'gait_walk_small')) - gait_single_step_small_button = MarchButton(name='gait_single_step_small', - image='/gait_single_step_small.png', - callback=lambda: self.publish_gait( - 'gait_single_step_small')) - gait_single_step_normal_button = MarchButton(name='gait_single_step_normal', - image='/gait_single_step_normal.png', - callback=lambda: self.publish_gait( - 'gait_single_step_normal')) - gait_side_step_left_button = MarchButton(name='gait_side_step_left', - image='/gait_side_step_left.png', - callback=lambda: self.publish_gait( - 'gait_side_step_left')) - gait_side_step_right_button = MarchButton(name='gait_side_step_right', - image='/gait_side_step_right.png', - callback=lambda: self.publish_gait( - 'gait_side_step_right')) - gait_side_step_left_small_button = MarchButton(name='gait_side_step_left_small', - text='Side step left small', - callback=lambda: self.publish_gait( - 'gait_side_step_left_small')) - gait_side_step_right_small_button = MarchButton(name='gait_side_step_right_small', - text='Side step right small', - callback=lambda: self.publish_gait( - 'gait_side_step_right_small')) - gait_stand_button = MarchButton(name='gait_stand', - image='/gait_stand.png', - callback=lambda: self.publish_gait( - 'gait_stand')) - gait_sofa_stand_button = MarchButton(name='gait_sofa_stand', - image='/gait_sofa_stand_up.png', - callback=lambda: self.publish_gait( - 'gait_sofa_stand')) - gait_sofa_sit_button = MarchButton(name='gait_sofa_sit', - image='/gait_sofa_sit.png', - callback=lambda: self.publish_gait( - 'gait_sofa_sit')) - gait_stairs_up_button = MarchButton(name='gait_stairs_up', - image='/gait_stairs_up.png', - callback=lambda: self.publish_gait( - 'gait_stairs_up')) - gait_stairs_down_button = MarchButton(name='gait_stairs_down', - image='/gait_stairs_down.png', - callback=lambda: self.publish_gait( - 'gait_stairs_down')) - gait_rough_terrain_high_step = MarchButton(name='gait_rough_terrain_high_step', - text='Rough terrain high step', - callback=lambda: self.publish_gait( - 'gait_rough_terrain_high_step')) - - gait_rough_terrain_middle_steps = MarchButton(name='gait_rough_terrain_middle_steps', - text='Rough terrain middle steps', - callback=lambda: self.publish_gait( - 'gait_rough_terrain_middle_steps')) - - gait_ramp_door_slope_up = MarchButton(name='gait_ramp_door_slope_up', - text='Ramp and Door slope up', - callback=lambda: self.publish_gait('gait_ramp_door_slope_up')) - - gait_ramp_door_slope_down = MarchButton(name='gait_ramp_door_slope_down', - text='Ramp and Door slope down', - callback=lambda: self.publish_gait('gait_ramp_door_slope_down')) - - gait_ramp_door_last_step = MarchButton(name='gait_ramp_door_last_step', - text='Ramp and Door last step', - callback=lambda: self.publish_gait('gait_ramp_door_last_step')) - - gait_tilted_path_straight_start_right = MarchButton(name='gait_tilted_path_straight_start_right', - text='Tilted Path straight start right', - callback=lambda: self.publish_gait( - 'gait_tilted_path_straight_start_right')) - - gait_tilted_path_straight_start_left = MarchButton(name='gait_tilted_path_straight_start_left', - text='Tilted Path straight start left', - callback=lambda: self.publish_gait( - 'gait_tilted_path_straight_start_left')) - - gait_tilted_path_first_start = MarchButton(name='gait_tilted_path_first_start', - text='Tilted Path side first start', - callback=lambda: self.publish_gait( - 'gait_tilted_path_first_start')) - - gait_tilted_path_second_start = MarchButton(name='gait_tilted_path_second_start', - text='Tilted Path side second start', - callback=lambda: self.publish_gait( - 'gait_tilted_path_second_start')) - - stop_button = MarchButton(name='gait_stop', image='/stop.png', - callback=lambda: self.publish_stop()) - pause_button = MarchButton(name='gait_pause', text='Pause', - callback=lambda: self.publish_pause()) - continue_button = MarchButton(name='gait_continue', text='Continue', - callback=lambda: self.publish_continue()) - - error_button = MarchButton(name='error', image='/error.png', - callback=lambda: self.publish_error()) - - # The button layout. - # Position in the array determines position on screen. - march_button_layout = [ - [home_sit_button, home_stand_button, gait_walk_button, gait_walk_small_button, stop_button], - [gait_sit_button, gait_stand_button, gait_single_step_normal_button, gait_single_step_small_button, - pause_button], - [gait_side_step_left_button, gait_side_step_right_button, gait_side_step_left_small_button, - gait_side_step_right_small_button, continue_button], - [gait_sofa_sit_button, gait_sofa_stand_button, gait_rough_terrain_high_step, - gait_rough_terrain_middle_steps, error_button], - [gait_stairs_up_button, gait_stairs_down_button, gait_ramp_door_slope_up, gait_ramp_door_slope_down, - gait_ramp_door_last_step], - [gait_tilted_path_straight_start_right, gait_tilted_path_straight_start_left, - gait_tilted_path_first_start, gait_tilted_path_second_start], - ] - - # Create the qt_layout from the button layout. - layout_builder = LayoutBuilder(march_button_layout) - qt_layout = layout_builder.build() - # Apply the qt_layout to the top level widget. - self._widget.frame.findChild(QWidget, 'content').setLayout(qt_layout) - - # Make the frame as tight as possible with spacing between the buttons. - qt_layout.setSpacing(15) - self._widget.frame.findChild(QWidget, 'content').adjustSize() - - # ROS publishers. - # It is important that you unregister them in the self.shutdown method. - self.instruction_gait_pub = rospy.Publisher( - '/march/input_device/instruction', GaitInstruction, queue_size=10) - - self.error_pub = rospy.Publisher('/march/error', Error, queue_size=10) - - self._ping = rospy.get_param('~ping_safety_node', True) - if self._ping: - self._alive_pub = rospy.Publisher( - '/march/input_device/alive', Time, queue_size=10) - self._alive_timer = rospy.Timer(rospy.Duration(0.05), self._timer_callback) - - def _timer_callback(self, event): - self._alive_pub.publish(event.current_real) - - def shutdown_plugin(self): - if self._ping: - self._alive_timer.shutdown() - self._alive_pub.unregister() - - def save_settings(self, plugin_settings, instance_settings): - # TODO save intrinsic configuration, usually using: - # instance_settings.set_value(k, v) - pass - - def restore_settings(self, plugin_settings, instance_settings): - # TODO restore intrinsic configuration, usually using: - # v = instance_settings.value(k) - pass - - def publish_gait(self, string): - rospy.logdebug('Mock Input Device published gait: ' + string) - self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), - GaitInstruction.GAIT, - string)) - - def publish_stop(self): - rospy.logdebug('Mock Input Device published stop') - self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), - GaitInstruction.STOP, - '')) - - def publish_continue(self): - rospy.logdebug('Mock Input Device published continue') - self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), - GaitInstruction.CONTINUE, '')) - - def publish_pause(self): - rospy.logdebug('Mock Input Device published pause') - self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), - GaitInstruction.PAUSE, - '')) - - def publish_error(self): - rospy.logdebug('Mock Input Device published error') - self.error_pub.publish(Error(std_msgs.msg.Header(stamp=rospy.Time.now()), - 'Fake error thrown by the develop input device.', Error.FATAL)) - - # def trigger_configuration(self): - # Comment in to signal that the plugin has a way to configure - # This will enable a setting button (the gear icon) - # in each dock widget title bar - # Usually used to open a modal configuration dialog diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_controller.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_controller.py new file mode 100644 index 0000000..22128e4 --- /dev/null +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_controller.py @@ -0,0 +1,59 @@ +import rospy +import std_msgs.msg + +from march_shared_resources.msg import Error, GaitInstruction + + +class InputDeviceController(object): + def __init__(self): + self.instruction_gait_pub = rospy.Publisher('/march/input_device/instruction', GaitInstruction, queue_size=10) + + self.error_pub = rospy.Publisher('/march/error', Error, queue_size=10) + self._ping = rospy.get_param('~ping_safety_node', True) + + if self._ping: + self._alive_pub = rospy.Publisher('/march/input_device/alive', std_msgs.msg.Time, queue_size=10) + self._alive_timer = rospy.Timer(rospy.Duration(0.05), self._timer_callback) + + def shutdown_plugin(self): + if self._ping: + self._alive_timer.shutdown() + self._alive_pub.unregister() + + def _timer_callback(self, event): + self._alive_pub.publish(event.current_real) + + def publish_increment_step_size(self): + rospy.logdebug('Mock Input Device published step size increment') + self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), + GaitInstruction.INCREMENT_STEP_SIZE, '')) + + def publish_decrement_step_size(self): + rospy.logdebug('Mock Input Device published step size decrement') + self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), + GaitInstruction.DECREMENT_STEP_SIZE, '')) + + def publish_gait(self, string): + rospy.logdebug('Mock Input Device published gait: ' + string) + self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), + GaitInstruction.GAIT, string)) + + def publish_stop(self): + rospy.logdebug('Mock Input Device published stop') + self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), + GaitInstruction.STOP, '')) + + def publish_continue(self): + rospy.logdebug('Mock Input Device published continue') + self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), + GaitInstruction.CONTINUE, '')) + + def publish_pause(self): + rospy.logdebug('Mock Input Device published pause') + self.instruction_gait_pub.publish(GaitInstruction(std_msgs.msg.Header(stamp=rospy.Time.now()), + GaitInstruction.PAUSE, '')) + + def publish_error(self): + rospy.logdebug('Mock Input Device published error') + self.error_pub.publish(Error(std_msgs.msg.Header(stamp=rospy.Time.now()), + 'Fake error thrown by the develop input device.', Error.FATAL)) diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py new file mode 100644 index 0000000..f422143 --- /dev/null +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py @@ -0,0 +1,301 @@ +import os + + +from python_qt_binding import loadUi +from python_qt_binding.QtCore import QSize +from python_qt_binding.QtWidgets import QGridLayout +from python_qt_binding.QtWidgets import QPushButton +from python_qt_binding.QtWidgets import QWidget +from qt_gui.plugin import Plugin +import rospkg + +from march_rqt_input_device.input_device_controller import InputDeviceController + + +class InputDevicePlugin(Plugin): + def __init__(self, context): + super(InputDevicePlugin, self).__init__(context) + self.controller = InputDeviceController() + + # region initialising the widget + self.setObjectName('InputDevicePlugin') + + # Create QWidget + self._widget = QWidget() + + # Get path to UI file which should be in the 'resource' folder of this package + ui_file = os.path.join(rospkg.RosPack().get_path('march_rqt_input_device'), 'resource', 'input_device.ui') + + # Extend the widget with all attributes and children from UI file + loadUi(ui_file, self._widget) + + # Give QObjects reasonable names + self._widget.setObjectName('Input Device') + + # Show _widget.windowTitle on left-top of each plugin (when it's set in _widget). (useful for multiple windows) + if context.serial_number() > 1: + self._widget.setWindowTitle('{0} ({1})'.format(self._widget.windowTitle(), context.serial_number())) + + # Add widget to the user interface + context.add_widget(self._widget) + + # Create buttons here + rocker_switch_increment = \ + self.create_button('rocker_switch_up', color_code='#239b56', + callback=lambda: self.controller.publish_increment_step_size()) + + rocker_switch_decrement = \ + self.create_button('rocker_switch_down', color_code='#239b56', + callback=lambda: self.controller.publish_decrement_step_size()) + + home_sit = \ + self.create_button('home_sit', image_path='/home_sit.png', + callback=lambda: self.controller.publish_gait('home_sit')) + + home_stand = \ + self.create_button('home_stand', image_path='/home_stand.png', + callback=lambda: self.controller.publish_gait('home_stand')) + + gait_sit = \ + self.create_button('gait_sit', image_path='/gait_sit.png', + callback=lambda: self.controller.publish_gait('gait_sit')) + + gait_walk = \ + self.create_button('gait_walk', image_path='/gait_walk_normal.png', + callback=lambda: self.controller.publish_gait('gait_walk')) + + gait_walk_small = \ + self.create_button('gait_walk_small', image_path='/gait_walk_small.png', + callback=lambda: self.controller.publish_gait('gait_walk_small')) + + gait_single_step_small = \ + self.create_button('gait_single_step_small', image_path='/gait_single_step_small.png', + callback=lambda: self.controller.publish_gait('gait_single_step_small')) + + gait_single_step_normal = \ + self.create_button('gait_single_step_normal', image_path='/gait_single_step_normal.png', + callback=lambda: self.controller.publish_gait('gait_single_step_normal')) + + gait_side_step_left = \ + self.create_button('gait_side_step_left', image_path='/gait_side_step_left.png', + callback=lambda: self.controller.publish_gait('gait_side_step_left')) + + gait_side_step_right = \ + self.create_button('gait_side_step_right', image_path='/gait_side_step_right.png', + callback=lambda: self.controller.publish_gait('gait_side_step_right')) + + gait_side_step_left_small = \ + self.create_button('gait_side_step_left_small', + callback=lambda: self.controller.publish_gait('gait_side_step_left_small')) + + gait_side_step_right_small = \ + self.create_button('gait_side_step_right_small', + callback=lambda: self.controller.publish_gait('gait_side_step_right_small')) + + gait_stand = \ + self.create_button('gait_stand', image_path='/gait_stand.png', + callback=lambda: self.controller.publish_gait('gait_stand')) + + gait_sofa_stand = \ + self.create_button('gait_sofa_stand', image_path='/gait_sofa_stand_up.png', + callback=lambda: self.controller.publish_gait('gait_sofa_stand')) + + gait_sofa_sit = \ + self.create_button('gait_sofa_sit', image_path='/gait_sofa_sit.png', + callback=lambda: self.controller.publish_gait('gait_sofa_sit')) + + gait_stairs_up = \ + self.create_button('gait_stairs_up', image_path='/gait_stairs_up.png', + callback=lambda: self.controller.publish_gait('gait_stairs_up')) + + gait_stairs_down = \ + self.create_button('gait_stairs_down', image_path='/gait_stairs_down.png', + callback=lambda: self.controller.publish_gait('gait_stairs_down')) + + gait_rough_terrain_high_step = \ + self.create_button('gait_rough_terrain_high_step', + callback=lambda: self.controller.publish_gait('gait_rough_terrain_high_step')) + + gait_rough_terrain_middle_steps = \ + self.create_button('gait_rough_terrain_middle_steps', + callback=lambda: self.controller.publish_gait('gait_rough_terrain_middle_steps')) + + gait_ramp_door_slope_up = \ + self.create_button('gait_ramp_door_slope_up', + callback=lambda: self.controller.publish_gait('gait_ramp_door_slope_up')) + + gait_ramp_door_slope_down = \ + self.create_button('gait_ramp_door_slope_down', + callback=lambda: self.controller.publish_gait('gait_ramp_door_slope_down')) + + gait_ramp_door_last_step = \ + self.create_button('gait_ramp_door_last_step', + callback=lambda: self.controller.publish_gait('gait_ramp_door_last_step')) + + gait_tilted_path_straight_start_right = \ + self.create_button('gait_tilted_path_straight_start_right', + callback=lambda: self.controller.publish_gait('gait_tilted_path_straight_start_right')) + + gait_tilted_path_straight_start_left = \ + self.create_button('gait_tilted_path_straight_start_left', + callback=lambda: self.controller.publish_gait('gait_tilted_path_straight_start_left')) + + gait_tilted_path_first_start = \ + self.create_button('gait_tilted_path_first_start', + callback=lambda: self.controller.publish_gait('gait_tilted_path_first_start')) + + gait_tilted_path_second_start = \ + self.create_button('gait_tilted_path_second_start', + callback=lambda: self.controller.publish_gait('gait_tilted_path_second_start')) + + stop_button = self.create_button('gait_stop', image_path='/stop.png', + callback=lambda: self.controller.publish_stop()) + + pause_button = self.create_button('gait_pause', + callback=lambda: self.controller.publish_pause()) + + continue_button = self.create_button('gait_continue', + callback=lambda: self.controller.publish_continue()) + + error_button = self.create_button('error', image_path='/error.png', + callback=lambda: self.controller.publish_error()) + + # The button layout. + # Position in the array determines position on screen. + march_button_layout = [ + + [home_sit, home_stand, gait_walk, gait_walk_small, stop_button, pause_button], + + [gait_sit, gait_stand, gait_single_step_normal, gait_single_step_small, continue_button, error_button], + + [gait_sofa_sit, gait_sofa_stand, gait_stairs_up, gait_stairs_down, rocker_switch_increment, + rocker_switch_decrement], + + [gait_side_step_left, gait_side_step_right, gait_side_step_left_small, gait_side_step_right_small], + + [gait_rough_terrain_high_step, gait_rough_terrain_middle_steps, gait_ramp_door_slope_up, + gait_ramp_door_slope_down, gait_ramp_door_last_step], + + [gait_tilted_path_straight_start_right, gait_tilted_path_straight_start_left, gait_tilted_path_first_start, + gait_tilted_path_second_start], + ] + + # Create the qt_layout from the button layout. + qt_layout = self.create_layout(march_button_layout) + + # Apply the qt_layout to the top level widget. + self._widget.frame.findChild(QWidget, 'content').setLayout(qt_layout) + + # Make the frame as tight as possible with spacing between the buttons. + qt_layout.setSpacing(15) + self._widget.frame.findChild(QWidget, 'content').adjustSize() + + @staticmethod + def create_button(text, callback=None, image_path=None, size=(125, 150), visible=True, color_code='#1F1E24'): + """Create a push button which the mock input device can register. + + :param text: + Possible name of the button + :param callback: + The callback to attach to the button when pressed + :param image_path: + The name of the image file + :param size: + Default size of the button + :param visible: + Turn button invisible on the gui + :param color_code: + Possible background color of the button + + :return: + A QPushButton object which contains the passed arguments + """ + qt_button = QPushButton() + + if image_path: + qt_button.setStyleSheet(create_image_button_css(get_image_path(image_path))) + else: + text = check_string(text) + qt_button.setStyleSheet(create_color_button_css(color_code)) + qt_button.setText(text) + + qt_button.setMinimumSize(QSize(*size)) + + if not visible: + qt_button.setVisible(False) + + if callback: + qt_button.clicked.connect(callback) + + return qt_button + + @staticmethod + def create_layout(layout_list): + """Create a button layout with a given list of buttons. + + :param layout_list: + A list which contains multiple list which represent a row with given items + + :return: + A populated QGridLayout object which contains the passed input buttons + """ + qt_button_layout = QGridLayout() + + for row in range(len(layout_list)): + for column in range(len(layout_list[row])): + user_input_object = layout_list[row][column] + qt_button_layout.addWidget(user_input_object, row, column, 1, 1) + + return qt_button_layout + + +def create_image_button_css(img_path): + """CSS of a button with a background-image.""" + css_base = """ + background: url() no-repeat center center; + background-color:#1F1E24; + color: #000000; + """ + return css_base.replace('', img_path) + + +def create_color_button_css(color_code): + """CSS of a button with a background-color.""" + css_base = """ + background-color: ; + color: #FFFFFF; + """ + return css_base.replace('', color_code) + + +def get_image_path(img_name): + """Create an absolute image path to an image.""" + return os.path.join( + rospkg.RosPack().get_path('march_rqt_input_device'), + 'resource', + 'img{0}'.format(img_name)) + + +def check_string(text): + """Split text into two lines if sentence is to long. + + :param text: + The text to split in half. + + :return: + New string which contains of an enter in the middle. + """ + text = text.replace('_', ' ') + split_text = text.split(' ') + if len(split_text) >= 3: + + new_string = '' + middle = len(split_text) / 2 + + new_string += ' '.join(split_text[:middle]) + new_string += '\n' + new_string += ' '.join(split_text[middle:]) + return new_string + + else: + return text From 9453efef56d361369431adb45512796955859773 Mon Sep 17 00:00:00 2001 From: marnixbrands <54286732+marnixbrands@users.noreply.github.com> Date: Tue, 28 Jan 2020 16:35:15 +0100 Subject: [PATCH 15/26] Added ending steps off tilted path to input device. (#19) --- .../src/march_rqt_input_device/input_device_view.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py index f422143..a430466 100644 --- a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py @@ -148,6 +148,14 @@ def __init__(self, context): self.create_button('gait_tilted_path_second_start', callback=lambda: self.controller.publish_gait('gait_tilted_path_second_start')) + gait_tilted_path_first_end = \ + self.create_button('gait_tilted_path_first_end', + callback=lambda: self.controller.publish_gait('gait_tilted_path_first_end')) + + gait_tilted_path_second_end = \ + self.create_button('gait_tilted_path_second_end', + callback=lambda: self.controller.publish_gait('gait_tilted_path_second_end')) + stop_button = self.create_button('gait_stop', image_path='/stop.png', callback=lambda: self.controller.publish_stop()) @@ -177,7 +185,7 @@ def __init__(self, context): gait_ramp_door_slope_down, gait_ramp_door_last_step], [gait_tilted_path_straight_start_right, gait_tilted_path_straight_start_left, gait_tilted_path_first_start, - gait_tilted_path_second_start], + gait_tilted_path_second_start, gait_tilted_path_first_end, gait_tilted_path_second_end], ] # Create the qt_layout from the button layout. From c0b3474fc578be777bb66b24db39ae0465993760 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Tue, 28 Jan 2020 19:37:04 +0100 Subject: [PATCH 16/26] Add codecov badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8fb7f8e..465cdd4 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Monitor RQt plugins for the March exoskeleton ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/project-march/monitor?include_prereleases) + [![codecov](https://codecov.io/gh/project-march/monitor/branch/master/graph/badge.svg)](https://codecov.io/gh/project-march/monitor) | Branch | Build Status | | ------ |:------------:| From 061dfcf1031089c1311fad6da958f2172298e586 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Thu, 30 Jan 2020 14:32:48 +0100 Subject: [PATCH 17/26] Split large test --- march_rqt_note_taker/test/entry_model_test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/march_rqt_note_taker/test/entry_model_test.py b/march_rqt_note_taker/test/entry_model_test.py index f49e50f..134baee 100644 --- a/march_rqt_note_taker/test/entry_model_test.py +++ b/march_rqt_note_taker/test/entry_model_test.py @@ -19,11 +19,15 @@ def test_horizontal_model_header(self): self.assertEqual(self.model.headerData(0, Qt.Horizontal, Qt.DisplayRole), 'Time') self.assertEqual(self.model.headerData(1, Qt.Horizontal, Qt.DisplayRole), 'Entry') - def test_insert_single_row(self): + def test_insert_single_row_count(self): entry = Entry('test', QDateTime.fromSecsSinceEpoch(5)) self.model.insert_row(entry) self.assertEqual(self.model.rowCount(), 1) + def test_insert_single_row(self): + entry = Entry('test', QDateTime.fromSecsSinceEpoch(5)) + self.model.insert_row(entry) + time_index = self.model.createIndex(0, 0) content_index = self.model.createIndex(0, 1) self.assertEqual(self.model.data(time_index), entry.time_string()) From 70c33f980fba7d295ea2f7fe58c0263272547da6 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Thu, 30 Jan 2020 16:55:29 +0100 Subject: [PATCH 18/26] Squashed commit of the following: commit cf689e99671b87ed9af1c967b075ff6c8922b7aa Author: Olav de Haas Date: Thu Jan 30 16:49:31 2020 +0100 Create separate project commit e7d4860cbe7eb9e1b640cf77197afefe53c5530f Author: Olav de Haas Date: Thu Jan 30 16:48:07 2020 +0100 Revert "Remove coverage script" This reverts commit 6d8a3994c9e33b1b4d0b6b0df11900f1b591eac6. commit 6d8a3994c9e33b1b4d0b6b0df11900f1b591eac6 Author: Olav de Haas Date: Thu Jan 30 16:40:06 2020 +0100 Remove coverage script commit cf23cbe7c1f5861a87979707018ce5b12d989bcf Author: Olav de Haas Date: Thu Jan 30 15:18:13 2020 +0100 Add default project commit 6a2e9af99262b6646087a0aa8bce38050395e31b Author: Olav de Haas Date: Thu Jan 30 14:51:58 2020 +0100 Apply recursive paths commit 3a860ebe0ca74eabd86ebd040e17735bd2e144a8 Author: Olav de Haas Date: Thu Jan 30 14:40:00 2020 +0100 Upload flags separately commit 746cd60cbaa3fb77458f67285ff3f099dc3a04a5 Author: Olav de Haas Date: Thu Jan 30 14:34:23 2020 +0100 Add codecov flags --- .coveragerc | 1 - .travis.yml | 2 +- README.md | 2 +- codecov.yml | 15 +++++++++++++++ coverage.sh | 1 - 5 files changed, 17 insertions(+), 4 deletions(-) diff --git a/.coveragerc b/.coveragerc index 78d956e..ffd0870 100644 --- a/.coveragerc +++ b/.coveragerc @@ -4,5 +4,4 @@ include = *march_rqt_input_device* *march_rqt_note_taker* omit = - *test* *__init__.py diff --git a/.travis.yml b/.travis.yml index 5a108b9..fb97bb2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,7 +26,7 @@ env: - CI_ENV=`bash <(curl -s https://codecov.io/env)` - DOCKER_RUN_OPTS='$CI_ENV -e CATKIN_TEST_COVERAGE=1 -e NOSE_COVER_INCLUSIVE=True -e NOSE_COVER_BRANCHES=True' - AFTER_INSTALL_TARGET_DEPENDENCIES='pip install coverage' - - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -Z' + - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -R src/monitor -F test && bash <(curl -s https://codecov.io/bash) -R src/monitor -F production' jobs: include: diff --git a/README.md b/README.md index 465cdd4..1f779ef 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Monitor RQt plugins for the March exoskeleton ![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/project-march/monitor?include_prereleases) - [![codecov](https://codecov.io/gh/project-march/monitor/branch/master/graph/badge.svg)](https://codecov.io/gh/project-march/monitor) + [![codecov](https://codecov.io/gh/project-march/monitor/branch/master/graph/badge.svg?flag=production)](https://codecov.io/gh/project-march/monitor) | Branch | Build Status | | ------ |:------------:| diff --git a/codecov.yml b/codecov.yml index 55f2b7b..ce69662 100644 --- a/codecov.yml +++ b/codecov.yml @@ -1,2 +1,17 @@ +coverage: + status: + project: + default: off + production: + target: auto + flags: + - production fixes: - "src/monitor/::" +flags: + production: + paths: + - "*/src/**/*" + test: + paths: + - "*/test/*" diff --git a/coverage.sh b/coverage.sh index 8521162..c2a2175 100755 --- a/coverage.sh +++ b/coverage.sh @@ -2,5 +2,4 @@ cd build/march_rqt_note_taker || return coverage xml --rcfile ../../src/monitor/.coveragerc -cp coverage.xml ../.. cd ../.. || return From 2d8cc9d4e2e5b998e48791fbe2c67338dd0535e6 Mon Sep 17 00:00:00 2001 From: Olav de Haas Date: Mon, 3 Feb 2020 11:05:52 +0100 Subject: [PATCH 19/26] Move imports in init to test --- march_rqt_note_taker/src/march_rqt_note_taker/__init__.py | 5 ----- march_rqt_note_taker/test/__init__.py | 5 +++++ 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/march_rqt_note_taker/src/march_rqt_note_taker/__init__.py b/march_rqt_note_taker/src/march_rqt_note_taker/__init__.py index 6f3d89f..e69de29 100644 --- a/march_rqt_note_taker/src/march_rqt_note_taker/__init__.py +++ b/march_rqt_note_taker/src/march_rqt_note_taker/__init__.py @@ -1,5 +0,0 @@ -from .entry import Entry -from .entry_model import EntryModel -from .filter_map import FilterMap -from .notes_plugin import NotesPlugin -from .notes_widget import NotesWidget diff --git a/march_rqt_note_taker/test/__init__.py b/march_rqt_note_taker/test/__init__.py index e69de29..dc5b546 100644 --- a/march_rqt_note_taker/test/__init__.py +++ b/march_rqt_note_taker/test/__init__.py @@ -0,0 +1,5 @@ +from march_rqt_note_taker.entry import Entry +from march_rqt_note_taker.entry_model import EntryModel +from march_rqt_note_taker.filter_map import FilterMap +from march_rqt_note_taker.notes_plugin import NotesPlugin +from march_rqt_note_taker.notes_widget import NotesWidget From 1f484b4f99f8da2b5c2ebdea4e9c7cf4fec5935d Mon Sep 17 00:00:00 2001 From: gaiavdh <54287750+gaiavdh@users.noreply.github.com> Date: Tue, 4 Feb 2020 16:51:51 +0100 Subject: [PATCH 20/26] Add new Rough Terrain middle steps buttons (#22) * Add buttons for three new separate middle steps to developer input device. * Fixed comma. --- .../input_device_view.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py index a430466..4bd58cf 100644 --- a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py @@ -120,6 +120,18 @@ def __init__(self, context): self.create_button('gait_rough_terrain_middle_steps', callback=lambda: self.controller.publish_gait('gait_rough_terrain_middle_steps')) + gait_rough_terrain_first_middle_step = \ + self.create_button('gait_rough_terrain_first_middle_step', + callback=lambda: self.controller.publish_gait('gait_rough_terrain_first_middle_step')) + + gait_rough_terrain_second_middle_step = \ + self.create_button('gait_rough_terrain_second_middle_step', + callback=lambda: self.controller.publish_gait('gait_rough_terrain_second_middle_step')) + + gait_rough_terrain_third_middle_step = \ + self.create_button('gait_rough_terrain_third_middle_step', + callback=lambda: self.controller.publish_gait('gait_rough_terrain_third_middle_step')) + gait_ramp_door_slope_up = \ self.create_button('gait_ramp_door_slope_up', callback=lambda: self.controller.publish_gait('gait_ramp_door_slope_up')) @@ -181,8 +193,10 @@ def __init__(self, context): [gait_side_step_left, gait_side_step_right, gait_side_step_left_small, gait_side_step_right_small], - [gait_rough_terrain_high_step, gait_rough_terrain_middle_steps, gait_ramp_door_slope_up, - gait_ramp_door_slope_down, gait_ramp_door_last_step], + [gait_rough_terrain_high_step, gait_rough_terrain_middle_steps, gait_rough_terrain_first_middle_step, + gait_rough_terrain_second_middle_step, gait_rough_terrain_third_middle_step], + + [gait_ramp_door_slope_up, gait_ramp_door_slope_down, gait_ramp_door_last_step], [gait_tilted_path_straight_start_right, gait_tilted_path_straight_start_left, gait_tilted_path_first_start, gait_tilted_path_second_start, gait_tilted_path_first_end, gait_tilted_path_second_end], From 4db488ef1b46af7ed0c5dd865208a50eeb71a113 Mon Sep 17 00:00:00 2001 From: marnixbrands <54286732+marnixbrands@users.noreply.github.com> Date: Fri, 7 Feb 2020 16:47:54 +0100 Subject: [PATCH 21/26] Add new Tilted Path gaits. (#23) Co-authored-by: gaiavdh <54287750+gaiavdh@users.noreply.github.com> --- .../input_device_view.py | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py index 4bd58cf..44e1e0a 100644 --- a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py @@ -144,13 +144,17 @@ def __init__(self, context): self.create_button('gait_ramp_door_last_step', callback=lambda: self.controller.publish_gait('gait_ramp_door_last_step')) - gait_tilted_path_straight_start_right = \ - self.create_button('gait_tilted_path_straight_start_right', - callback=lambda: self.controller.publish_gait('gait_tilted_path_straight_start_right')) + gait_tilted_path_straight_start = \ + self.create_button('gait_tilted_path_straight_start', + callback=lambda: self.controller.publish_gait('gait_tilted_path_straight_start')) - gait_tilted_path_straight_start_left = \ - self.create_button('gait_tilted_path_straight_start_left', - callback=lambda: self.controller.publish_gait('gait_tilted_path_straight_start_left')) + gait_tilted_path_single_step = \ + self.create_button('gait_tilted_path_single_step', + callback=lambda: self.controller.publish_gait('gait_tilted_path_single_step')) + + gait_tilted_path_straight_end = \ + self.create_button('gait_tilted_path_straight_end', + callback=lambda: self.controller.publish_gait('gait_tilted_path_straight_end')) gait_tilted_path_first_start = \ self.create_button('gait_tilted_path_first_start', @@ -198,8 +202,10 @@ def __init__(self, context): [gait_ramp_door_slope_up, gait_ramp_door_slope_down, gait_ramp_door_last_step], - [gait_tilted_path_straight_start_right, gait_tilted_path_straight_start_left, gait_tilted_path_first_start, - gait_tilted_path_second_start, gait_tilted_path_first_end, gait_tilted_path_second_end], + [gait_tilted_path_straight_start, gait_tilted_path_single_step, gait_tilted_path_straight_end], + + [gait_tilted_path_first_start, gait_tilted_path_second_start, gait_tilted_path_first_end, + gait_tilted_path_second_end], ] # Create the qt_layout from the button layout. From de049161b7e8be487f57f3c421d229e90691907d Mon Sep 17 00:00:00 2001 From: gaiavdh Date: Tue, 18 Feb 2020 10:27:32 +0100 Subject: [PATCH 22/26] Add walk_large button. --- .../src/march_rqt_input_device/input_device_view.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py index 44e1e0a..3e7275f 100644 --- a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py @@ -68,6 +68,10 @@ def __init__(self, context): self.create_button('gait_walk_small', image_path='/gait_walk_small.png', callback=lambda: self.controller.publish_gait('gait_walk_small')) + gait_walk_large = \ + self.create_button('gait_walk_large', + callback=lambda: self.controller.publish_gait('gait_walk_large')) + gait_single_step_small = \ self.create_button('gait_single_step_small', image_path='/gait_single_step_small.png', callback=lambda: self.controller.publish_gait('gait_single_step_small')) @@ -188,7 +192,7 @@ def __init__(self, context): # Position in the array determines position on screen. march_button_layout = [ - [home_sit, home_stand, gait_walk, gait_walk_small, stop_button, pause_button], + [home_sit, home_stand, gait_walk, gait_walk_small, gait_walk_large, stop_button, pause_button], [gait_sit, gait_stand, gait_single_step_normal, gait_single_step_small, continue_button, error_button], From fdbfc05cfe27e6aab575aacf5d9591056340afb5 Mon Sep 17 00:00:00 2001 From: gaiavdh Date: Tue, 3 Mar 2020 15:24:02 +0100 Subject: [PATCH 23/26] Added a single step for both stairs up and down to the input device. --- .../src/march_rqt_input_device/input_device_view.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py index 3e7275f..884b3df 100644 --- a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py @@ -116,6 +116,14 @@ def __init__(self, context): self.create_button('gait_stairs_down', image_path='/gait_stairs_down.png', callback=lambda: self.controller.publish_gait('gait_stairs_down')) + gait_stairs_up_single_step = \ + self.create_button('gait_stairs_up_single_step', + callback=lambda: self.controller.publish_gait('gait_stairs_up_single_step')) + + gait_stairs_down_single_step = \ + self.create_button('gait_stairs_down_single_step', + callback=lambda: self.controller.publish_gait('gait_stairs_down_single_step')) + gait_rough_terrain_high_step = \ self.create_button('gait_rough_terrain_high_step', callback=lambda: self.controller.publish_gait('gait_rough_terrain_high_step')) @@ -196,8 +204,9 @@ def __init__(self, context): [gait_sit, gait_stand, gait_single_step_normal, gait_single_step_small, continue_button, error_button], - [gait_sofa_sit, gait_sofa_stand, gait_stairs_up, gait_stairs_down, rocker_switch_increment, - rocker_switch_decrement], + [gait_sofa_sit, gait_sofa_stand, rocker_switch_increment, rocker_switch_decrement], + + [gait_stairs_up, gait_stairs_down, gait_stairs_up_single_step, gait_stairs_down_single_step], [gait_side_step_left, gait_side_step_right, gait_side_step_left_small, gait_side_step_right_small], From ced7f4226ca4e76b50b0b48d0825723aac157f69 Mon Sep 17 00:00:00 2001 From: gaiavdh <54287750+gaiavdh@users.noreply.github.com> Date: Tue, 3 Mar 2020 17:14:43 +0100 Subject: [PATCH 24/26] Added button for a new single step with flexed left knee at the of the gait (#26) Co-authored-by: marnixbrands <54286732+marnixbrands@users.noreply.github.com> --- .../src/march_rqt_input_device/input_device_view.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py index 3e7275f..f93608f 100644 --- a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py @@ -176,6 +176,10 @@ def __init__(self, context): self.create_button('gait_tilted_path_second_end', callback=lambda: self.controller.publish_gait('gait_tilted_path_second_end')) + gait_tilted_path_flexed_knee_step = \ + self.create_button('gait_tilted_path_flexed_knee_step', + callback=lambda: self.controller.publish_gait('gait_tilted_path_flexed_knee_step')) + stop_button = self.create_button('gait_stop', image_path='/stop.png', callback=lambda: self.controller.publish_stop()) @@ -206,7 +210,8 @@ def __init__(self, context): [gait_ramp_door_slope_up, gait_ramp_door_slope_down, gait_ramp_door_last_step], - [gait_tilted_path_straight_start, gait_tilted_path_single_step, gait_tilted_path_straight_end], + [gait_tilted_path_straight_start, gait_tilted_path_single_step, gait_tilted_path_straight_end, + gait_tilted_path_flexed_knee_step], [gait_tilted_path_first_start, gait_tilted_path_second_start, gait_tilted_path_first_end, gait_tilted_path_second_end], From 8528db90bc02ffcbc513cd00566e1ada95497d9f Mon Sep 17 00:00:00 2001 From: Roelemans <47626418+Roelemans@users.noreply.github.com> Date: Thu, 5 Mar 2020 12:37:48 +0100 Subject: [PATCH 25/26] Feature: log current gait (#25) * Fix time bug * Add inserting entry for current gait versions * Add msg dependencies * Add march_shared_resources rosinstall Co-authored-by: Roelemans <47626418+Roelemans@users.noreply.github.com> --- .rosinstall | 4 ++ .travis.yml | 1 + march_rqt_note_taker/CMakeLists.txt | 4 +- march_rqt_note_taker/package.xml | 3 ++ .../src/march_rqt_note_taker/entry.py | 4 +- .../src/march_rqt_note_taker/notes_plugin.py | 42 +++++++++++++++++-- 6 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 .rosinstall diff --git a/.rosinstall b/.rosinstall new file mode 100644 index 0000000..8edaa99 --- /dev/null +++ b/.rosinstall @@ -0,0 +1,4 @@ +- git: + local-name: march + uri: https://github.com/project-march/march + version: develop diff --git a/.travis.yml b/.travis.yml index fb97bb2..c58bdf9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,7 @@ env: - DOCKER_RUN_OPTS='$CI_ENV -e CATKIN_TEST_COVERAGE=1 -e NOSE_COVER_INCLUSIVE=True -e NOSE_COVER_BRANCHES=True' - AFTER_INSTALL_TARGET_DEPENDENCIES='pip install coverage' - AFTER_RUN_TARGET_TEST='cd "$target_ws" && ./src/monitor/coverage.sh && bash <(curl -s https://codecov.io/bash) -R src/monitor -F test && bash <(curl -s https://codecov.io/bash) -R src/monitor -F production' + - UPSTREAM_WORKSPACE='.rosinstall -march/march_data_collector -march/march_description -march/march_gain_scheduling -march/march_gait_scheduler -march/march_gait_selection -march/march_launch -march/march_safety -march/march_shared_classes -march/march_state_machine' jobs: include: diff --git a/march_rqt_note_taker/CMakeLists.txt b/march_rqt_note_taker/CMakeLists.txt index b7f3a56..f9d9b53 100644 --- a/march_rqt_note_taker/CMakeLists.txt +++ b/march_rqt_note_taker/CMakeLists.txt @@ -1,10 +1,10 @@ cmake_minimum_required(VERSION 2.8.3) project(march_rqt_note_taker) -find_package(catkin REQUIRED) +find_package(catkin REQUIRED COMPONENTS march_shared_resources std_msgs) catkin_python_setup() -catkin_package() +catkin_package(CATKIN_DEPENDS march_shared_resources std_msgs) install(FILES plugin.xml DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} diff --git a/march_rqt_note_taker/package.xml b/march_rqt_note_taker/package.xml index 0bb2d48..290fc7f 100644 --- a/march_rqt_note_taker/package.xml +++ b/march_rqt_note_taker/package.xml @@ -11,6 +11,9 @@ catkin + std_msgs + march_shared_resources + rospy rqt_gui rqt_gui_py diff --git a/march_rqt_note_taker/src/march_rqt_note_taker/entry.py b/march_rqt_note_taker/src/march_rqt_note_taker/entry.py index 47ff6f8..b7ee549 100644 --- a/march_rqt_note_taker/src/march_rqt_note_taker/entry.py +++ b/march_rqt_note_taker/src/march_rqt_note_taker/entry.py @@ -4,11 +4,11 @@ class Entry(QObject): - def __init__(self, content, date_time=QDateTime.currentDateTime(), is_error=False): + def __init__(self, content, date_time=None, is_error=False): super(Entry, self).__init__() self.content = content - self.date_time = date_time + self.date_time = QDateTime.currentDateTime() if date_time is None else date_time self.is_error = is_error @classmethod diff --git a/march_rqt_note_taker/src/march_rqt_note_taker/notes_plugin.py b/march_rqt_note_taker/src/march_rqt_note_taker/notes_plugin.py index 8d33453..496d40e 100644 --- a/march_rqt_note_taker/src/march_rqt_note_taker/notes_plugin.py +++ b/march_rqt_note_taker/src/march_rqt_note_taker/notes_plugin.py @@ -1,10 +1,15 @@ +import ast import os from qt_gui.plugin import Plugin from rosgraph_msgs.msg import Log import rospkg import rospy +from std_msgs.msg import String +from march_shared_resources.srv import Trigger + +from .entry import Entry from .entry_model import EntryModel from .filter_map import FilterMap from .notes_widget import NotesWidget @@ -24,14 +29,43 @@ def __init__(self, context): self._filter_map = FilterMap() self._filter_map.add_filter(lambda l: l.level >= Log.ERROR) self._filter_map.add_filter_info_level(lambda l: l.msg == 'March is fully operational') - self._subscriber = rospy.Subscriber('/rosout_agg', - Log, - self._rosout_cb) + + self._subscribers = [] + self._subscribers.append(rospy.Subscriber('/rosout_agg', + Log, + self._rosout_cb)) + self._subscribers.append(rospy.Subscriber('/march/gait/current', + String, + self._current_gait_cb)) + + self._get_gait_version_map = rospy.ServiceProxy('/march/gait_selection/get_version_map', + Trigger) def shutdown_plugin(self): - self._subscriber.unregister() + for subscriber in self._subscribers: + subscriber.unregister() def _rosout_cb(self, log_msg): mapped_msg = self._filter_map(log_msg) if mapped_msg: self._model.insert_log_msg(mapped_msg) + + def _current_gait_cb(self, current_gait): + """ + Inserts an entry, which logs the current gait version used. + + :type current_gait: String + :param current_gait: Current gait goal being executed + """ + try: + gait_version_map = ast.literal_eval(self._get_gait_version_map().message) + + message = 'Starting gait {0}: {1}'.format(current_gait.data, + str(gait_version_map[current_gait.data])) + self._model.insert_row(Entry(message)) + except rospy.ServiceException as e: + rospy.logwarn('Failed to contact gait selection node for gait versions: {0}'.format(e)) + except KeyError: + pass + except ValueError as e: + rospy.logerr('Failed to parse gait version map: {0}'.format(e)) From df25a21a921450bd5c9a42320ab0e124b37dcc20 Mon Sep 17 00:00:00 2001 From: marnixbrands Date: Tue, 10 Mar 2020 11:33:11 +0100 Subject: [PATCH 26/26] Changed the tilted path buttons in IPD, now two rows of straight tilted path gaits (for both orientations of the tilted path) --- .../input_device_view.py | 49 +++++++++++++------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py index 2109b56..ccf4c61 100644 --- a/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py +++ b/march_rqt_input_device/src/march_rqt_input_device/input_device_view.py @@ -156,17 +156,37 @@ def __init__(self, context): self.create_button('gait_ramp_door_last_step', callback=lambda: self.controller.publish_gait('gait_ramp_door_last_step')) - gait_tilted_path_straight_start = \ - self.create_button('gait_tilted_path_straight_start', - callback=lambda: self.controller.publish_gait('gait_tilted_path_straight_start')) + gait_tilted_path_left_straight_start = \ + self.create_button('gait_tilted_path_left_straight_start', + callback=lambda: self.controller.publish_gait('gait_tilted_path_left_straight_start')) - gait_tilted_path_single_step = \ - self.create_button('gait_tilted_path_single_step', - callback=lambda: self.controller.publish_gait('gait_tilted_path_single_step')) + gait_tilted_path_left_single_step = \ + self.create_button('gait_tilted_path_left_single_step', + callback=lambda: self.controller.publish_gait('gait_tilted_path_left_single_step')) - gait_tilted_path_straight_end = \ - self.create_button('gait_tilted_path_straight_end', - callback=lambda: self.controller.publish_gait('gait_tilted_path_straight_end')) + gait_tilted_path_left_straight_end = \ + self.create_button('gait_tilted_path_left_straight_end', + callback=lambda: self.controller.publish_gait('gait_tilted_path_left_straight_end')) + + gait_tilted_path_left_flexed_knee_step = \ + self.create_button('gait_tilted_path_left_flexed_knee_step', + callback=lambda: self.controller.publish_gait('gait_tilted_path_left_flexed_knee_step')) + + gait_tilted_path_right_straight_start = \ + self.create_button('gait_tilted_path_right_straight_start', + callback=lambda: self.controller.publish_gait('gait_tilted_path_right_straight_start')) + + gait_tilted_path_right_single_step = \ + self.create_button('gait_tilted_path_right_single_step', + callback=lambda: self.controller.publish_gait('gait_tilted_path_right_single_step')) + + gait_tilted_path_right_straight_end = \ + self.create_button('gait_tilted_path_right_straight_end', + callback=lambda: self.controller.publish_gait('gait_tilted_path_right_straight_end')) + + gait_tilted_path_right_flexed_knee_step = \ + self.create_button('gait_tilted_path_right_flexed_knee_step', + callback=lambda: self.controller.publish_gait('gait_tilted_path_right_flexed_knee_step')) gait_tilted_path_first_start = \ self.create_button('gait_tilted_path_first_start', @@ -184,10 +204,6 @@ def __init__(self, context): self.create_button('gait_tilted_path_second_end', callback=lambda: self.controller.publish_gait('gait_tilted_path_second_end')) - gait_tilted_path_flexed_knee_step = \ - self.create_button('gait_tilted_path_flexed_knee_step', - callback=lambda: self.controller.publish_gait('gait_tilted_path_flexed_knee_step')) - stop_button = self.create_button('gait_stop', image_path='/stop.png', callback=lambda: self.controller.publish_stop()) @@ -219,8 +235,11 @@ def __init__(self, context): [gait_ramp_door_slope_up, gait_ramp_door_slope_down, gait_ramp_door_last_step], - [gait_tilted_path_straight_start, gait_tilted_path_single_step, gait_tilted_path_straight_end, - gait_tilted_path_flexed_knee_step], + [gait_tilted_path_left_straight_start, gait_tilted_path_left_single_step, + gait_tilted_path_left_straight_end, gait_tilted_path_left_flexed_knee_step], + + [gait_tilted_path_right_straight_start, gait_tilted_path_right_single_step, + gait_tilted_path_right_straight_end, gait_tilted_path_right_flexed_knee_step], [gait_tilted_path_first_start, gait_tilted_path_second_start, gait_tilted_path_first_end, gait_tilted_path_second_end],