Skip to content

Commit 9ad13b3

Browse files
committedNov 25, 2023
Initial Commit
0 parents  commit 9ad13b3

15 files changed

+769
-0
lines changed
 

‎.gitignore

+272
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
### JetBrains template
2+
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
3+
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
4+
5+
# User-specific stuff
6+
.idea/**/workspace.xml
7+
.idea/**/tasks.xml
8+
.idea/**/usage.statistics.xml
9+
.idea/**/dictionaries
10+
.idea/**/shelf
11+
12+
# AWS User-specific
13+
.idea/**/aws.xml
14+
15+
# Generated files
16+
.idea/**/contentModel.xml
17+
18+
# Sensitive or high-churn files
19+
.idea/**/dataSources/
20+
.idea/**/dataSources.ids
21+
.idea/**/dataSources.local.xml
22+
.idea/**/sqlDataSources.xml
23+
.idea/**/dynamic.xml
24+
.idea/**/uiDesigner.xml
25+
.idea/**/dbnavigator.xml
26+
27+
# Gradle
28+
.idea/**/gradle.xml
29+
.idea/**/libraries
30+
31+
# Gradle and Maven with auto-import
32+
# When using Gradle or Maven with auto-import, you should exclude module files,
33+
# since they will be recreated, and may cause churn. Uncomment if using
34+
# auto-import.
35+
# .idea/artifacts
36+
# .idea/compiler.xml
37+
# .idea/jarRepositories.xml
38+
# .idea/modules.xml
39+
# .idea/*.iml
40+
# .idea/modules
41+
# *.iml
42+
# *.ipr
43+
44+
# CMake
45+
cmake-build-*/
46+
47+
# Mongo Explorer plugin
48+
.idea/**/mongoSettings.xml
49+
50+
# File-based project format
51+
*.iws
52+
53+
# IntelliJ
54+
out/
55+
56+
# mpeltonen/sbt-idea plugin
57+
.idea_modules/
58+
59+
# JIRA plugin
60+
atlassian-ide-plugin.xml
61+
62+
# Cursive Clojure plugin
63+
.idea/replstate.xml
64+
65+
# SonarLint plugin
66+
.idea/sonarlint/
67+
68+
# Crashlytics plugin (for Android Studio and IntelliJ)
69+
com_crashlytics_export_strings.xml
70+
crashlytics.properties
71+
crashlytics-build.properties
72+
fabric.properties
73+
74+
# Editor-based Rest Client
75+
.idea/httpRequests
76+
77+
# Android studio 3.1+ serialized cache file
78+
.idea/caches/build_file_checksums.ser
79+
80+
### ROS2 template
81+
install/
82+
log/
83+
build/
84+
85+
# Ignore generated docs
86+
*.dox
87+
*.wikidoc
88+
89+
# eclipse stuff
90+
.project
91+
.cproject
92+
93+
# qcreator stuff
94+
CMakeLists.txt.user
95+
96+
srv/_*.py
97+
*.pcd
98+
*.pyc
99+
qtcreator-*
100+
*.user
101+
102+
*~
103+
104+
# Emacs
105+
.#*
106+
107+
# Colcon custom files
108+
COLCON_IGNORE
109+
AMENT_IGNORE
110+
111+
### Python template
112+
# Byte-compiled / optimized / DLL files
113+
__pycache__/
114+
*.py[cod]
115+
*$py.class
116+
117+
# C extensions
118+
*.so
119+
120+
# Distribution / packaging
121+
.Python
122+
build/
123+
develop-eggs/
124+
dist/
125+
downloads/
126+
eggs/
127+
.eggs/
128+
lib/
129+
lib64/
130+
parts/
131+
sdist/
132+
var/
133+
wheels/
134+
share/python-wheels/
135+
*.egg-info/
136+
.installed.cfg
137+
*.egg
138+
MANIFEST
139+
140+
# PyInstaller
141+
# Usually these files are written by a python script from a template
142+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
143+
*.manifest
144+
*.spec
145+
146+
# Installer logs
147+
pip-log.txt
148+
pip-delete-this-directory.txt
149+
150+
# Unit test / coverage reports
151+
htmlcov/
152+
.tox/
153+
.nox/
154+
.coverage
155+
.coverage.*
156+
.cache
157+
nosetests.xml
158+
coverage.xml
159+
*.cover
160+
*.py,cover
161+
.hypothesis/
162+
.pytest_cache/
163+
cover/
164+
165+
# Translations
166+
*.mo
167+
*.pot
168+
169+
# Django stuff:
170+
*.log
171+
local_settings.py
172+
db.sqlite3
173+
db.sqlite3-journal
174+
175+
# Flask stuff:
176+
instance/
177+
.webassets-cache
178+
179+
# Scrapy stuff:
180+
.scrapy
181+
182+
# Sphinx documentation
183+
docs/_build/
184+
185+
# PyBuilder
186+
.pybuilder/
187+
target/
188+
189+
# Jupyter Notebook
190+
.ipynb_checkpoints
191+
192+
# IPython
193+
profile_default/
194+
ipython_config.py
195+
196+
# pyenv
197+
# For a library or package, you might want to ignore these files since the code is
198+
# intended to run in multiple environments; otherwise, check them in:
199+
# .python-version
200+
201+
# pipenv
202+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
203+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
204+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
205+
# install all needed dependencies.
206+
#Pipfile.lock
207+
208+
# poetry
209+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
210+
# This is especially recommended for binary packages to ensure reproducibility, and is more
211+
# commonly ignored for libraries.
212+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
213+
#poetry.lock
214+
215+
# pdm
216+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
217+
#pdm.lock
218+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
219+
# in version control.
220+
# https://pdm.fming.dev/#use-with-ide
221+
.pdm.toml
222+
223+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
224+
__pypackages__/
225+
226+
# Celery stuff
227+
celerybeat-schedule
228+
celerybeat.pid
229+
230+
# SageMath parsed files
231+
*.sage.py
232+
233+
# Environments
234+
.env
235+
.venv
236+
env/
237+
venv/
238+
ENV/
239+
env.bak/
240+
venv.bak/
241+
242+
# Spyder project settings
243+
.spyderproject
244+
.spyproject
245+
246+
# Rope project settings
247+
.ropeproject
248+
249+
# mkdocs documentation
250+
/site
251+
252+
# mypy
253+
.mypy_cache/
254+
.dmypy.json
255+
dmypy.json
256+
257+
# Pyre type checker
258+
.pyre/
259+
260+
# pytype static type analyzer
261+
.pytype/
262+
263+
# Cython debug symbols
264+
cython_debug/
265+
266+
# PyCharm
267+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
268+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
269+
# and can be added to the global gitignore or merged into this file. For a more nuclear
270+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
271+
#.idea/
272+

