chore: 框架科学优化前的完整基线
在开始'设备契约层 + 目录重构 + 通止规装配'改造之前,先钉住当前可运行状态, 使后续任何删除/重构都可回退。 本基线包含: - 现有 ROS 2 工作区全部源码(arm_application / arm_control / arm_bringup 等) - 官方 flexiv_ros2 栈(含 flexiv_hardware / flexiv_controllers 等符号链接) - 设备契约层 src/arm_interfaces(新增,46 项单测通过) - devices/ 设备选型与品牌清单(新增) - scripts/gen_site_example.py 与由它生成的 config/site.example.yaml 按 .gitignore 排除:build/ / install/ / log/ / config/site.yaml / 模型权重二进制。
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
project(arm_bringup)
|
||||
|
||||
find_package(ament_cmake REQUIRED)
|
||||
|
||||
install(DIRECTORY launch config
|
||||
DESTINATION share/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
ament_package()
|
||||
@@ -0,0 +1,14 @@
|
||||
# Site defaults for Flexiv Rizon 4 (SN: Rizon4-063989)
|
||||
robot_sn: Rizon4-063989
|
||||
rizon_type: Rizon4
|
||||
# Flexiv Studio gripper (GN01) — keep false. DH PGEA uses run_gripper.sh.
|
||||
load_gripper: false
|
||||
use_fake_hardware: false
|
||||
start_rviz: true
|
||||
|
||||
# Official Flexiv joint naming: Rizon4-063989_joint1 ... joint7
|
||||
joint_prefix: Rizon4-063989_
|
||||
|
||||
base_frame: base_link
|
||||
ee_frame: tcp
|
||||
flange_frame: flange
|
||||
@@ -0,0 +1,77 @@
|
||||
from launch import LaunchDescription
|
||||
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, LogInfo, OpaqueFunction
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
|
||||
from launch_ros.substitutions import FindPackageShare
|
||||
from ament_index_python.packages import get_package_share_directory, PackageNotFoundError
|
||||
|
||||
import os
|
||||
|
||||
# Site robot — DH PGEA is a separate Modbus node (run_gripper.sh).
|
||||
# Keep Flexiv load_gripper false (that flag is Flexiv-GN01 in Studio).
|
||||
SITE_ROBOT_SN = os.environ.get('SITE_ROBOT_SN', 'Rizon4-063989')
|
||||
|
||||
|
||||
def _launch_setup(context, *args, **kwargs):
|
||||
robot_sn = LaunchConfiguration('robot_sn').perform(context)
|
||||
rizon_type = LaunchConfiguration('rizon_type').perform(context)
|
||||
use_fake = LaunchConfiguration('use_fake_hardware').perform(context)
|
||||
load_gripper = LaunchConfiguration('load_gripper').perform(context)
|
||||
start_rviz = LaunchConfiguration('start_rviz').perform(context)
|
||||
|
||||
if not robot_sn:
|
||||
return [
|
||||
LogInfo(msg=f'[arm_bringup] ERROR: robot_sn is required, e.g. robot_sn:={SITE_ROBOT_SN}')
|
||||
]
|
||||
|
||||
try:
|
||||
get_package_share_directory('flexiv_bringup')
|
||||
except PackageNotFoundError:
|
||||
return [
|
||||
LogInfo(
|
||||
msg=(
|
||||
'[arm_bringup] flexiv_bringup not found. '
|
||||
'Run scripts/fetch_flexiv.sh and build, or use sim.launch.py for mock.'
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
return [
|
||||
LogInfo(
|
||||
msg=(
|
||||
f'[arm_bringup] Starting Flexiv {rizon_type} ({robot_sn}), '
|
||||
f'load_gripper={load_gripper}'
|
||||
)
|
||||
),
|
||||
IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
PathJoinSubstitution([
|
||||
FindPackageShare('flexiv_bringup'), 'launch', 'rizon.launch.py'
|
||||
])
|
||||
),
|
||||
launch_arguments={
|
||||
'robot_sn': robot_sn,
|
||||
'rizon_type': rizon_type,
|
||||
'use_fake_hardware': use_fake,
|
||||
'load_gripper': load_gripper,
|
||||
'start_rviz': start_rviz,
|
||||
}.items(),
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
"""Real Rizon4 bringup via official flexiv_bringup (RDK v1 / humble-v1)."""
|
||||
return LaunchDescription([
|
||||
DeclareLaunchArgument(
|
||||
'robot_sn',
|
||||
default_value=SITE_ROBOT_SN,
|
||||
description='Site robot serial number (no spaces)',
|
||||
),
|
||||
DeclareLaunchArgument('rizon_type', default_value='Rizon4'),
|
||||
DeclareLaunchArgument('use_fake_hardware', default_value='false'),
|
||||
# Flexiv-GN01 only. DH PGEA: bash ~/ros2/scripts/run_gripper.sh
|
||||
DeclareLaunchArgument('load_gripper', default_value='false'),
|
||||
DeclareLaunchArgument('start_rviz', default_value='true'),
|
||||
OpaqueFunction(function=_launch_setup),
|
||||
])
|
||||
@@ -0,0 +1,46 @@
|
||||
from launch import LaunchDescription
|
||||
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
|
||||
from launch.conditions import IfCondition
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
|
||||
from launch_ros.substitutions import FindPackageShare
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
"""Offline mock bringup for Flexiv Rizon 4 (7-DOF), no real robot required."""
|
||||
use_rviz = LaunchConfiguration('use_rviz')
|
||||
use_moveit = LaunchConfiguration('use_moveit')
|
||||
robot_sn = LaunchConfiguration('robot_sn')
|
||||
|
||||
mock = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
PathJoinSubstitution([
|
||||
FindPackageShare('arm_control'), 'launch', 'mock_control.launch.py'
|
||||
])
|
||||
),
|
||||
launch_arguments={
|
||||
'use_rviz': use_rviz,
|
||||
'robot_sn': robot_sn,
|
||||
}.items(),
|
||||
)
|
||||
|
||||
moveit = IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
PathJoinSubstitution([
|
||||
FindPackageShare('arm_moveit_config'), 'launch', 'move_group.launch.py'
|
||||
])
|
||||
),
|
||||
condition=IfCondition(use_moveit),
|
||||
)
|
||||
|
||||
return LaunchDescription([
|
||||
DeclareLaunchArgument('use_rviz', default_value='true'),
|
||||
DeclareLaunchArgument('use_moveit', default_value='false'),
|
||||
DeclareLaunchArgument(
|
||||
'robot_sn',
|
||||
default_value='Rizon4-063989',
|
||||
description='Site SN; joints become Rizon4-063989_joint1..joint7',
|
||||
),
|
||||
mock,
|
||||
moveit,
|
||||
])
|
||||
@@ -0,0 +1,208 @@
|
||||
"""Unified stack launch: backend:=mock|moveit|real|isaac
|
||||
|
||||
Application interfaces stay the same across backends:
|
||||
/set_named_pose, /get_arm_state, /arm_status, /follow_joint_trajectory
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from launch import LaunchDescription
|
||||
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, LogInfo, OpaqueFunction
|
||||
from launch.conditions import IfCondition
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
|
||||
from launch_ros.actions import Node
|
||||
from launch_ros.substitutions import FindPackageShare
|
||||
from ament_index_python.packages import PackageNotFoundError, get_package_share_directory
|
||||
|
||||
|
||||
SITE_SN = os.environ.get('SITE_ROBOT_SN', 'Rizon4-063989')
|
||||
SITE_PREFIX = os.environ.get('SITE_JOINT_PREFIX', f'{SITE_SN}_')
|
||||
SITE_NAMED_POSES = os.environ.get('SITE_NAMED_POSES_FILE', '').strip()
|
||||
|
||||
|
||||
def _setup(context, *args, **kwargs):
|
||||
backend = LaunchConfiguration('backend').perform(context).strip().lower()
|
||||
use_rviz = LaunchConfiguration('use_rviz')
|
||||
robot_sn = LaunchConfiguration('robot_sn')
|
||||
load_gripper = LaunchConfiguration('load_gripper')
|
||||
sn = robot_sn.perform(context).strip() or SITE_SN
|
||||
|
||||
actions = [
|
||||
LogInfo(msg=f'[arm_bringup] backend={backend} sn={sn}'),
|
||||
]
|
||||
|
||||
if backend in ('mock', 'moveit', 'isaac'):
|
||||
actions.append(
|
||||
IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
PathJoinSubstitution([
|
||||
FindPackageShare('arm_control'),
|
||||
'launch',
|
||||
'mock_control.launch.py',
|
||||
])
|
||||
),
|
||||
launch_arguments={
|
||||
'use_rviz': use_rviz,
|
||||
'robot_sn': robot_sn,
|
||||
'load_gripper': load_gripper,
|
||||
}.items(),
|
||||
)
|
||||
)
|
||||
|
||||
if backend == 'moveit':
|
||||
actions.append(
|
||||
Node(
|
||||
package='arm_control',
|
||||
executable='trajectory_bridge',
|
||||
name='trajectory_bridge',
|
||||
parameters=[{
|
||||
'control_action': 'rizon_arm_controller/follow_joint_trajectory',
|
||||
'arm_action': 'follow_joint_trajectory',
|
||||
}],
|
||||
output='screen',
|
||||
)
|
||||
)
|
||||
actions.append(
|
||||
IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
PathJoinSubstitution([
|
||||
FindPackageShare('arm_moveit_config'),
|
||||
'launch',
|
||||
'move_group.launch.py',
|
||||
])
|
||||
),
|
||||
launch_arguments={
|
||||
'use_fake_hardware': 'true',
|
||||
'robot_sn': robot_sn,
|
||||
'start_rviz': 'false',
|
||||
}.items(),
|
||||
)
|
||||
)
|
||||
actions.append(
|
||||
LogInfo(
|
||||
msg=(
|
||||
'[arm_bringup] MoveIt on top of mock. '
|
||||
'Named poses still via /set_named_pose; '
|
||||
'MoveIt plans execute through trajectory_bridge.'
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if backend == 'real':
|
||||
try:
|
||||
get_package_share_directory('flexiv_bringup')
|
||||
except PackageNotFoundError:
|
||||
actions.append(
|
||||
LogInfo(
|
||||
msg=(
|
||||
'[arm_bringup] flexiv_bringup missing. '
|
||||
'Run: ./scripts/fetch_flexiv.sh && rebuild. '
|
||||
'Falling back tip: use backend:=mock for now.'
|
||||
)
|
||||
)
|
||||
)
|
||||
return actions
|
||||
actions.append(
|
||||
IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
PathJoinSubstitution([
|
||||
FindPackageShare('arm_bringup'),
|
||||
'launch',
|
||||
'real.launch.py',
|
||||
])
|
||||
),
|
||||
launch_arguments={
|
||||
'robot_sn': robot_sn,
|
||||
'load_gripper': load_gripper,
|
||||
'start_rviz': use_rviz,
|
||||
}.items(),
|
||||
)
|
||||
)
|
||||
# Keep application services on top of real HW when possible
|
||||
actions.append(
|
||||
Node(
|
||||
package='arm_control',
|
||||
executable='real_trajectory_adapter',
|
||||
name='real_trajectory_adapter',
|
||||
parameters=[{
|
||||
'control_action': 'rizon_arm_controller/follow_joint_trajectory',
|
||||
'arm_action': 'follow_joint_trajectory',
|
||||
}],
|
||||
output='screen',
|
||||
)
|
||||
)
|
||||
poses_params = []
|
||||
if SITE_NAMED_POSES and os.path.isfile(SITE_NAMED_POSES):
|
||||
poses_params.append(SITE_NAMED_POSES)
|
||||
else:
|
||||
poses_params.append(
|
||||
PathJoinSubstitution([
|
||||
FindPackageShare('arm_control'), 'config', 'named_poses.yaml'
|
||||
])
|
||||
)
|
||||
poses_params.append({'joint_prefix': f'{sn}_'})
|
||||
actions.append(
|
||||
Node(
|
||||
package='arm_control',
|
||||
executable='named_pose_server',
|
||||
name='named_pose_server',
|
||||
parameters=poses_params,
|
||||
output='screen',
|
||||
)
|
||||
)
|
||||
actions.append(
|
||||
Node(
|
||||
package='arm_control',
|
||||
executable='arm_status_node',
|
||||
name='arm_status_node',
|
||||
parameters=[{
|
||||
'base_frame': f'{sn}_base_link',
|
||||
'ee_frame': f'{sn}_flange',
|
||||
'tcp_pose_topic': f'/{sn.replace("-", "_")}/tcp_pose',
|
||||
}],
|
||||
output='screen',
|
||||
)
|
||||
)
|
||||
actions.append(
|
||||
LogInfo(
|
||||
msg=(
|
||||
'[arm_bringup] REAL mode: flexiv_bringup + named_pose_server '
|
||||
'+ arm_status_node. '
|
||||
'Ensure RDK is enabled and network reaches the robot.'
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if backend == 'isaac':
|
||||
actions.append(
|
||||
LogInfo(
|
||||
msg=(
|
||||
'[arm_bringup] ISAAC mode: mock ROS stack is up for bridge testing. '
|
||||
'Start Isaac Sim + flexiv_sim_plugin separately '
|
||||
'(see docs/INTERFACES.md). '
|
||||
'Sync joints via /joint_states or RDK bridge topics.'
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
if backend not in ('mock', 'moveit', 'real', 'isaac'):
|
||||
actions.append(
|
||||
LogInfo(msg=f'[arm_bringup] Unknown backend "{backend}". Use mock|moveit|real|isaac')
|
||||
)
|
||||
|
||||
return actions
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
return LaunchDescription([
|
||||
DeclareLaunchArgument(
|
||||
'backend',
|
||||
default_value='mock',
|
||||
description='mock | moveit | real | isaac',
|
||||
),
|
||||
DeclareLaunchArgument('use_rviz', default_value='true'),
|
||||
DeclareLaunchArgument('robot_sn', default_value=SITE_SN),
|
||||
DeclareLaunchArgument('load_gripper', default_value='false'),
|
||||
OpaqueFunction(function=_setup),
|
||||
])
|
||||
@@ -0,0 +1,20 @@
|
||||
<?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>arm_bringup</name>
|
||||
<version>0.1.0</version>
|
||||
<description>Bringup for Flexiv Rizon 4 simulation and real robot.</description>
|
||||
<maintainer email="dev@example.com">arm_dev</maintainer>
|
||||
<license>Apache-2.0</license>
|
||||
|
||||
<buildtool_depend>ament_cmake</buildtool_depend>
|
||||
|
||||
<exec_depend>arm_description</exec_depend>
|
||||
<exec_depend>arm_control</exec_depend>
|
||||
<exec_depend>arm_moveit_config</exec_depend>
|
||||
<exec_depend>arm_application</exec_depend>
|
||||
|
||||
<export>
|
||||
<build_type>ament_cmake</build_type>
|
||||
</export>
|
||||
</package>
|
||||
Reference in New Issue
Block a user