Staging checkin
Moved to mechanum controller Use a single URDF from the robot description TODO: Wheel physics is not yet correct for mecanum movement.
This commit is contained in:
@@ -36,7 +36,7 @@ def generate_launch_description():
|
||||
urdf_file = os.path.join(
|
||||
get_package_share_directory('agv_pro_description'),
|
||||
'urdf',
|
||||
'agv_pro.urdf'
|
||||
'agv_pro.urdf.xacro'
|
||||
)
|
||||
|
||||
# Pass both namespace and port_name into the xacro processor so that the
|
||||
@@ -117,9 +117,12 @@ def generate_launch_description():
|
||||
output='screen',
|
||||
)
|
||||
|
||||
# mecanum_drive_controller subscribes to ~/reference (TwistStamped).
|
||||
# --controller-ros-args remaps it to /cmd_vel so nav2 and teleop work
|
||||
# without extra flags (teleop still needs stamped:=true).
|
||||
# mecanum_drive_controller subscribes to ~/reference (TwistStamped). Remap it
|
||||
# to the standard /cmd_vel so nav2 and teleop work without extra flags
|
||||
# (teleop still needs stamped:=true).
|
||||
# NOTE: the remap key MUST be the private name '~/reference' — a bare
|
||||
# 'reference:=/cmd_vel' is silently ignored and the controller stays on
|
||||
# /mecanum_drive_controller/reference.
|
||||
# Delayed slightly so controller_manager is ready before spawning.
|
||||
mecanum_drive_controller_spawner = TimerAction(
|
||||
period=2.0,
|
||||
@@ -130,29 +133,13 @@ def generate_launch_description():
|
||||
arguments=[
|
||||
'mecanum_drive_controller',
|
||||
'--controller-manager', 'controller_manager',
|
||||
'--controller-ros-args', '-r reference:=/cmd_vel',
|
||||
'--controller-ros-args', '-r ~/reference:=/cmd_vel',
|
||||
],
|
||||
output='screen',
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
# Relay /cmd_vel (TwistStamped) → /mecanum_drive_controller/reference.
|
||||
# This bridges the standard nav2/teleop topic to the controller's
|
||||
# internal subscription, which ros2_control does not remap at load time.
|
||||
# lazy:=false ensures the subscription exists before any publisher appears.
|
||||
cmd_vel_relay = Node(
|
||||
package='topic_tools',
|
||||
executable='relay',
|
||||
name='cmd_vel_relay',
|
||||
parameters=[{
|
||||
'input_topic': '/cmd_vel',
|
||||
'output_topic': '/mecanum_drive_controller/reference',
|
||||
'lazy': False,
|
||||
}],
|
||||
output='screen',
|
||||
)
|
||||
|
||||
lidar_launchs = [
|
||||
include_lidar('lslidar_driver', 'lsn10p_launch.py', enable_lidar, lidar_type, 'n10p'),
|
||||
include_lidar('agv_pro_bringup', 'MID360_launch.py', enable_lidar, lidar_type, 'mid360'),
|
||||
@@ -170,7 +157,6 @@ def generate_launch_description():
|
||||
robot_state_pub,
|
||||
joint_state_broadcaster_spawner,
|
||||
mecanum_drive_controller_spawner,
|
||||
cmd_vel_relay,
|
||||
*lidar_launchs,
|
||||
]
|
||||
)
|
||||
@@ -12,7 +12,6 @@
|
||||
<exec_depend>controller_manager</exec_depend>
|
||||
<exec_depend>mecanum_drive_controller</exec_depend>
|
||||
<exec_depend>joint_state_broadcaster</exec_depend>
|
||||
<exec_depend>topic_tools</exec_depend>
|
||||
<exec_depend>agv_pro_hardware</exec_depend>
|
||||
<exec_depend>agv_pro_description</exec_depend>
|
||||
<exec_depend>rviz2</exec_depend>
|
||||
|
||||
@@ -20,7 +20,7 @@ def generate_launch_description():
|
||||
urdf_file = os.path.join(
|
||||
get_package_share_directory('agv_pro_description'),
|
||||
'urdf',
|
||||
'agv_pro.urdf'
|
||||
'agv_pro.urdf.xacro'
|
||||
)
|
||||
|
||||
robot_description_content = Command([
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
|
||||
|
||||
<!--
|
||||
Gazebo (gz-sim Harmonic) specific tags. Only included when sim=true.
|
||||
Provides wheel surface friction/material and loads the gz_ros2_control
|
||||
system plugin that hosts the controller_manager inside gz-sim.
|
||||
-->
|
||||
<xacro:macro name="agv_pro_gazebo" params="namespace controllers_file">
|
||||
|
||||
<!-- Per-wheel surface friction + dark material -->
|
||||
<xacro:macro name="wheel_gz" params="link">
|
||||
<gazebo reference="${link}">
|
||||
<mu1>0.8</mu1>
|
||||
<mu2>0.8</mu2>
|
||||
<kp>100000.0</kp>
|
||||
<kd>1.0</kd>
|
||||
<visual>
|
||||
<material>
|
||||
<ambient>0.1 0.1 0.1 1</ambient>
|
||||
<diffuse>0.1 0.1 0.1 1</diffuse>
|
||||
<specular>0.1 0.1 0.1 1</specular>
|
||||
</material>
|
||||
</visual>
|
||||
</gazebo>
|
||||
</xacro:macro>
|
||||
|
||||
<xacro:wheel_gz link="${namespace}left_front_wheel_link"/>
|
||||
<xacro:wheel_gz link="${namespace}right_front_wheel_link"/>
|
||||
<xacro:wheel_gz link="${namespace}left_rear_wheel_link"/>
|
||||
<xacro:wheel_gz link="${namespace}right_rear_wheel_link"/>
|
||||
|
||||
<!-- gz_ros2_control system plugin: hosts the controller_manager in gz-sim -->
|
||||
<gazebo>
|
||||
<plugin filename="gz_ros2_control-system"
|
||||
name="gz_ros2_control::GazeboSimROS2ControlPlugin">
|
||||
<parameters>${controllers_file}</parameters>
|
||||
</plugin>
|
||||
</gazebo>
|
||||
</xacro:macro>
|
||||
</robot>
|
||||
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
|
||||
|
||||
<!--
|
||||
ros2_control block shared by the physical robot and the Gazebo simulation.
|
||||
|
||||
The only difference between the two is the <hardware> plugin:
|
||||
sim=false -> agv_pro_hardware/AgvProHardwareInterface (real serial base)
|
||||
sim=true -> gz_ros2_control/GazeboSimSystem (Gazebo Harmonic)
|
||||
|
||||
Joint-name note: the URDF joint origins show two wheels are physically at the
|
||||
'wrong' position relative to their names (left_rear is physically front-right,
|
||||
right_front is physically rear-left). The hardware plugin (real) and the
|
||||
mecanum_drive_controller (both) resolve this via the front/rear/left/right
|
||||
parameter mapping.
|
||||
-->
|
||||
<xacro:macro name="agv_pro_ros2_control" params="sim namespace port_name">
|
||||
<ros2_control name="AgvProSystem" type="system">
|
||||
<hardware>
|
||||
<xacro:if value="${sim}">
|
||||
<plugin>gz_ros2_control/GazeboSimSystem</plugin>
|
||||
</xacro:if>
|
||||
<xacro:unless value="${sim}">
|
||||
<plugin>agv_pro_hardware/AgvProHardwareInterface</plugin>
|
||||
<param name="port_name">${port_name}</param>
|
||||
<param name="wheel_radius">0.072</param>
|
||||
<param name="lx">0.172</param>
|
||||
<param name="ly">0.180</param>
|
||||
<!-- Physical wheel position -> URDF joint name mapping -->
|
||||
<param name="front_left_joint">${namespace}left_front_wheel_joint</param>
|
||||
<param name="front_right_joint">${namespace}left_rear_wheel_joint</param>
|
||||
<param name="rear_left_joint">${namespace}right_front_wheel_joint</param>
|
||||
<param name="rear_right_joint">${namespace}right_rear_wheel_joint</param>
|
||||
</xacro:unless>
|
||||
</hardware>
|
||||
|
||||
<joint name="${namespace}left_front_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
<joint name="${namespace}left_rear_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
<joint name="${namespace}right_front_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
<joint name="${namespace}right_rear_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
</ros2_control>
|
||||
</xacro:macro>
|
||||
</robot>
|
||||
Executable → Regular
+20
-44
@@ -1,10 +1,21 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<robot name="AGV pro" xmlns:xacro="http://www.ros.org/wiki/xacro">
|
||||
<robot name="agv_pro" xmlns:xacro="http://www.ros.org/wiki/xacro">
|
||||
|
||||
<!-- Optional namespace prefix for all link/joint names -->
|
||||
<xacro:arg name="namespace" default=""/>
|
||||
<xacro:property name="namespace" value="$(arg namespace)"/>
|
||||
|
||||
<!-- Hardware selection: false -> real serial base, true -> Gazebo (gz-sim) -->
|
||||
<xacro:arg name="sim" default="false"/>
|
||||
<xacro:property name="sim" value="$(arg sim)"/>
|
||||
|
||||
<!-- Real-hardware serial port (ignored when sim=true) -->
|
||||
<xacro:arg name="port_name" default="/dev/agvpro_controller"/>
|
||||
<xacro:property name="port_name" value="$(arg port_name)"/>
|
||||
|
||||
<!-- Controller params file consumed by gz_ros2_control (sim only) -->
|
||||
<xacro:arg name="controllers_file" default=""/>
|
||||
<xacro:property name="controllers_file" value="$(arg controllers_file)"/>
|
||||
|
||||
<link name="${namespace}base_footprint"/>
|
||||
|
||||
@@ -231,49 +242,14 @@
|
||||
<child link="${namespace}imu_link" />
|
||||
</joint>
|
||||
|
||||
<!-- ════════════════════════════════════════════════════════════════════════
|
||||
ros2_control hardware interface for the real robot.
|
||||
<!-- ros2_control: real hardware or gz_ros2_control depending on 'sim' -->
|
||||
<xacro:include filename="$(find agv_pro_description)/urdf/agv_pro.ros2_control.xacro"/>
|
||||
<xacro:agv_pro_ros2_control sim="${sim}" namespace="${namespace}" port_name="${port_name}"/>
|
||||
|
||||
Joint-name note: the URDF joint origins show that two wheels are
|
||||
physically at the 'wrong' position relative to their names:
|
||||
left_rear_wheel_joint is physically at front-right (+x, -y)
|
||||
right_front_wheel_joint is physically at rear-left (-x, +y)
|
||||
The hardware plugin and mecanum_drive_controller both use the
|
||||
front_left/front_right/rear_left/rear_right params to resolve this.
|
||||
════════════════════════════════════════════════════════════════════════ -->
|
||||
<ros2_control name="AgvProHardwareInterface" type="system">
|
||||
<hardware>
|
||||
<plugin>agv_pro_hardware/AgvProHardwareInterface</plugin>
|
||||
<param name="port_name">$(arg port_name)</param>
|
||||
<param name="wheel_radius">0.072</param>
|
||||
<param name="lx">0.172</param>
|
||||
<param name="ly">0.180</param>
|
||||
<!-- Physical wheel position → URDF joint name mapping -->
|
||||
<param name="front_left_joint">${namespace}left_front_wheel_joint</param>
|
||||
<param name="front_right_joint">${namespace}left_rear_wheel_joint</param>
|
||||
<param name="rear_left_joint">${namespace}right_front_wheel_joint</param>
|
||||
<param name="rear_right_joint">${namespace}right_rear_wheel_joint</param>
|
||||
</hardware>
|
||||
<joint name="${namespace}left_front_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
<joint name="${namespace}left_rear_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
<joint name="${namespace}right_front_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
<joint name="${namespace}right_rear_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
</ros2_control>
|
||||
<!-- Gazebo-only tags (friction, material, gz_ros2_control system plugin) -->
|
||||
<xacro:if value="${sim}">
|
||||
<xacro:include filename="$(find agv_pro_description)/urdf/agv_pro.gazebo.xacro"/>
|
||||
<xacro:agv_pro_gazebo namespace="${namespace}" controllers_file="${controllers_file}"/>
|
||||
</xacro:if>
|
||||
|
||||
</robot>
|
||||
@@ -7,14 +7,13 @@ endif()
|
||||
|
||||
# find dependencies
|
||||
find_package(ament_cmake REQUIRED)
|
||||
find_package(urdf REQUIRED)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
find_package(ament_lint_auto REQUIRED)
|
||||
ament_lint_auto_find_test_dependencies()
|
||||
endif()
|
||||
|
||||
install(DIRECTORY meshes urdf launch rviz config worlds
|
||||
install(DIRECTORY meshes launch rviz config worlds
|
||||
DESTINATION share/${PROJECT_NAME}
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
controller_manager:
|
||||
ros__parameters:
|
||||
update_rate: 100 # 控制器更新频率 (Hz)
|
||||
update_rate: 50 # 控制器更新频率 (Hz) — matches the physical robot (ESP32 auto-report rate)
|
||||
use_sim_time: true # 使用仿真时间
|
||||
|
||||
# 定义关节状态广播器
|
||||
@@ -11,29 +11,36 @@ controller_manager:
|
||||
mecanum_drive_controller:
|
||||
type: mecanum_drive_controller/MecanumDriveController
|
||||
|
||||
# 麦克纳姆四轮驱动控制器配置
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Mecanum drive controller — kept IN SYNC with the physical robot config at
|
||||
# agv_pro_bringup/config/ros2_controllers.yaml. Only the hardware plugin differs
|
||||
# (gz_ros2_control/GazeboSimSystem here vs agv_pro_hardware/AgvProHardwareInterface
|
||||
# on the real robot); the controller parameters are identical.
|
||||
#
|
||||
# NOTE: The URDF joint names do not match the physical wheel positions due to a
|
||||
# naming inconsistency in the shared robot model. The controller compensates via
|
||||
# the front/rear/left/right command-joint mapping below:
|
||||
#
|
||||
# Physical position │ URDF joint name
|
||||
# ──────────────────┼────────────────────────────
|
||||
# front-left (FL) │ left_front_wheel_joint ✓
|
||||
# front-right (FR) │ left_rear_wheel_joint ← physically front-right
|
||||
# rear-left (RL) │ right_front_wheel_joint ← physically rear-left
|
||||
# rear-right (RR) │ right_rear_wheel_joint ✓
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
mecanum_drive_controller:
|
||||
ros__parameters:
|
||||
reference_timeout: 0.5
|
||||
|
||||
# 命令关节 (velocity command interface)
|
||||
front_left_wheel_command_joint_name: left_front_wheel_joint
|
||||
front_right_wheel_command_joint_name: right_front_wheel_joint
|
||||
rear_left_wheel_command_joint_name: left_rear_wheel_joint
|
||||
front_right_wheel_command_joint_name: left_rear_wheel_joint
|
||||
rear_left_wheel_command_joint_name: right_front_wheel_joint
|
||||
rear_right_wheel_command_joint_name: right_rear_wheel_joint
|
||||
|
||||
kinematics:
|
||||
base_frame_offset:
|
||||
x: 0.0
|
||||
y: 0.0
|
||||
theta: 0.0
|
||||
wheels_radius: 0.05 # 轮子半径
|
||||
# lx + ly : 底盘中心到轮子在 X 与 Y 方向投影之和
|
||||
sum_of_robot_center_projection_on_X_Y_axis: 0.35
|
||||
|
||||
base_frame_id: base_link
|
||||
odom_frame_id: odom
|
||||
base_frame_id: base_footprint
|
||||
enable_odom_tf: true
|
||||
|
||||
pose_covariance_diagonal: [0.001, 0.001, 99999.0, 99999.0, 99999.0, 0.03]
|
||||
twist_covariance_diagonal: [0.001, 0.001, 99999.0, 99999.0, 99999.0, 0.03]
|
||||
kinematics:
|
||||
wheels_radius: 0.072 # 轮子半径 (wheel centre height above ground)
|
||||
# sum_of_robot_center_projection_on_X_Y_axis = lx + ly (0.172 + 0.180)
|
||||
sum_of_robot_center_projection_on_X_Y_axis: 0.352
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
import os
|
||||
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
|
||||
from launch import LaunchDescription
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from launch.actions import DeclareLaunchArgument
|
||||
from launch_ros.actions import Node
|
||||
|
||||
import xacro
|
||||
|
||||
|
||||
def generate_launch_description():
|
||||
|
||||
# Check if we're told to use sim time
|
||||
use_sim_time = LaunchConfiguration('use_sim_time')
|
||||
|
||||
# Process the URDF file
|
||||
pkg_path = os.path.join(get_package_share_directory('agv_pro_gazebo'))
|
||||
xacro_file = os.path.join(pkg_path,'urdf','agv_pro.xacro')
|
||||
robot_description_config = xacro.process_file(xacro_file)
|
||||
|
||||
# Create a robot_state_publisher node
|
||||
params = {'robot_description': robot_description_config.toxml(), 'use_sim_time': use_sim_time}
|
||||
node_robot_state_publisher = Node(
|
||||
package='robot_state_publisher',
|
||||
executable='robot_state_publisher',
|
||||
output='screen',
|
||||
parameters=[params]
|
||||
)
|
||||
|
||||
# Launch!
|
||||
return LaunchDescription([
|
||||
DeclareLaunchArgument(
|
||||
'use_sim_time',
|
||||
default_value='false',
|
||||
description='Use sim time if true'),
|
||||
|
||||
node_robot_state_publisher
|
||||
])
|
||||
@@ -1,48 +0,0 @@
|
||||
import os
|
||||
from launch import LaunchDescription
|
||||
from launch_ros.actions import Node
|
||||
from launch.conditions import IfCondition
|
||||
from launch.substitutions import LaunchConfiguration
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
|
||||
def generate_launch_description():
|
||||
|
||||
use_rviz = LaunchConfiguration('use_rviz', default='true')
|
||||
rviz_config_dir = os.path.join(
|
||||
get_package_share_directory('agv_pro_gazebo'),
|
||||
'rviz',
|
||||
'agvpro_display.rviz')
|
||||
|
||||
urdf_file = os.path.join(
|
||||
get_package_share_directory('agv_pro_gazebo'),
|
||||
'urdf',
|
||||
'agv_pro.urdf'
|
||||
)
|
||||
|
||||
with open(urdf_file, 'r') as file:
|
||||
robot_description_content = file.read()
|
||||
|
||||
return LaunchDescription([
|
||||
|
||||
Node(
|
||||
package='joint_state_publisher',
|
||||
executable='joint_state_publisher',
|
||||
name='joint_state_publisher'
|
||||
),
|
||||
|
||||
Node(
|
||||
package='robot_state_publisher',
|
||||
executable='robot_state_publisher',
|
||||
name='robot_state_publisher',
|
||||
parameters=[{'robot_description': robot_description_content}]
|
||||
),
|
||||
|
||||
Node(
|
||||
package='rviz2',
|
||||
executable='rviz2',
|
||||
name='rviz2',
|
||||
arguments=['-d', rviz_config_dir],
|
||||
condition=IfCondition(use_rviz),
|
||||
output='screen')
|
||||
|
||||
])
|
||||
@@ -4,12 +4,18 @@ from launch.actions import (
|
||||
IncludeLaunchDescription,
|
||||
DeclareLaunchArgument,
|
||||
RegisterEventHandler,
|
||||
SetEnvironmentVariable,
|
||||
TimerAction,
|
||||
)
|
||||
from launch.conditions import IfCondition
|
||||
from launch.event_handlers import OnProcessExit
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch.substitutions import Command, LaunchConfiguration, PythonExpression
|
||||
from launch.substitutions import (
|
||||
Command,
|
||||
EnvironmentVariable,
|
||||
LaunchConfiguration,
|
||||
PythonExpression,
|
||||
)
|
||||
from launch_ros.actions import Node
|
||||
from launch_ros.parameter_descriptions import ParameterValue
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
@@ -17,9 +23,12 @@ from ament_index_python.packages import get_package_share_directory
|
||||
|
||||
def generate_launch_description():
|
||||
pkg_gazebo = get_package_share_directory('agv_pro_gazebo')
|
||||
pkg_description = get_package_share_directory('agv_pro_description')
|
||||
pkg_ros_gz_sim = get_package_share_directory('ros_gz_sim')
|
||||
|
||||
xacro_file = os.path.join(pkg_gazebo, 'urdf', 'agv_pro.xacro')
|
||||
# Shared robot description (agv_pro_description) built for simulation.
|
||||
xacro_file = os.path.join(pkg_description, 'urdf', 'agv_pro.urdf.xacro')
|
||||
controllers_file = os.path.join(pkg_gazebo, 'config', 'agv_control.yaml')
|
||||
world_file = os.path.join(pkg_gazebo, 'worlds', 'empty.world')
|
||||
rviz_config = os.path.join(pkg_gazebo, 'rviz', 'agvpro_display.rviz')
|
||||
|
||||
@@ -29,11 +38,29 @@ def generate_launch_description():
|
||||
|
||||
robot_description = {
|
||||
'robot_description': ParameterValue(
|
||||
Command(['xacro ', xacro_file]), value_type=str
|
||||
Command([
|
||||
'xacro ', xacro_file,
|
||||
' sim:=true',
|
||||
' controllers_file:=', controllers_file,
|
||||
]),
|
||||
value_type=str,
|
||||
),
|
||||
'use_sim_time': use_sim_time,
|
||||
}
|
||||
|
||||
# Let gz-sim resolve the package:// mesh URIs in the shared description.
|
||||
# URDF->SDF conversion rewrites package://agv_pro_description/... to
|
||||
# model://agv_pro_description/..., which gz finds by searching
|
||||
# GZ_SIM_RESOURCE_PATH for a directory named 'agv_pro_description'.
|
||||
gz_resource_path = SetEnvironmentVariable(
|
||||
name='GZ_SIM_RESOURCE_PATH',
|
||||
value=[
|
||||
os.path.dirname(pkg_description),
|
||||
':',
|
||||
EnvironmentVariable('GZ_SIM_RESOURCE_PATH', default_value=''),
|
||||
],
|
||||
)
|
||||
|
||||
# Start gz-sim (Gazebo Harmonic) with the world.
|
||||
# '-s' (server only) is added when headless:=true.
|
||||
gz_args = PythonExpression([
|
||||
@@ -88,12 +115,17 @@ def generate_launch_description():
|
||||
output='screen',
|
||||
)
|
||||
|
||||
# Remap the controller's reference topic (~/reference) to the standard
|
||||
# /cmd_vel so teleop and nav2 (which publish geometry_msgs/TwistStamped)
|
||||
# drive the robot directly. NOTE: the remap key must be the private name
|
||||
# '~/reference' — a bare 'reference:=/cmd_vel' is silently ignored.
|
||||
mecanum_drive_controller_spawner = Node(
|
||||
package='controller_manager',
|
||||
executable='spawner',
|
||||
arguments=[
|
||||
'mecanum_drive_controller',
|
||||
'--controller-manager', '/controller_manager',
|
||||
'--controller-ros-args', '-r ~/reference:=/cmd_vel',
|
||||
],
|
||||
output='screen',
|
||||
)
|
||||
@@ -124,6 +156,7 @@ def generate_launch_description():
|
||||
default_value='false',
|
||||
description='Run gz-sim without the GUI (server only)',
|
||||
),
|
||||
gz_resource_path,
|
||||
gz_sim,
|
||||
robot_state_publisher,
|
||||
clock_bridge,
|
||||
|
||||
@@ -13,12 +13,12 @@ def generate_launch_description():
|
||||
prefix='xterm -e', # 或 'gnome-terminal --' 替换为你的终端命令
|
||||
# mecanum_drive_controller expects a stamped reference; teleop must
|
||||
# publish geometry_msgs/TwistStamped with a fresh timestamp.
|
||||
# It publishes on the standard /cmd_vel topic, which the sim launch
|
||||
# feeds to the controller (spawner remap + cmd_vel_relay), mirroring
|
||||
# the physical robot.
|
||||
parameters=[{
|
||||
'stamped': True,
|
||||
'frame_id': 'base_link',
|
||||
}],
|
||||
remappings=[
|
||||
('/cmd_vel', '/mecanum_drive_controller/reference'),
|
||||
]
|
||||
)
|
||||
])
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import os
|
||||
from launch import LaunchDescription
|
||||
from launch.actions import IncludeLaunchDescription
|
||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||
from launch_ros.actions import Node
|
||||
from launch.substitutions import Command
|
||||
from ament_index_python.packages import get_package_share_directory
|
||||
|
||||
def generate_launch_description():
|
||||
pkg_dir = get_package_share_directory('agv_pro_description')
|
||||
xacro_file = os.path.join(pkg_dir, 'urdf', 'minimal_robot.xacro')
|
||||
world_file = os.path.join(pkg_dir, 'worlds', 'empty.world')
|
||||
|
||||
robot_description = {'robot_description': Command(['xacro ', xacro_file])}
|
||||
|
||||
return LaunchDescription([
|
||||
IncludeLaunchDescription(
|
||||
PythonLaunchDescriptionSource(
|
||||
os.path.join(get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')
|
||||
),
|
||||
launch_arguments={'world': world_file}.items()
|
||||
),
|
||||
Node(
|
||||
package='robot_state_publisher',
|
||||
executable='robot_state_publisher',
|
||||
parameters=[robot_description],
|
||||
output='screen'
|
||||
),
|
||||
Node(
|
||||
package='gazebo_ros',
|
||||
executable='spawn_entity.py',
|
||||
arguments=['-topic', 'robot_description', '-entity', 'minimal_bot'],
|
||||
output='screen'
|
||||
)
|
||||
])
|
||||
@@ -13,6 +13,8 @@
|
||||
<buildtool_depend>xacro</buildtool_depend>
|
||||
|
||||
<!-- Runtime dependencies -->
|
||||
<!-- Shared robot description (single source of truth for sim + real) -->
|
||||
<depend>agv_pro_description</depend>
|
||||
<!-- Gazebo (gz-sim Harmonic) integration for ROS 2 Jazzy -->
|
||||
<exec_depend>ros_gz_sim</exec_depend>
|
||||
<exec_depend>ros_gz_bridge</exec_depend>
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="agv_pro">
|
||||
|
||||
<!-- Define vehicle dimensions -->
|
||||
<xacro:property name="vehicle_width" value="0.36"/> <!-- 车辆宽度 -->
|
||||
<xacro:property name="wheel_radius" value="0.05"/> <!-- 轮子半径 -->
|
||||
|
||||
<!-- Gazebo-specific properties -->
|
||||
<xacro:property name="wheel_damping" value="0.1"/>
|
||||
<xacro:property name="wheel_axis" value="0 1 0"/>
|
||||
|
||||
<!-- Base footprint -->
|
||||
<link name="base_footprint"/>
|
||||
|
||||
<joint name="base_joint" type="fixed">
|
||||
<parent link="base_footprint"/>
|
||||
<child link="base_link" />
|
||||
<origin xyz="0 0 0.020" rpy="0 0 0"/>
|
||||
</joint>
|
||||
|
||||
<link name="base_link">
|
||||
<inertial>
|
||||
<origin xyz="-0.0076254 -0.00023134 0.06693" rpy="0 0 0" />
|
||||
<mass value="19.236" />
|
||||
<inertia ixx="0.14436" ixy="0.0012037" ixz="0.0019458" iyy="0.24191" iyz="0.0044629" izz="0.33755" />
|
||||
</inertial>
|
||||
<visual>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="file://$(find agv_pro_gazebo)/meshes/base_link.stl" />
|
||||
</geometry>
|
||||
<material name=""/>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="file://$(find agv_pro_gazebo)/meshes/base_link.stl" />
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
|
||||
<!-- Include wheel macros & controller definitions -->
|
||||
<xacro:include filename="$(find agv_pro_gazebo)/urdf/parts/wheel_macro.xacro"/>
|
||||
|
||||
<!-- Wheels definition -->
|
||||
<!-- Right Rear Wheel -->
|
||||
<xacro:wheel name="right_rear_wheel" mesh="file://$(find agv_pro_gazebo)/meshes/wheel_rb_link.stl" origin_xyz="-0.1718 -0.1799 0.05188" origin_rpy="0 0 0" mass="0.21659" ixx="0.00051181" ixy="2.1577E-08" ixz="2.538E-07" iyy="0.00097519" iyz="-2.3635E-07" izz="0.00051178"/>
|
||||
|
||||
<!-- Right Front Wheel -->
|
||||
<xacro:wheel name="right_front_wheel" mesh="file://$(find agv_pro_gazebo)/meshes/wheel_rf_link.stl" origin_xyz="-0.17181 0.1799 0.051884" origin_rpy="0 0 0" mass="0.21659" ixx="0.00051181" ixy="2.1577E-08" ixz="2.538E-07" iyy="0.00097519" iyz="-2.3635E-07" izz="0.00051178"/>
|
||||
|
||||
<!-- Left Front Wheel -->
|
||||
<xacro:wheel name="left_front_wheel" mesh="file://$(find agv_pro_gazebo)/meshes/wheel_lf_link.stl" origin_xyz="0.17128 0.1799 0.052" origin_rpy="0 0 0" mass="0.3015" ixx="0.00052475" ixy="-2.2533E-07" ixz="-4.1904E-07" iyy="0.00099948" iyz="7.5332E-08" izz="0.00052362"/>
|
||||
|
||||
<!-- Left Rear Wheel -->
|
||||
<xacro:wheel name="left_rear_wheel" mesh="file://$(find agv_pro_gazebo)/meshes/wheel_lb_link.stl" origin_xyz="0.17128 -0.1799 0.052" origin_rpy="0 0 0" mass="0.29613" ixx="0.00051227" ixy="-2.0628E-07" ixz="-4.9074E-07" iyy="0.0009752" iyz="1.173E-07" izz="0.00051131"/>
|
||||
|
||||
|
||||
<!-- Lidar definition -->
|
||||
<link name="laser_link">
|
||||
<inertial>
|
||||
<origin xyz="-0.0035142 -2.8248E-05 0.0010013" rpy="0 0 0" />
|
||||
<mass value="0.049095" />
|
||||
<inertia ixx="2.0572E-05" ixy="8.5013E-08" ixz="2.0871E-07" iyy="2.0483E-05" iyz="-4.2154E-09" izz="3.4612E-05" />
|
||||
</inertial>
|
||||
<visual>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="file://$(find agv_pro_gazebo)/meshes/laser_link.stl" />
|
||||
</geometry>
|
||||
<material name=""/>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="file://$(find agv_pro_gazebo)/meshes/laser_link.stl" />
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
|
||||
<joint name="lidar_joint" type="fixed">
|
||||
<origin xyz="0.17891 0 0.20928" rpy="0 0 0" />
|
||||
<parent link="base_link" />
|
||||
<child link="laser_link" />
|
||||
</joint>
|
||||
|
||||
<!-- Include ros2_controller.xacro to define controllers -->
|
||||
<xacro:include filename="$(find agv_pro_gazebo)/urdf/ros2_controller.xacro"/>
|
||||
<xacro:ros2_controller/>
|
||||
</robot>
|
||||
@@ -1,91 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot xmlns:xacro="http://ros.org/wiki/xacro" name="agv_pro">
|
||||
|
||||
<!-- Gazebo-specific properties -->
|
||||
<xacro:property name="wheel_damping" value="0.1"/>
|
||||
<xacro:property name="wheel_axis" value="0 1 0"/>
|
||||
|
||||
<!-- Base footprint -->
|
||||
<link name="base_footprint"/>
|
||||
|
||||
<joint name="base_joint" type="fixed">
|
||||
<parent link="base_footprint"/>
|
||||
<child link="base_link" />
|
||||
<origin xyz="0 0 0.020" rpy="0 0 0"/>
|
||||
</joint>
|
||||
|
||||
<link name="base_link">
|
||||
<inertial>
|
||||
<origin xyz="-0.0076254 -0.00023134 0.06693" rpy="0 0 0" />
|
||||
<mass value="19.236" />
|
||||
<inertia ixx="0.14436" ixy="0.0012037" ixz="0.0019458" iyy="0.24191" iyz="0.0044629" izz="0.33755" />
|
||||
</inertial>
|
||||
<visual>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="model://agv_pro_description/meshes/base_link.stl" />
|
||||
</geometry>
|
||||
<material name="">
|
||||
<color rgba="1 1 1 1" />
|
||||
</material>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="model://agv_pro_description/meshes/base_link.stl" />
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
|
||||
<gazebo reference="base_link">
|
||||
<material>Gazebo/White</material>
|
||||
<mu1>1.0</mu1>
|
||||
<mu2>1.0</mu2>
|
||||
<kp>100000.0</kp>
|
||||
<kd>1.0</kd>
|
||||
</gazebo>
|
||||
|
||||
<!-- Include wheel macros & plugin -->
|
||||
<xacro:include filename="$(find agv_pro_description)/urdf/parts/wheel_macro.xacro"/>
|
||||
<xacro:include filename="$(find agv_pro_description)/urdf/parts/gazebo_control_plugin.xacro"/>
|
||||
|
||||
<!-- All four wheels with corrected mesh paths -->
|
||||
<xacro:wheel name="right_rear_wheel" mesh="model://agv_pro_description/meshes/wheel_rb_link.stl" origin_xyz="-0.1718 -0.1799 0.05188" origin_rpy="0 0 0" mass="0.21659" ixx="0.00051181" ixy="2.1577E-08" ixz="2.538E-07" iyy="0.00097519" iyz="-2.3635E-07" izz="0.00051178"/>
|
||||
<xacro:wheel name="right_front_wheel" mesh="model://agv_pro_description/meshes/wheel_rf_link.stl" origin_xyz="-0.17181 0.1799 0.051884" origin_rpy="0 0 0" mass="0.21659" ixx="0.00051181" ixy="2.1577E-08" ixz="2.538E-07" iyy="0.00097519" iyz="-2.3635E-07" izz="0.00051178"/>
|
||||
<xacro:wheel name="left_front_wheel" mesh="model://agv_pro_description/meshes/wheel_lf_link.stl" origin_xyz="0.17128 0.1799 0.052" origin_rpy="0 0 0" mass="0.3015" ixx="0.00052475" ixy="-2.2533E-07" ixz="-4.1904E-07" iyy="0.00099948" iyz="7.5332E-08" izz="0.00052362"/>
|
||||
<xacro:wheel name="left_rear_wheel" mesh="model://agv_pro_description/meshes/wheel_lb_link.stl" origin_xyz="0.17128 -0.1799 0.052" origin_rpy="0 0 0" mass="0.29613" ixx="0.00051227" ixy="-2.0628E-07" ixz="-4.9074E-07" iyy="0.0009752" iyz="1.173E-07" izz="0.00051131"/>
|
||||
|
||||
<!-- Lidar -->
|
||||
<link name="laser_link">
|
||||
<inertial>
|
||||
<origin xyz="-0.0035142 -2.8248E-05 0.0010013" rpy="0 0 0" />
|
||||
<mass value="0.049095" />
|
||||
<inertia ixx="2.0572E-05" ixy="8.5013E-08" ixz="2.0871E-07" iyy="2.0483E-05" iyz="-4.2154E-09" izz="3.4612E-05" />
|
||||
</inertial>
|
||||
<visual>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="model://agv_pro_description/meshes/laser_link.stl" />
|
||||
</geometry>
|
||||
<material name="">
|
||||
<color rgba="1 1 1 1" />
|
||||
</material>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="model://agv_pro_description/meshes/laser_link.stl" />
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
|
||||
<joint name="lidar_joint" type="fixed">
|
||||
<origin xyz="0.17891 0 0.20928" rpy="0 0 0" />
|
||||
<parent link="base_link" />
|
||||
<child link="laser_link" />
|
||||
</joint>
|
||||
|
||||
<!-- 插件调用 -->
|
||||
<xacro:gazebo_control_plugin/>
|
||||
|
||||
</robot>
|
||||
@@ -1,29 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
|
||||
<xacro:macro name="gazebo_control_plugin">
|
||||
<gazebo>
|
||||
<!-- 使用全向控制插件 -->
|
||||
<plugin filename="libgazebo_ros_planar_move.so" name="mecanum_drive_controller">
|
||||
<ros>
|
||||
<remapping>cmd_vel:=/cmd_vel</remapping>
|
||||
<remapping>odom:=/odom</remapping>
|
||||
</ros>
|
||||
|
||||
<!-- 配置全向控制 -->
|
||||
<frontLeftJoint>front_left_wheel_joint</frontLeftJoint> <!-- 前左轮 -->
|
||||
<frontRightJoint>front_right_wheel_joint</frontRightJoint> <!-- 前右轮 -->
|
||||
<rearLeftJoint>rear_left_wheel_joint</rearLeftJoint> <!-- 后左轮 -->
|
||||
<rearRightJoint>rear_right_wheel_joint</rearRightJoint> <!-- 后右轮 -->
|
||||
<wheelDiameter>0.1</wheelDiameter> <!-- 轮子直径 -->
|
||||
<wheelSeparation>0.36</wheelSeparation> <!-- 轮距(车辆宽度) -->
|
||||
|
||||
<torque>20</torque> <!-- 轮子扭矩 -->
|
||||
<topicName>cmd_vel</topicName> <!-- 控制命令话题 -->
|
||||
<odometryFrame>odom</odometryFrame> <!-- 里程计坐标系 -->
|
||||
<odometryTopic>odom</odometryTopic> <!-- 里程计话题 -->
|
||||
<robotBaseFrame>base_footprint</robotBaseFrame> <!-- 机器人基础坐标系 -->
|
||||
<publishOdomTF>true</publishOdomTF> <!-- 发布里程计变换 -->
|
||||
</plugin>
|
||||
</gazebo>
|
||||
</xacro:macro>
|
||||
</robot>
|
||||
@@ -1,64 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot xmlns:xacro="http://ros.org/wiki/xacro">
|
||||
|
||||
<xacro:macro name="wheel" params="name mesh origin_xyz origin_rpy mass ixx ixy ixz iyy iyz izz">
|
||||
|
||||
<link name="${name}_link">
|
||||
<inertial>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<mass value="${mass}" />
|
||||
<inertia ixx="${ixx}" ixy="${ixy}" ixz="${ixz}" iyy="${iyy}" iyz="${iyz}" izz="${izz}" />
|
||||
</inertial>
|
||||
<visual>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="${mesh}" />
|
||||
</geometry>
|
||||
<material name="gray">
|
||||
<color rgba="0.3 0.3 0.3 1"/>
|
||||
</material>
|
||||
</visual>
|
||||
<collision>
|
||||
<origin xyz="0 0 0" rpy="0 0 0" />
|
||||
<geometry>
|
||||
<mesh filename="${mesh}" />
|
||||
</geometry>
|
||||
</collision>
|
||||
</link>
|
||||
|
||||
<joint name="${name}_joint" type="continuous">
|
||||
<origin xyz="${origin_xyz}" rpy="${origin_rpy}" />
|
||||
<parent link="base_link" />
|
||||
<child link="${name}_link" />
|
||||
<axis xyz="0 1 0"/>
|
||||
<dynamics damping="0.1"/>
|
||||
</joint>
|
||||
|
||||
<!-- Correct transmission for ROS2 -->
|
||||
<transmission name="${name}_trans">
|
||||
<type>transmission_interface/SimpleTransmission</type>
|
||||
<joint name="${name}_joint">
|
||||
<hardwareInterface>hardware_interface/velocity</hardwareInterface>
|
||||
</joint>
|
||||
<actuator name="${name}_motor">
|
||||
<mechanicalReduction>1</mechanicalReduction>
|
||||
<hardwareInterface>hardware_interface/velocity</hardwareInterface>
|
||||
</actuator>
|
||||
</transmission>
|
||||
|
||||
<gazebo reference="${name}_link">
|
||||
<mu1>0.8</mu1>
|
||||
<mu2>0.8</mu2>
|
||||
<kp>100000.0</kp>
|
||||
<kd>1.0</kd>
|
||||
<visual>
|
||||
<material>
|
||||
<ambient>0.1 0.1 0.1 1</ambient>
|
||||
<diffuse>0.1 0.1 0.1 1</diffuse>
|
||||
<specular>0.1 0.1 0.1 1</specular>
|
||||
</material>
|
||||
</visual>
|
||||
</gazebo>
|
||||
|
||||
</xacro:macro>
|
||||
</robot>
|
||||
@@ -1,43 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
|
||||
<xacro:macro name="ros2_controller">
|
||||
<!-- ros2_control hardware description for gz-sim (Gazebo Harmonic) -->
|
||||
<ros2_control name="GazeboSimSystem" type="system">
|
||||
<hardware>
|
||||
<plugin>gz_ros2_control/GazeboSimSystem</plugin>
|
||||
</hardware>
|
||||
|
||||
<joint name="left_front_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
|
||||
<joint name="right_front_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
|
||||
<joint name="left_rear_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
|
||||
<joint name="right_rear_wheel_joint">
|
||||
<command_interface name="velocity"/>
|
||||
<state_interface name="position"/>
|
||||
<state_interface name="velocity"/>
|
||||
</joint>
|
||||
</ros2_control>
|
||||
|
||||
<!-- gz_ros2_control system plugin: hosts the controller_manager inside gz-sim -->
|
||||
<gazebo>
|
||||
<plugin filename="gz_ros2_control-system"
|
||||
name="gz_ros2_control::GazeboSimROS2ControlPlugin">
|
||||
<parameters>$(find agv_pro_gazebo)/config/agv_control.yaml</parameters>
|
||||
</plugin>
|
||||
</gazebo>
|
||||
</xacro:macro>
|
||||
</robot>
|
||||
Reference in New Issue
Block a user