‎.idea/.gitignore

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/avr_vmc_2023_action_bridge.iml

+13
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/inspectionProfiles/Project_Default.xml

+104
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/inspectionProfiles/profiles_settings.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/misc.xml

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/modules.xml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎.idea/vcs.xml

+6
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎LICENSE

+165
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
GNU LESSER GENERAL PUBLIC LICENSE
2+
Version 3, 29 June 2007
3+
4+
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
5+
Everyone is permitted to copy and distribute verbatim copies
6+
of this license document, but changing it is not allowed.
7+
8+
9+
This version of the GNU Lesser General Public License incorporates
10+
the terms and conditions of version 3 of the GNU General Public
11+
License, supplemented by the additional permissions listed below.
12+
13+
0. Additional Definitions.
14+
15+
As used herein, "this License" refers to version 3 of the GNU Lesser
16+
General Public License, and the "GNU GPL" refers to version 3 of the GNU
17+
General Public License.
18+
19+
"The Library" refers to a covered work governed by this License,
20+
other than an Application or a Combined Work as defined below.
21+
22+
An "Application" is any work that makes use of an interface provided
23+
by the Library, but which is not otherwise based on the Library.
24+
Defining a subclass of a class defined by the Library is deemed a mode
25+
of using an interface provided by the Library.
26+
27+
A "Combined Work" is a work produced by combining or linking an
28+
Application with the Library. The particular version of the Library
29+
with which the Combined Work was made is also called the "Linked
30+
Version".
31+
32+
The "Minimal Corresponding Source" for a Combined Work means the
33+
Corresponding Source for the Combined Work, excluding any source code
34+
for portions of the Combined Work that, considered in isolation, are
35+
based on the Application, and not on the Linked Version.
36+
37+
The "Corresponding Application Code" for a Combined Work means the
38+
object code and/or source code for the Application, including any data
39+
and utility programs needed for reproducing the Combined Work from the
40+
Application, but excluding the System Libraries of the Combined Work.
41+
42+
1. Exception to Section 3 of the GNU GPL.
43+
44+
You may convey a covered work under sections 3 and 4 of this License
45+
without being bound by section 3 of the GNU GPL.
46+
47+
2. Conveying Modified Versions.
48+
49+
If you modify a copy of the Library, and, in your modifications, a
50+
facility refers to a function or data to be supplied by an Application
51+
that uses the facility (other than as an argument passed when the
52+
facility is invoked), then you may convey a copy of the modified
53+
version:
54+
55+
a) under this License, provided that you make a good faith effort to
56+
ensure that, in the event an Application does not supply the
57+
function or data, the facility still operates, and performs
58+
whatever part of its purpose remains meaningful, or
59+
60+
b) under the GNU GPL, with none of the additional permissions of
61+
this License applicable to that copy.
62+
63+
3. Object Code Incorporating Material from Library Header Files.
64+
65+
The object code form of an Application may incorporate material from
66+
a header file that is part of the Library. You may convey such object
67+
code under terms of your choice, provided that, if the incorporated
68+
material is not limited to numerical parameters, data structure
69+
layouts and accessors, or small macros, inline functions and templates
70+
(ten or fewer lines in length), you do both of the following:
71+
72+
a) Give prominent notice with each copy of the object code that the
73+
Library is used in it and that the Library and its use are
74+
covered by this License.
75+
76+
b) Accompany the object code with a copy of the GNU GPL and this license
77+
document.
78+
79+
4. Combined Works.
80+
81+
You may convey a Combined Work under terms of your choice that,
82+
taken together, effectively do not restrict modification of the
83+
portions of the Library contained in the Combined Work and reverse
84+
engineering for debugging such modifications, if you also do each of
85+
the following:
86+
87+
a) Give prominent notice with each copy of the Combined Work that
88+
the Library is used in it and that the Library and its use are
89+
covered by this License.
90+
91+
b) Accompany the Combined Work with a copy of the GNU GPL and this license
92+
document.
93+
94+
c) For a Combined Work that displays copyright notices during
95+
execution, include the copyright notice for the Library among
96+
these notices, as well as a reference directing the user to the
97+
copies of the GNU GPL and this license document.
98+
99+
d) Do one of the following:
100+
101+
0) Convey the Minimal Corresponding Source under the terms of this
102+
License, and the Corresponding Application Code in a form
103+
suitable for, and under terms that permit, the user to
104+
recombine or relink the Application with a modified version of
105+
the Linked Version to produce a modified Combined Work, in the
106+
manner specified by section 6 of the GNU GPL for conveying
107+
Corresponding Source.
108+
109+
1) Use a suitable shared library mechanism for linking with the
110+
Library. A suitable mechanism is one that (a) uses at run time
111+
a copy of the Library already present on the user's computer
112+
system, and (b) will operate properly with a modified version
113+
of the Library that is interface-compatible with the Linked
114+
Version.
115+
116+
e) Provide Installation Information, but only if you would otherwise
117+
be required to provide such information under section 6 of the
118+
GNU GPL, and only to the extent that such information is
119+
necessary to install and execute a modified version of the
120+
Combined Work produced by recombining or relinking the
121+
Application with a modified version of the Linked Version. (If
122+
you use option 4d0, the Installation Information must accompany
123+
the Minimal Corresponding Source and Corresponding Application
124+
Code. If you use option 4d1, you must provide the Installation
125+
Information in the manner specified by section 6 of the GNU GPL
126+
for conveying Corresponding Source.)
127+
128+
5. Combined Libraries.
129+
130+
You may place library facilities that are a work based on the
131+
Library side by side in a single library together with other library
132+
facilities that are not Applications and are not covered by this
133+
License, and convey such a combined library under terms of your
134+
choice, if you do both of the following:
135+
136+
a) Accompany the combined library with a copy of the same work based
137+
on the Library, uncombined with any other library facilities,
138+
conveyed under the terms of this License.
139+
140+
b) Give prominent notice with the combined library that part of it
141+
is a work based on the Library, and explaining where to find the
142+
accompanying uncombined form of the same work.
143+
144+
6. Revised Versions of the GNU Lesser General Public License.
145+
146+
The Free Software Foundation may publish revised and/or new versions
147+
of the GNU Lesser General Public License from time to time. Such new
148+
versions will be similar in spirit to the present version, but may
149+
differ in detail to address new problems or concerns.
150+
151+
Each version is given a distinguishing version number. If the
152+
Library as you received it specifies that a certain numbered version
153+
of the GNU Lesser General Public License "or any later version"
154+
applies to it, you have the option of following the terms and
155+
conditions either of that published version or of any later version
156+
published by the Free Software Foundation. If the Library as you
157+
received it does not specify a version number of the GNU Lesser
158+
General Public License, you may choose any version of the GNU Lesser
159+
General Public License ever published by the Free Software Foundation.
160+
161+
If the Library as you received it specifies that a proxy can decide
162+
whether future versions of the GNU Lesser General Public License shall
163+
apply, that proxy's public statement of acceptance of any version is
164+
permanent authorization for you to choose that version for the
165+
Library.

