Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,13 @@
*.exe
*.out
*.app

# Python
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.egg-info/
dist/
build/
125 changes: 81 additions & 44 deletions hunter_pltf_bringup/launch/hunter_pltf_bringup.launch.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@
# limitations under the License.

from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription
from launch.actions import DeclareLaunchArgument, IncludeLaunchDescription, OpaqueFunction
from launch.substitutions import Command, FindExecutable, PathJoinSubstitution, LaunchConfiguration
from ament_index_python.packages import get_package_share_directory
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
from launch_ros.substitutions import FindPackageShare
import os
import sys
from pathlib import Path

def generate_launch_description():

Expand All @@ -33,6 +35,7 @@ def generate_launch_description():
is_sim = LaunchConfiguration('is_sim' , default='false')
enable_pd_regulator = LaunchConfiguration('enable_pd_regulator', default='False')
use_sim_time = LaunchConfiguration('use_sim_time', default='False')
robot_id = LaunchConfiguration('robot_id', default='default')

gui_declare = DeclareLaunchArgument(
"gui", default_value=gui, description="Start RViz2 automatically with this launch file.")
Expand All @@ -50,24 +53,43 @@ def generate_launch_description():
enable_pd_regulator_declare = DeclareLaunchArgument('enable_pd_regulator', default_value=enable_pd_regulator
, description='Use PD regulator estimate residual control to the robot')

# Get URDF via xacro
robot_description_content = Command(
[
PathJoinSubstitution([FindExecutable(name="xacro")]),
" ",
PathJoinSubstitution(
[FindPackageShare("hunter_pltf_description"), "description" ,"hunter_pltf.urdf.xacro"]
),
" ",
"is_sim:=",
is_sim,
" ",
"prefix:=''",
" ",
]
)
def generate_robot_description(context, *args, **kwargs):
"""Generate robot description with robot-specific configuration."""
is_sim_val = LaunchConfiguration('is_sim').perform(context)
robot_id_val = LaunchConfiguration('robot_id').perform(context)

# Import config loader
config_dir = Path(get_package_share_directory('hunter_pltf_description')) / 'config' / 'robots'
sys.path.insert(0, str(config_dir))
from config_loader import load_robot_config, get_xacro_args, format_xacro_args

# Load robot configuration
is_sim_bool = is_sim_val.lower() == 'true'
config = load_robot_config(robot_id_val)
xacro_args = get_xacro_args(config, is_sim_bool)

# Build xacro command with all arguments
xacro_file = PathJoinSubstitution(
[FindPackageShare("hunter_pltf_description"), "description", "hunter_pltf.urdf.xacro"]
)

# Format all arguments
args_str = f"is_sim:={is_sim_val} prefix:='' {format_xacro_args(xacro_args)}"

robot_description_content = Command(
[
PathJoinSubstitution([FindExecutable(name="xacro")]),
" ",
xacro_file,
" ",
args_str,
]
)

return robot_description_content

robot_description = {"robot_description": robot_description_content}
# Note: robot_description will be generated in the OpaqueFunction
# to allow runtime evaluation of robot_id

robot_controllers = PathJoinSubstitution(
[
Expand All @@ -79,31 +101,46 @@ def generate_launch_description():

base_launch = os.path.join(get_package_share_directory("hunter_base"), "launch", "hunter_base.launch.py")

control_node = Node(
package="controller_manager",
executable="ros2_control_node",
parameters=[robot_description, robot_controllers],
output="both",
)

robot_state_pub_node = Node(
package="robot_state_publisher",
executable="robot_state_publisher",
output="both",
parameters=[robot_description],
)
def launch_setup(context, *args, **kwargs):
"""Setup launch nodes with robot configuration."""
robot_description_content = generate_robot_description(context)
robot_description = {"robot_description": robot_description_content}

control_node = Node(
package="controller_manager",
executable="ros2_control_node",
parameters=[robot_description, robot_controllers],
output="both",
)

robot_state_pub_node = Node(
package="robot_state_publisher",
executable="robot_state_publisher",
output="both",
parameters=[robot_description],
)

hunter_base_node = IncludeLaunchDescription(
PythonLaunchDescriptionSource(base_launch),
launch_arguments={
'use_sim_time': use_sim_time,
'kp_v': kp_v,
'kd_v': kd_v,
'kp_w': kp_w,
'kd_w': kd_w,
'enable_pd_regulator': enable_pd_regulator
}.items(),
)

return [
robot_state_pub_node,
hunter_base_node,
]

hunter_base_node = IncludeLaunchDescription(
PythonLaunchDescriptionSource(base_launch),
launch_arguments={
'use_sim_time': use_sim_time,
'kp_v': kp_v,
'kd_v': kd_v,
'kp_w': kp_w,
'kd_w': kd_w,
'enable_pd_regulator': enable_pd_regulator
}.items(),
)
robot_id_declare = DeclareLaunchArgument(
'robot_id', default_value='default',
description='Robot instance ID (e.g., hunter_01, hunter_02). Uses robot-specific \
configuration from config/robots/<robot_id>.yaml. Defaults to default.yaml.')

# Create the launch description and populate
ld = LaunchDescription()
Expand All @@ -117,8 +154,8 @@ def generate_launch_description():
ld.add_action(kd_w_val_declare)
ld.add_action(enable_pd_regulator_declare)
ld.add_action(use_sim_time_declare)
ld.add_action(robot_id_declare)

ld.add_action(robot_state_pub_node)
ld.add_action(hunter_base_node)
ld.add_action(OpaqueFunction(function=launch_setup))

return ld
2 changes: 1 addition & 1 deletion hunter_pltf_description/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ if(BUILD_TESTING)
endif()

install(
DIRECTORY launch meshes description
DIRECTORY launch meshes description config
DESTINATION share/${PROJECT_NAME}
)

Expand Down
Loading