fix run node fail, modify arm control panel
This commit is contained in:
@@ -209,6 +209,9 @@ def build_ui(node: CtrlGuiNode) -> None:
|
||||
ui.button('Cancel', on_click=dialog.close).classes('text-white bg-red-500')
|
||||
dialog.open()
|
||||
|
||||
# Shared variables for arm control
|
||||
arm_inputs = {}
|
||||
|
||||
with ui.row():
|
||||
|
||||
# send action package
|
||||
@@ -372,25 +375,51 @@ def build_ui(node: CtrlGuiNode) -> None:
|
||||
|
||||
#move arm
|
||||
with ui.column():
|
||||
with ui.row():
|
||||
left_arm_position_pose = ui.input('LEFT_ARM_POSE: x, y, z, rx, ry, rz, w', value='0, 0, 0, 0, 0, 0, 0').style('width: 550px')
|
||||
arm_mode_select = ui.select(['MoveJ', 'MoveP'], value='MoveP').style('width: 100px')
|
||||
|
||||
with ui.row():
|
||||
right_arm_position_pose = ui.input('RIGHT_ARM_POSE: x, y, z, rx, ry, rz, w', value='0, 0, 0, 0, 0, 0, 0').style('width: 550px')
|
||||
with ui.column():
|
||||
arm_inputs_container = ui.column()
|
||||
|
||||
# TODO check input data
|
||||
def update_arm_inputs():
|
||||
arm_inputs_container.clear()
|
||||
arm_inputs.clear()
|
||||
if arm_mode_select.value == 'MoveJ':
|
||||
with arm_inputs_container:
|
||||
with ui.row():
|
||||
arm_inputs['left'] = ui.input('LEFT_ARM_JOINT: j1, j2, j3, j4, j5, j6', value='0, 0, 0, 0, 0, 0').style('width: 550px')
|
||||
with ui.row():
|
||||
arm_inputs['right'] = ui.input('RIGHT_ARM_JOINT: j1, j2, j3, j4, j5, j6', value='0, 0, 0, 0, 0, 0').style('width: 550px')
|
||||
elif arm_mode_select.value == 'MoveP':
|
||||
with arm_inputs_container:
|
||||
with ui.row():
|
||||
arm_inputs['left'] = ui.input('LEFT_ARM_POSE: x, y, z, rx, ry, rz, w', value='0, 0, 0, 0, 0, 0, 0').style('width: 550px')
|
||||
with ui.row():
|
||||
arm_inputs['right'] = ui.input('RIGHT_ARM_POSE: x, y, z, rx, ry, rz, w', value='0, 0, 0, 0, 0, 0, 0').style('width: 550px')
|
||||
|
||||
def move_arm_() -> None:
|
||||
node.file_logger.info('Running move_arm_...')
|
||||
action_name = "Arm"
|
||||
text = f"body_id: 0\ndata_type: 3\ndata_length: 14\ncommand_id: 0\nframe_time_stamp: {node.get_clock().now().to_msg().sec}\ndata_array: [{left_arm_position_pose.value}, {right_arm_position_pose.value}]\n"
|
||||
# send_action_package(action_name, text)
|
||||
rebuild_now("Remote", action_name, text)
|
||||
# Initial update
|
||||
update_arm_inputs()
|
||||
|
||||
ui.button('Arm Control', on_click=lambda: show_confirm_dialog(
|
||||
f'Confirm Move Arm operation?\nleft_arm_pose: {left_arm_position_pose.value}\nright_arm_pose: {right_arm_position_pose.value}\n',
|
||||
move_arm_
|
||||
)).classes('self-end')
|
||||
# Update inputs when select value changes
|
||||
arm_mode_select.on('update:model-value', lambda e: update_arm_inputs())
|
||||
def move_arm_() -> None:
|
||||
node.file_logger.info('Running move_arm_...')
|
||||
action_name = "Arm"
|
||||
|
||||
if arm_mode_select.value == 'MoveJ':
|
||||
data_type = 2
|
||||
data_length = 12
|
||||
elif arm_mode_select.value == 'MoveP':
|
||||
data_type = 3
|
||||
data_length = 14
|
||||
|
||||
text = f"body_id: 0\ndata_type: {data_type}\ndata_length: {data_length}\ncommand_id: 0\nframe_time_stamp: {node.get_clock().now().to_msg().sec}\ndata_array: [{arm_inputs['left'].value}, {arm_inputs['right'].value}]\n"
|
||||
# send_action_package(action_name, text)
|
||||
rebuild_now("Remote", action_name, text)
|
||||
|
||||
ui.button('Arm Control', on_click=lambda: show_confirm_dialog(
|
||||
f'Confirm Move Arm operation?\nMove: {arm_mode_select.value}\nleft_arm_params: {arm_inputs["left"].value}\nright_arm_params: {arm_inputs["right"].value}\n',
|
||||
move_arm_
|
||||
)).classes('self-end')
|
||||
|
||||
# Add statistics display
|
||||
# ui.separator()
|
||||
@@ -489,10 +518,30 @@ def main() -> None:
|
||||
spin_thread = threading.Thread(target=rclpy.spin, args=(node,), daemon=True)
|
||||
spin_thread.start()
|
||||
|
||||
# Add static file serving for background image
|
||||
# Add static file serving: prefer workspace ../static (with background.png), fallback to package static
|
||||
from nicegui import app
|
||||
static_path = os.path.join(os.path.dirname(__file__), '..', 'static')
|
||||
app.mount('/static', StaticFiles(directory=static_path), name='static')
|
||||
pkg_static = os.path.join(os.path.dirname(__file__), 'static')
|
||||
# Allow explicit override via environment variable
|
||||
override_static = os.getenv('CTRLGUI_STATIC_DIR')
|
||||
static_path = None
|
||||
if override_static and os.path.isdir(override_static):
|
||||
static_path = override_static
|
||||
else:
|
||||
# Prefer share-installed static (from package data_files)
|
||||
try:
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
share_dir = get_package_share_directory('ctrlgui')
|
||||
share_static = os.path.join(share_dir, 'static')
|
||||
if os.path.isdir(share_static):
|
||||
static_path = share_static
|
||||
except Exception:
|
||||
static_path = None
|
||||
# Fallback to packaged static inside site-packages
|
||||
if not static_path:
|
||||
static_path = pkg_static
|
||||
print("static_path: " + static_path)
|
||||
if os.path.isdir(static_path):
|
||||
app.mount('/static', StaticFiles(directory=static_path), name='static')
|
||||
|
||||
# Build UI for the default page
|
||||
@ui.page('/')
|
||||
@@ -523,18 +572,15 @@ def main() -> None:
|
||||
|
||||
atexit.register(shutdown)
|
||||
|
||||
if __name__ in {"__main__", "__mp_main__"}:
|
||||
# Import StaticFiles for serving static files
|
||||
from starlette.staticfiles import StaticFiles
|
||||
|
||||
# Start NiceGUI honoring HOST/PORT environment variables (configurable via ROS launch)
|
||||
# Start NiceGUI honoring HOST/PORT environment variables (works with ros2 launch env)
|
||||
host = os.getenv('HOST', '0.0.0.0')
|
||||
try:
|
||||
port = int(os.getenv('PORT', '8080'))
|
||||
except ValueError:
|
||||
port = 8080
|
||||
print(f'Starting NiceGUI on {host}:{port}...')
|
||||
main()
|
||||
ui.run(title='HiveCore Robot Control Panel', host=host, port=port, reload=False, uvicorn_logging_level='info')
|
||||
else:
|
||||
ui.run(main, title='HiveCore Robot Control Panel')
|
||||
|
||||
|
||||
if __name__ in {"__main__", "__mp_main__"}:
|
||||
main()
|
||||
13
setup.py
13
setup.py
@@ -1,6 +1,6 @@
|
||||
from setuptools import find_packages, setup
|
||||
import os
|
||||
from glob import glob
|
||||
import os
|
||||
|
||||
package_name = 'ctrlgui'
|
||||
|
||||
@@ -8,14 +8,19 @@ setup(
|
||||
name=package_name,
|
||||
version='0.0.0',
|
||||
packages=find_packages(exclude=['test']),
|
||||
include_package_data=True,
|
||||
package_data={
|
||||
'ctrlgui': ['static/*'],
|
||||
},
|
||||
data_files=[
|
||||
('share/ament_index/resource_index/packages',
|
||||
['resource/' + package_name]),
|
||||
('share/' + package_name, ['package.xml']),
|
||||
('share/' + package_name + '/launch', ['launch/ctrlgui.launch.py']),
|
||||
('share/' + package_name + '/static',
|
||||
[os.path.join('static', 'background.png'),
|
||||
os.path.join('static', 'favicon.ico')]),
|
||||
# Install top-level static assets into share for runtime serving
|
||||
('share/' + package_name + '/static', [
|
||||
*glob(os.path.join('static', '*'))
|
||||
]),
|
||||
],
|
||||
install_requires=['setuptools', 'nicegui>=1.4.0'],
|
||||
zip_safe=True,
|
||||
|
||||
Reference in New Issue
Block a user