‎avr_vmc_2023_action_bridge/__init__.py

Whitespace-only changes.
+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import json
2+
from typing import List, Tuple, Any
3+
4+
import rclpy
5+
from rclpy import Future
6+
from rclpy.action import ActionClient
7+
from rclpy.node import Node
8+
9+
from avr_vmc_2023_action_bridge_interfaces.srv import Goal, Cancel
10+
from avr_vmc_2023_action_bridge_interfaces.msg import Feedback, Result
11+
from avr_vmc_2023_auton_drop_interfaces.action import AutonDrop
12+
13+
14+
class ActionBridgeNode(Node):
15+
def __init__(self) -> None:
16+
super().__init__('avr_vmc_2023_action_bridge', namespace='action_bridge')
17+
18+
self.goal_service = self.create_service(
19+
Goal,
20+
'goal',
21+
self.send_goal
22+
)
23+
self.cancel_service = self.create_service(
24+
Cancel,
25+
'cancel',
26+
self.cancel
27+
)
28+
29+
self.feedback_publisher = self.create_publisher(
30+
Feedback,
31+
'feedback',
32+
10
33+
)
34+
self.result_publisher = self.create_publisher(
35+
Result,
36+
'result',
37+
10
38+
)
39+
40+
self.action_clients: List[Tuple[str, type, ActionClient]] = []
41+
# Setup actions
42+
self.action_clients.append(
43+
(
44+
'/auton_drop/trigger',
45+
AutonDrop,
46+
ActionClient(
47+
self,
48+
AutonDrop,
49+
'/auton_drop/trigger'
50+
)
51+
)
52+
)
53+
54+
for client_info in self.action_clients:
55+
# noinspection PyProtectedMember
56+
self.get_logger().info(f'Waiting for action: {client_info[0]}')
57+
success = client_info[2].wait_for_server(timeout_sec=10)
58+
if not success:
59+
# noinspection PyProtectedMember
60+
self.get_logger().warning(f'Could not find action: {client_info[0]}')
61+
62+
self.goal_futures: List[Future | None] = [None] * len(self.action_clients)
63+
64+
def send_goal(self, request: Goal.Request, response: Goal.Response) -> Goal.Response:
65+
if 0 <= request.id < len(self.action_clients):
66+
client_info = self.action_clients[request.id]
67+
try:
68+
data = json.loads(request.data)
69+
except json.JSONDecodeError:
70+
self.get_logger().warning(f'Failed to parse goal message for action: {client_info[1]}')
71+
self.get_logger().warning(f'Data: {request.data}')
72+
else:
73+
self.get_logger().debug(f'Calling action \'{client_info[0]}\' with data: {data}')
74+
# noinspection PyUnresolvedReferences
75+
goal = client_info[1].Goal(data)
76+
self.goal_futures[request.id] = client_info[2].send_goal_async(
77+
goal,
78+
feedback_callback=lambda msg: self._send_feedback(request.id, msg)
79+
)
80+
self.goal_futures[request.id].add_done_callback(lambda future: self._send_result(request.id, future))
81+
response.success = True
82+
return response
83+
84+
def cancel(self, request: Cancel.Request, response: Cancel.Response) -> Cancel.Response:
85+
if 0 <= request.id < len(self.action_clients):
86+
client_name = self.action_clients[request.id][0]
87+
if self.goal_futures[request.id] is not None:
88+
self.get_logger().debug(f'Canceling action \'{client_name}\'')
89+
self.goal_futures[request.id].cancel()
90+
response.success = True
91+
return response
92+
93+
def _send_feedback(self, action_id: int, msg: Any) -> None:
94+
if 0 <= action_id < len(self.action_clients):
95+
client_name = self.action_clients[action_id][0]
96+
self.get_logger().debug(f'Sending feedback for action: {client_name}')
97+
98+
feedback = Feedback()
99+
feedback.id = action_id
100+
feedback.data = self._convert_msg_to_json(msg)
101+
102+
self.feedback_publisher.publish(feedback)
103+
104+
def _send_result(self, action_id: int, future: Future) -> None:
105+
if 0 <= action_id < len(self.action_clients):
106+
client_name = self.action_clients[action_id][0]
107+
self.get_logger().debug(f'Action \'{client_name}\' has finished')
108+
109+
if not future.cancelled():
110+
result = Result()
111+
result.id = action_id
112+
result.data = self._convert_msg_to_json(future.result())
113+
114+
self.result_publisher.publish(result)
115+
116+
@staticmethod
117+
def _convert_msg_to_json(msg: Any) -> str:
118+
d = {}
119+
for slot in msg.__slots__:
120+
value = getattr(msg, slot)
121+
d[slot] = value
122+
return json.dumps(d)
123+
124+
125+
def main() -> None:
126+
rclpy.init()
127+
node = ActionBridgeNode()
128+
executor = rclpy.executors.MultiThreadedExecutor()
129+
rclpy.spin(node, executor)
130+
131+
132+
if __name__ == '__main__':
133+
main()

