AS: creating packages
This commit is contained in:
0
workspace/src/joint_info/joint_info/__init__.py
Normal file
0
workspace/src/joint_info/joint_info/__init__.py
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
102
workspace/src/joint_info/joint_info/osc_joint_states_pub.py
Executable file
102
workspace/src/joint_info/joint_info/osc_joint_states_pub.py
Executable file
@@ -0,0 +1,102 @@
|
||||
import rclpy
|
||||
from rclpy.node import Node
|
||||
from sensor_msgs.msg import JointState
|
||||
from osc4py3.as_eventloop import *
|
||||
from osc4py3 import oscbuildparse
|
||||
|
||||
class JointStateOSC(Node):
|
||||
def __init__(self):
|
||||
super().__init__('joint_states_osc')
|
||||
|
||||
# Create a ROS 2 subscriber to /joint_states topic
|
||||
self.subscription = self.create_subscription(
|
||||
JointState,
|
||||
'/joint_states',
|
||||
self.joint_states_callback,
|
||||
1 # Queue size
|
||||
)
|
||||
|
||||
# Open Sound Control (OSC) Client settings
|
||||
self.osc_ip = "127.0.0.1" # Replace with the target IP
|
||||
self.osc_port = 8000 # Replace with the target port
|
||||
|
||||
# Start the OSC system
|
||||
osc_startup()
|
||||
|
||||
# Make client channels to send packets
|
||||
osc_udp_client(self.osc_ip, self.osc_port, "osc_client")
|
||||
|
||||
def joint_states_callback(self, msg):
|
||||
"""Callback function to handle incoming joint states."""
|
||||
header = msg.header
|
||||
joint_names = msg.name
|
||||
joint_positions = msg.position
|
||||
joint_velocity = msg.velocity
|
||||
joint_effort = msg.effort
|
||||
|
||||
joint_names_str = "\n- ".join(joint_names)
|
||||
joint_positions_str = "\n- ".join(map(str, joint_positions))
|
||||
joint_velocity_str = "\n- ".join(map(str, joint_velocity))
|
||||
joint_effort_str = "\n- ".join(map(str, joint_effort))
|
||||
|
||||
info = f"""
|
||||
---
|
||||
header:
|
||||
stamp:
|
||||
sec: {header.stamp.sec}
|
||||
nanosec: {header.stamp.nanosec}
|
||||
name:
|
||||
- {joint_names_str}
|
||||
position:
|
||||
- {joint_positions_str}
|
||||
velocity:
|
||||
- {joint_velocity_str}
|
||||
effort:
|
||||
- {joint_effort_str}
|
||||
---"""
|
||||
|
||||
# Send the info message
|
||||
msg_info = oscbuildparse.OSCMessage("/joint_states", None, [info])
|
||||
msg_name = oscbuildparse.OSCMessage("/joint_states/name", None, [i for i in joint_names])
|
||||
msg_position = oscbuildparse.OSCMessage("/joint_states/position", None, [i for i in joint_positions])
|
||||
msg_velocity = oscbuildparse.OSCMessage("/joint_states/velocity", None, [i for i in joint_velocity])
|
||||
msg_effort = oscbuildparse.OSCMessage("/joint_states/effort", None, [i for i in joint_effort])
|
||||
|
||||
bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY, [msg_info, msg_name, msg_position, msg_velocity, msg_effort])
|
||||
|
||||
osc_send(bun, "osc_client")
|
||||
osc_process()
|
||||
#print(f"Publishing: {info}")
|
||||
|
||||
|
||||
'''
|
||||
# Send each joint state as an OSC message
|
||||
for i, name in enumerate(joint_names):
|
||||
#msg_sec = oscbuildparse.OSCMessage(f"/joint_states/header/sec", None, [header.stamp.sec])
|
||||
#msg_nanosec = oscbuildparse.OSCMessage(f"/joint_states/header/nanosec", None, [header.stamp.nanosec])
|
||||
msg_position = oscbuildparse.OSCMessage(f"/joint_states/{name}/position", None, [joint_positions[i]])
|
||||
msg_velocity = oscbuildparse.OSCMessage(f"/joint_states/{name}/velocity", None, [joint_velocity[i]])
|
||||
msg_effort = oscbuildparse.OSCMessage(f"/joint_states/{name}/effort", None, [joint_effort[i]])
|
||||
|
||||
bun = oscbuildparse.OSCBundle(oscbuildparse.unixtime2timetag(header.stamp.sec + header.stamp.nanosec), [msg_position, msg_velocity, msg_effort])
|
||||
#bun = oscbuildparse.OSCBundle(oscbuildparse.OSC_IMMEDIATELY , [msg_position, msg_velocity, msg_effort])
|
||||
osc_send(bun, "osc_client")
|
||||
osc_process()
|
||||
#print(f"OSC bundle sent for joint {name}")
|
||||
'''
|
||||
|
||||
def main():
|
||||
rclpy.init()
|
||||
node = JointStateOSC()
|
||||
print(f"Publishing joint states to OSC on {node.osc_ip}:{node.osc_port}...")
|
||||
try:
|
||||
rclpy.spin(node)
|
||||
except KeyboardInterrupt:
|
||||
print("shutting down...")
|
||||
finally:
|
||||
node.destroy_node()
|
||||
rclpy.shutdown()
|
||||
osc_terminate()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
41
workspace/src/joint_info/joint_info/osc_joint_states_sub.py
Normal file
41
workspace/src/joint_info/joint_info/osc_joint_states_sub.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from osc4py3.as_eventloop import *
|
||||
from osc4py3 import oscmethod as osm
|
||||
import time
|
||||
|
||||
def joint_states_handler(address, *args):
|
||||
"""Handler function to process incoming joint states."""
|
||||
#print([i*180/3.141 for i in args]) # for printing joint angles in degrees
|
||||
|
||||
if address == "/joint_states":
|
||||
print(args[0])
|
||||
|
||||
def main():
|
||||
ip = "0.0.0.0" # IP address to listen on
|
||||
port = 8000 # Port to listen on
|
||||
|
||||
# Start the OSC system
|
||||
osc_startup()
|
||||
|
||||
# Make server channels to receive packets
|
||||
osc_udp_server(ip, port, "osc_server")
|
||||
|
||||
# Associate Python functions with message address patterns
|
||||
osc_method("/joint_states", joint_states_handler, argscheme=osm.OSCARG_ADDRESS + osm.OSCARG_DATAUNPACK)
|
||||
|
||||
print(f"Listening for OSC messages on {ip}:{port}...")
|
||||
|
||||
try:
|
||||
# Run the event loop
|
||||
while True:
|
||||
osc_process() # Process OSC messages
|
||||
time.sleep(0.01) # Sleep to avoid high CPU usage
|
||||
|
||||
except KeyboardInterrupt:
|
||||
print("")
|
||||
|
||||
finally:
|
||||
# Properly close the system
|
||||
osc_terminate()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
23
workspace/src/joint_info/package.xml
Normal file
23
workspace/src/joint_info/package.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
|
||||
<package format="3">
|
||||
<name>joint_info</name>
|
||||
<version>0.0.0</version>
|
||||
<description>TODO: Package description</description>
|
||||
<maintainer email="root@todo.todo">root</maintainer>
|
||||
<license>TODO: License declaration</license>
|
||||
|
||||
<depend>rclpy</depend>
|
||||
<depend>sensor_msgs</depend>
|
||||
|
||||
<test_depend>ament_copyright</test_depend>
|
||||
<test_depend>ament_flake8</test_depend>
|
||||
<test_depend>ament_pep257</test_depend>
|
||||
<test_depend>python3-pytest</test_depend>
|
||||
|
||||
<exec_depend>osc4py3</exec_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_python</build_type>
|
||||
</export>
|
||||
</package>
|
||||
0
workspace/src/joint_info/resource/joint_info
Normal file
0
workspace/src/joint_info/resource/joint_info
Normal file
4
workspace/src/joint_info/setup.cfg
Normal file
4
workspace/src/joint_info/setup.cfg
Normal file
@@ -0,0 +1,4 @@
|
||||
[develop]
|
||||
script_dir=$base/lib/joint_info
|
||||
[install]
|
||||
install_scripts=$base/lib/joint_info
|
||||
29
workspace/src/joint_info/setup.py
Normal file
29
workspace/src/joint_info/setup.py
Normal file
@@ -0,0 +1,29 @@
|
||||
from setuptools import find_packages, setup
|
||||
|
||||
package_name = 'joint_info'
|
||||
|
||||
setup(
|
||||
name=package_name,
|
||||
version='0.0.0',
|
||||
packages=find_packages(exclude=['test']),
|
||||
data_files=[
|
||||
('share/ament_index/resource_index/packages',
|
||||
['resource/' + package_name]),
|
||||
('share/' + package_name, ['package.xml']),
|
||||
],
|
||||
install_requires=[
|
||||
'setuptools'
|
||||
'osc4py3'],
|
||||
zip_safe=True,
|
||||
maintainer='root',
|
||||
maintainer_email='root@todo.todo',
|
||||
description='TODO: Package description',
|
||||
license='TODO: License declaration',
|
||||
tests_require=['pytest'],
|
||||
entry_points={
|
||||
'console_scripts': [
|
||||
"joint_states_pub = joint_info.osc_joint_states_pub:main",
|
||||
"joint_states_sub = joint_info.osc_joint_states_sub:main",
|
||||
],
|
||||
},
|
||||
)
|
||||
25
workspace/src/joint_info/test/test_copyright.py
Normal file
25
workspace/src/joint_info/test/test_copyright.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2015 Open Source Robotics Foundation, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from ament_copyright.main import main
|
||||
import pytest
|
||||
|
||||
|
||||
# Remove the `skip` decorator once the source file(s) have a copyright header
|
||||
@pytest.mark.skip(reason='No copyright header has been placed in the generated source file.')
|
||||
@pytest.mark.copyright
|
||||
@pytest.mark.linter
|
||||
def test_copyright():
|
||||
rc = main(argv=['.', 'test'])
|
||||
assert rc == 0, 'Found errors'
|
||||
25
workspace/src/joint_info/test/test_flake8.py
Normal file
25
workspace/src/joint_info/test/test_flake8.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# Copyright 2017 Open Source Robotics Foundation, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from ament_flake8.main import main_with_errors
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.flake8
|
||||
@pytest.mark.linter
|
||||
def test_flake8():
|
||||
rc, errors = main_with_errors(argv=[])
|
||||
assert rc == 0, \
|
||||
'Found %d code style errors / warnings:\n' % len(errors) + \
|
||||
'\n'.join(errors)
|
||||
23
workspace/src/joint_info/test/test_pep257.py
Normal file
23
workspace/src/joint_info/test/test_pep257.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright 2015 Open Source Robotics Foundation, Inc.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from ament_pep257.main import main
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.linter
|
||||
@pytest.mark.pep257
|
||||
def test_pep257():
|
||||
rc = main(argv=['.', 'test'])
|
||||
assert rc == 0, 'Found code style errors / warnings'
|
||||
Reference in New Issue
Block a user