‎package.xml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0"?>
2+
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
3+
<package format="3">
4+
<name>avr_vmc_2023_action_bridge</name>
5+
<version>0.0.0</version>
6+
<description></description>
7+
<maintainer email="hunterbaker@me.com">Hunter Baker</maintainer>
8+
<license>LGPL-3.0-only</license>
9+
10+
<test_depend>ament_copyright</test_depend>
11+
<test_depend>ament_flake8</test_depend>
12+
<test_depend>ament_pep257</test_depend>
13+
<test_depend>python3-pytest</test_depend>
14+
15+
<export>
16+
<build_type>ament_python</build_type>
17+
</export>
18+
</package>

‎resource/avr_vmc_2023_action_bridge

Whitespace-only changes.

‎setup.cfg

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[develop]
2+
script_dir=$base/lib/avr_vmc_2023_action_bridge
3+
[install]
4+
install_scripts=$base/lib/avr_vmc_2023_action_bridge

‎setup.py

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from setuptools import find_packages, setup
2+
3+
package_name = 'avr_vmc_2023_action_bridge'
4+
5+
setup(
6+
name=package_name,
7+
version='0.0.0',
8+
packages=find_packages(exclude=['test']),
9+
data_files=[
10+
('share/ament_index/resource_index/packages', ['resource/' + package_name]),
11+
('share/' + package_name, ['package.xml']),
12+
],
13+
install_requires=['setuptools'],
14+
zip_safe=True,
15+
maintainer='Hunter Baker',
16+
maintainer_email='hunterbaker@me.com',
17+
description='',
18+
license='LGPL-3.0-only',
19+
tests_require=['pytest'],
20+
entry_points={
21+
'console_scripts': [
22+
'action_bridge_node = avr_vmc_2023_action_bridge.action_bridge:main'
23+
],
24+
},
25+
)

0 commit comments

Comments
 (0)
Please sign in to comment.