feat: ROS2 support

#34
This commit is contained in:
fan-ziqi 2024-11-08 17:52:03 +08:00
parent 1a92a2a10c
commit 64fc72d613
132 changed files with 2315 additions and 7214 deletions

2
.gitignore vendored
View File

@ -1,6 +1,8 @@
build
devel
logs
install
log
.catkin_tools
.vscode
*.csv

View File

@ -2,10 +2,13 @@
[中文文档](README_CN.md)
**Version Select: [ROS-Noetic](https://github.com/fan-ziqi/rl_sar/tree/main) | [ROS2-Foxy](https://github.com/fan-ziqi/rl_sar/tree/ros2)**
This repository provides a framework for simulation verification and physical deployment of robot reinforcement learning algorithms, suitable for quadruped robots, wheeled robots, and humanoid robots. "sar" stands for "simulation and real"
feature:
- Support legged_gym based on IaacGym and IsaacLab based on IsaacSim. Use `framework` to distinguish.
- The code has two versions: **ROS** and **ROS2**
- The code supports both cpp and python, you can find python version in `src/rl_sar/scripts`
[Click to discuss on Discord](https://discord.gg/vmVjkhVugU)
@ -20,10 +23,10 @@ git clone https://github.com/fan-ziqi/rl_sar.git
## Dependency
This project uses `ros-noetic` (Ubuntu 20.04) and requires the installation of the following ROS dependency packages:
This project uses `ros2-foxy` (Ubuntu 20.04) and requires the installation of the following ROS dependency packages:
```bash
sudo apt install ros-noetic-teleop-twist-keyboard ros-noetic-controller-interface ros-noetic-gazebo-ros-control ros-noetic-joint-state-controller ros-noetic-effort-controllers ros-noetic-joint-trajectory-controller
sudo apt install ros-$ROS_DISTRO-teleop-twist-keyboard ros-$ROS_DISTRO-ros2-control ros-$ROS_DISTRO-ros2-controllers ros-$ROS_DISTRO-control-toolbox ros-$ROS_DISTRO-robot-state-publisher ros-$ROS_DISTRO-joint-state-publisher-gui ros-$ROS_DISTRO-gazebo-ros2-control ros-$ROS_DISTRO-gazebo-ros-pkgs ros-$ROS_DISTRO-xacro
```
Download and deploy `libtorch` at any location
@ -72,14 +75,17 @@ Compile in the root directory of the project
```bash
cd ..
catkin build
colcon build --merge-install --symlink-install
```
If catkin build report errors: `Unable to find either executable 'empy' or Python module 'em'`, run `catkin config -DPYTHON_EXECUTABLE=/usr/bin/python3` before `catkin build`
## Running
In the following text, **\<ROBOT\>_\<PLATFORM\>** is used to represent different environments, which can be `a1_isaacgym`, `a1_isaacsim`, `go2_isaacgym`, `gr1t1_isaacgym`, or `gr1t2_isaacgym`.
In the following text, **\<ROBOT\>_\<PLATFORM\>** is used to represent different environments. Currently supported list:
| | isaacgym | isaacsim |
|-------|----------|----------|
| a1 | ✓ | ✓ |
| go2 | ✓ | |
Before running, copy the trained pt model file to `rl_sar/src/rl_sar/models/<ROBOT>_<PLATFORM>`, and configure the parameters in `config.yaml`.
@ -88,24 +94,25 @@ Before running, copy the trained pt model file to `rl_sar/src/rl_sar/models/<ROB
Open a terminal, launch the gazebo simulation environment
```bash
source devel/setup.bash
roslaunch rl_sar gazebo_<ROBOT>_<PLATFORM>.launch
source install/setup.bash
ros2 launch rl_sar gazebo.launch.py rname:=<ROBOT> framework:=<PLATFORM>
(e.g. ros2 launch rl_sar gazebo.launch.py rname:=a1 framework:=isaacgym)
```
Open a new terminal, launch the control program
```bash
source devel/setup.bash
(for cpp version) rosrun rl_sar rl_sim
(for python version) rosrun rl_sar rl_sim.py
source install/setup.bash
(for cpp version) ros2 run rl_sar rl_sim
(for python version) ros2 run rl_sar rl_sim.py
```
Control:
* Press **\<Enter\>** to toggle simulation start/stop.
<!-- * Press **\<Enter\>** to toggle simulation start/stop. -->
* **W** and **S** controls x-axis, **A** and **D** controls yaw, and **J** and **L** controls y-axis.
* Press **\<Space\>** to sets all control commands to zero.
* If robot falls down, press **R** to reset Gazebo environment.
<!-- * If robot falls down, press **R** to reset Gazebo environment. -->
### Real Robots
@ -119,8 +126,8 @@ Unitree A1 can be connected using both wireless and wired methods:
Open a new terminal and start the control program
```bash
source devel/setup.bash
rosrun rl_sar rl_real_a1
source install/local.bash
ros2 run rl_sar rl_real_a1
```
Press the **R2** button on the controller to switch the robot to the default standing position, press **R1** to switch to RL control mode, and press **L2** in any state to switch to the initial lying position. The left stick controls x-axis up and down, controls yaw left and right, and the right stick controls y-axis left and right.
@ -133,8 +140,8 @@ Or press **0** on the keyboard to switch the robot to the default standing posit
2. Use the `ifconfig` command to find the name of the network interface for the 123 network segment, such as `enxf8e43b808e06`. In the following steps, replace `<YOUR_NETWORK_INTERFACE>` with the actual network interface name.
3. Open a new terminal and start the control program:
```bash
source devel/setup.bash
rosrun rl_sar rl_real_go2 <YOUR_NETWORK_INTERFACE>
source install/local.bash
ros2 run rl_sar rl_real_go2 <YOUR_NETWORK_INTERFACE>
```
4. Go2 supports both joy and keyboard control, using the same method as mentioned above for A1.
@ -146,11 +153,11 @@ Take A1 as an example below
2. Run the control program, and the program will log all data after execution.
3. Stop the control program and start training the actuator network. Note that `rl_sar/src/rl_sar/models/` is omitted before the following paths.
```bash
rosrun rl_sar actuator_net.py --mode train --data a1/motor.csv --output a1/motor.pt
ros2 run rl_sar actuator_net.py --mode train --data a1/motor.csv --output a1/motor.pt
```
4. Verify the trained actuator network.
```bash
rosrun rl_sar actuator_net.py --mode play --data a1/motor.csv --output a1/motor.pt
ros2 run rl_sar actuator_net.py --mode play --data a1/motor.csv --output a1/motor.pt
```
## Add Your Robot
@ -160,8 +167,8 @@ In the following text, **\<ROBOT\>_\<PLATFORM\>** is used to represent your robo
1. Create a model package named `<ROBOT>_description` in the `rl_sar/src/robots` directory. Place the robot's URDF file in the `rl_sar/src/robots/<ROBOT>_description/urdf` directory and name it `<ROBOT>.urdf`. Additionally, create a joint configuration file with the namespace `<ROBOT>_gazebo` in the `rl_sar/src/robots/<ROBOT>_description/config` directory.
2. Place the trained RL model files in the `rl_sar/src/rl_sar/models/<ROBOT>_<PLATFORM>` directory, and create a new `config.yaml` file in this path. Refer to the `rl_sar/src/rl_sar/models/a1_isaacgym/config.yaml` file to modify the parameters.
3. Modify the `forward()` function in the code as needed to adapt to different models.
4. If you need to run simulations, modify the launch files as needed by referring to those in the `rl_sar/src/rl_sar/launch` directory.
5. If you need to run on the physical robot, modify the file `rl_sar/src/rl_sar/src/rl_real_a1.cpp` as needed.
<!-- 4. If you need to run simulations, modify the launch files as needed by referring to those in the `rl_sar/src/rl_sar/launch` directory. -->
4. If you need to run on the physical robot, modify the file `rl_sar/src/rl_sar/src/rl_real_a1.cpp` as needed.
## Contributing

View File

@ -2,10 +2,13 @@
[English document](README.md)
**版本选择: [ROS-Noetic](https://github.com/fan-ziqi/rl_sar/tree/main) | [ROS2-Foxy](https://github.com/fan-ziqi/rl_sar/tree/ros2)**
本仓库提供了机器人强化学习算法的仿真验证与实物部署框架,适配四足机器人、轮足机器人、人形机器人。"sar"代表"simulation and real"
特性:
- 支持基于IaacGym的legged_gym也支持基于IsaacSim的IsaacLab用`framework`加以区分。
- 代码有**ROS**和**ROS2**两个版本
- 代码有python和cpp两个版本python版本可以在`src/rl_sar/scripts`中找到
[点击在Discord上讨论](https://discord.gg/MC9KguQHtt)
@ -20,10 +23,10 @@ git clone https://github.com/fan-ziqi/rl_sar.git
## 依赖
本项目使用`ros-noetic`(Ubuntu20.04)且需要安装以下的ros依赖包
本项目使用`ros2-foxy`(Ubuntu20.04)且需要安装以下的ros依赖包
```bash
sudo apt install ros-noetic-teleop-twist-keyboard ros-noetic-controller-interface ros-noetic-gazebo-ros-control ros-noetic-joint-state-controller ros-noetic-effort-controllers ros-noetic-joint-trajectory-controller
sudo apt install ros-$ROS_DISTRO-teleop-twist-keyboard ros-$ROS_DISTRO-ros2-control ros-$ROS_DISTRO-ros2-controllers ros-$ROS_DISTRO-control-toolbox ros-$ROS_DISTRO-robot-state-publisher ros-$ROS_DISTRO-joint-state-publisher-gui ros-$ROS_DISTRO-gazebo-ros2-control ros-$ROS_DISTRO-gazebo-ros-pkgs ros-$ROS_DISTRO-xacro
```
在任意位置下载并部署`libtorch`
@ -72,14 +75,17 @@ sudo ldconfig
```bash
cd ..
catkin build
colcon build --merge-install --symlink-install
```
如果 catkin build 报错: `Unable to find either executable 'empy' or Python module 'em'`, 在`catkin build` 之前执行 `catkin config -DPYTHON_EXECUTABLE=/usr/bin/python3`
## 运行
下文中使用 **\<ROBOT\>_\<PLATFORM\>** 代替表示不同的环境,可以是 `a1_isaacgym``a1_isaacsim``go2_isaacgym``gr1t1_isaacgym``gr1t2_isaacgym`
下文中使用 **\<ROBOT\>** 和 **\<PLATFORM\>** 代替表示不同的机器人和框架。目前支持列表:
| | isaacgym | isaacsim |
|-------|----------|----------|
| a1 | ✓ | ✓ |
| go2 | ✓ | |
运行前请将训练好的pt模型文件拷贝到`rl_sar/src/rl_sar/models/<ROBOT>_<PLATFORM>`中,并配置`config.yaml`中的参数。
@ -88,24 +94,25 @@ catkin build
打开一个终端启动gazebo仿真环境
```bash
source devel/setup.bash
roslaunch rl_sar gazebo_<ROBOT>_<PLATFORM>.launch
source install/setup.bash
ros2 launch rl_sar gazebo.launch.py rname:=<ROBOT> framework:=<PLATFORM>
(e.g. ros2 launch rl_sar gazebo.launch.py rname:=a1 framework:=isaacgym)
```
打开一个新终端,启动控制程序
```bash
source devel/setup.bash
(for cpp version) rosrun rl_sar rl_sim
(for python version) rosrun rl_sar rl_sim.py
source install/setup.bash
(for cpp version) ros2 run rl_sar rl_sim
(for python version) ros2 run rl_sar rl_sim.py
```
控制:
* 按 **\<Enter\>** 切换仿真器运行/停止。
* **W****S** 控制x轴**A** 和 **D** 控制yaw轴**J** 和 **L** 控制y轴,按下空格重置控制指令
<!-- * 按 **\<Enter\>** 切换仿真器运行/停止。 -->
* **W****S** 控制x轴**A** 和 **D** 控制yaw轴**J** 和 **L** 控制y轴。
* 按 **\<Space\>** 将所有控制指令设置为零。
* 如果机器人摔倒,按 **R** 重置Gazebo环境。
<!-- * 如果机器人摔倒,按 **R** 重置Gazebo环境。 -->
### 真实机器人
@ -119,8 +126,8 @@ source devel/setup.bash
新建终端,启动控制程序
```bash
source devel/setup.bash
rosrun rl_sar rl_real_a1
source install/local.bash
ros2 run rl_sar rl_real_a1
```
按下遥控器的**R2**键让机器人切换到默认站起姿态,按下**R1**键切换到RL控制模式任意状态按下**L2**切换到最初的趴下姿态。左摇杆上下控制x左右控制yaw右摇杆左右控制y。
@ -133,8 +140,8 @@ rosrun rl_sar rl_real_a1
2. 通过`ifconfig`命令查看123网段的网卡名字如`enxf8e43b808e06`,下文用 \<YOUR_NETWORK_INTERFACE\> 代替
3. 新建终端,启动控制程序
```bash
source devel/setup.bash
rosrun rl_sar rl_real_go2 <YOUR_NETWORK_INTERFACE>
source install/local.bash
ros2 run rl_sar rl_real_go2 <YOUR_NETWORK_INTERFACE>
```
4. Go2支持手柄与键盘控制方法与上面a1相同
@ -144,13 +151,13 @@ rosrun rl_sar rl_real_a1
1. 取消注释`rl_real_a1.cpp`中最上面的`#define CSV_LOGGER`,你也可以在仿真程序中修改对应部分采集仿真数据用来测试训练过程。
2. 运行控制程序,程序会在执行后记录所有数据。
3. 停止控制程序,开始训练执行器网络。注意,下面的路径前均省略了`rl_sar/src/rl_sar/models/`。
3. 停止控制程序,开始训练执行器网络。
```bash
rosrun rl_sar actuator_net.py --mode train --data a1/motor.csv --output a1/motor.pt
ros2 run rl_sar actuator_net.py --mode train --data a1_isaacgym/motor.csv --output a1_isaacgym/motor.pt
```
4. 验证已经训练好的训练执行器网络。
```bash
rosrun rl_sar actuator_net.py --mode play --data a1/motor.csv --output a1/motor.pt
ros2 run rl_sar actuator_net.py --mode play --data a1_isaacgym/motor.csv --output a1_isaacgym/motor.pt
```
## 添加你的机器人
@ -160,8 +167,8 @@ rosrun rl_sar rl_real_a1
1. 在`rl_sar/src/robots`路径下创建名为`<ROBOT>_description`的模型包将模型的urdf放到`rl_sar/src/robots/<ROBOT>_description/urdf`路径下并命名为`<ROBOT>.urdf`,并在`rl_sar/src/robots/<ROBOT>_description/config`路径下创建命名空间为`<ROBOT>_gazebo`的关节配置文件
2. 将训练好的RL模型文件放到`rl_sar/src/rl_sar/models/<ROBOT>_<PLATFORM>`路径下并在此路径中新建config.yaml文件参考`rl_sar/src/rl_sar/models/a1_isaacgym/config.yaml`文件修改其中参数
3. 按需修改代码中的`forward()`函数,以适配不同的模型
4. 若需要运行仿真,则参考`rl_sar/src/rl_sar/launch`路径下的launch文件自行修改
5. 若需要运行实物,则参考`rl_sar/src/rl_sar/src/rl_real_a1.cpp`文件自行修改
<!-- 4. 若需要运行仿真,则参考`rl_sar/src/rl_sar/launch`路径下的launch文件自行修改 -->
4. 若需要运行实物,则参考`rl_sar/src/rl_sar/src/rl_real_a1.cpp`文件自行修改
## 贡献

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0.2)
cmake_minimum_required(VERSION 3.5)
project(rl_sar)
add_definitions(-DCMAKE_CURRENT_SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}")
@ -10,33 +10,27 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TORCH_CXX_FLAGS}")
find_package(Torch REQUIRED)
set(CMAKE_INSTALL_RPATH "${Torch_DIR}/lib")
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GAZEBO_CXX_FLAGS}")
find_package(gazebo REQUIRED)
find_package(catkin REQUIRED COMPONENTS
controller_manager
genmsg
joint_state_controller
robot_state_publisher
roscpp
gazebo_ros
std_msgs
tf
geometry_msgs
robot_msgs
robot_joint_controller
rospy
)
find_package(ament_cmake REQUIRED)
find_package(joint_state_controller REQUIRED)
find_package(robot_state_publisher REQUIRED)
find_package(rclcpp REQUIRED)
find_package(gazebo_ros REQUIRED)
find_package(std_msgs REQUIRED)
find_package(robot_msgs REQUIRED)
find_package(robot_joint_controller REQUIRED)
find_package(rclpy REQUIRED)
find_package(gazebo_msgs REQUIRED)
find_package(std_srvs REQUIRED)
find_package(Python3 COMPONENTS Interpreter Development REQUIRED)
catkin_package(
CATKIN_DEPENDS
robot_joint_controller
rospy
)
link_directories(/usr/local/lib)
include_directories(${YAML_CPP_INCLUDE_DIR})
@ -44,6 +38,11 @@ include_directories(${YAML_CPP_INCLUDE_DIR})
include_directories(library/unitree_legged_sdk_3.2/include)
link_directories(library/unitree_legged_sdk_3.2/lib)
set(UNITREE_A1_LIBS -pthread unitree_legged_sdk_amd64 lcm)
file(GLOB GLOB_UNITREE_LEGGED_SDK "${PROJECT_SOURCE_DIR}/library/unitree_legged_sdk_3.2/lib/*.so")
install(FILES
${GLOB_UNITREE_LEGGED_SDK}
DESTINATION lib/
)
# Unitree Go2
include_directories(library/unitree_sdk2/include)
@ -52,10 +51,16 @@ include_directories(library/unitree_sdk2/thirdparty/include)
include_directories(library/unitree_sdk2/thirdparty/include/ddscxx)
link_directories(library/unitree_sdk2/thirdparty/lib/x86_64)
set(UNITREE_GO2_LIBS -pthread unitree_sdk2 ddsc ddscxx)
file(GLOB GLOB_UNITREE_SDK2 "${PROJECT_SOURCE_DIR}/library/unitree_sdk2/lib/x86_64/*.so")
file(GLOB GLOB_UNITREE_SDK2_THIRDPARTY "${PROJECT_SOURCE_DIR}/library/unitree_sdk2/thirdparty/lib/x86_64/*.so")
install(FILES
${GLOB_UNITREE_SDK2_THIRDPARTY}
${GLOB_UNITREE_SDK2_THIRDPARTY}
DESTINATION lib/
)
include_directories(
include
${catkin_INCLUDE_DIRS}
library/matplotlibcpp
library/observation_buffer
library/rl_sdk
@ -78,24 +83,53 @@ set_property(TARGET observation_buffer PROPERTY CXX_STANDARD 14)
add_executable(rl_sim src/rl_sim.cpp )
target_link_libraries(rl_sim
${catkin_LIBRARIES} -pthread
-pthread
rl_sdk observation_buffer yaml-cpp
)
add_executable(rl_real_a1 src/rl_real_a1.cpp )
target_link_libraries(rl_real_a1
${catkin_LIBRARIES} ${UNITREE_A1_LIBS}
${UNITREE_A1_LIBS}
rl_sdk observation_buffer yaml-cpp
)
add_executable(rl_real_go2 src/rl_real_go2.cpp )
target_link_libraries(rl_real_go2
${catkin_LIBRARIES} ${UNITREE_GO2_LIBS}
${UNITREE_GO2_LIBS}
rl_sdk observation_buffer yaml-cpp
)
catkin_install_python(PROGRAMS
ament_target_dependencies(rl_sim
joint_state_controller
robot_state_publisher
rclcpp
gazebo_ros
std_msgs
robot_msgs
robot_joint_controller
rclpy
gazebo_msgs
std_srvs
)
install(TARGETS
rl_sim
rl_sdk
observation_buffer
rl_real_a1
rl_real_go2
DESTINATION lib/${PROJECT_NAME}
)
install(PROGRAMS
scripts/rl_sim.py
scripts/actuator_net.py
DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
)
DESTINATION lib/${PROJECT_NAME}
)
install(
DIRECTORY launch worlds models
DESTINATION share/${PROJECT_NAME}/
)
ament_package()

View File

@ -4,19 +4,22 @@
#include "rl_sdk.hpp"
#include "observation_buffer.hpp"
#include "loop.hpp"
#include <ros/ros.h>
#include <gazebo_msgs/ModelStates.h>
#include <sensor_msgs/JointState.h>
#include "std_srvs/Empty.h"
#include <geometry_msgs/Twist.h>
#include "robot_msgs/MotorCommand.h"
#include "robot_msgs/msg/robot_command.hpp"
#include "robot_msgs/msg/robot_state.hpp"
#include <rclcpp/rclcpp.hpp>
#include <sensor_msgs/msg/joint_state.hpp>
#include <sensor_msgs/msg/imu.hpp>
#include <geometry_msgs/msg/twist.hpp>
#include <std_srvs/srv/empty.hpp>
#include <gazebo_msgs/srv/set_model_state.hpp>
#include <rcl_interfaces/srv/get_parameters.hpp>
#include <csignal>
#include <gazebo_msgs/SetModelState.h>
#include "matplotlibcpp.h"
namespace plt = matplotlibcpp;
class RL_Sim : public RL
class RL_Sim : public RL, public rclcpp::Node
{
public:
RL_Sim();
@ -48,29 +51,27 @@ private:
// ros interface
std::string ros_namespace;
geometry_msgs::Twist vel;
geometry_msgs::Pose pose;
geometry_msgs::Twist cmd_vel;
ros::Subscriber model_state_subscriber;
ros::Subscriber joint_state_subscriber;
ros::Subscriber cmd_vel_subscriber;
ros::ServiceClient gazebo_set_model_state_client;
ros::ServiceClient gazebo_pause_physics_client;
ros::ServiceClient gazebo_unpause_physics_client;
std::map<std::string, ros::Publisher> joint_publishers;
std::vector<robot_msgs::MotorCommand> joint_publishers_commands;
void ModelStatesCallback(const gazebo_msgs::ModelStates::ConstPtr &msg);
void JointStatesCallback(const sensor_msgs::JointState::ConstPtr &msg);
void CmdvelCallback(const geometry_msgs::Twist::ConstPtr &msg);
sensor_msgs::msg::Imu gazebo_imu;
geometry_msgs::msg::Twist cmd_vel;
robot_msgs::msg::RobotCommand robot_command_publisher_msg;
robot_msgs::msg::RobotState robot_state_subscriber_msg;
rclcpp::Subscription<sensor_msgs::msg::Imu>::SharedPtr gazebo_imu_subscriber;
rclcpp::Subscription<sensor_msgs::msg::JointState>::SharedPtr joint_state_subscriber;
rclcpp::Subscription<geometry_msgs::msg::Twist>::SharedPtr cmd_vel_subscriber;
rclcpp::Client<gazebo_msgs::srv::SetModelState>::SharedPtr gazebo_set_model_state_client;
rclcpp::Client<std_srvs::srv::Empty>::SharedPtr gazebo_pause_physics_client;
rclcpp::Client<std_srvs::srv::Empty>::SharedPtr gazebo_unpause_physics_client;
rclcpp::Publisher<robot_msgs::msg::RobotCommand>::SharedPtr robot_command_publisher;
rclcpp::Subscription<robot_msgs::msg::RobotState>::SharedPtr robot_state_subscriber;
rclcpp::Client<rcl_interfaces::srv::GetParameters>::SharedPtr param_client;
void GazeboImuCallback(const sensor_msgs::msg::Imu::SharedPtr msg);
void CmdvelCallback(const geometry_msgs::msg::Twist::SharedPtr msg);
void RobotStateCallback(const robot_msgs::msg::RobotState::SharedPtr msg);
// others
std::string gazebo_model_name;
int motiontime = 0;
std::map<std::string, size_t> sorted_to_original_index;
std::vector<double> mapped_joint_positions;
std::vector<double> mapped_joint_velocities;
std::vector<double> mapped_joint_efforts;
void MapData(const std::vector<double> &source_data, std::vector<double> &target_data);
};
#endif // RL_SIM_HPP

View File

@ -0,0 +1,94 @@
import os
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, DeclareLaunchArgument
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch.substitutions import LaunchConfiguration, TextSubstitution, Command
from launch_ros.actions import Node
from launch_ros.parameter_descriptions import ParameterValue
from ament_index_python.packages import get_package_share_directory
def generate_launch_description():
rname = LaunchConfiguration("rname")
framework = LaunchConfiguration("framework")
wname = "stair"
robot_name = ParameterValue(Command(["echo -n ", rname, "_", framework]), value_type=str)
ros_namespace = ParameterValue(Command(["echo -n ", "/", rname, "_gazebo"]), value_type=str)
gazebo_model_name = ParameterValue(Command(["echo -n ", rname, "_gazebo"]), value_type=str)
robot_description = ParameterValue(
Command([
"xacro ",
Command(["echo -n ", Command(["ros2 pkg prefix ", rname, "_description"])]),
"/share/", rname, "_description/xacro/robot.xacro"
]),
value_type=str
)
robot_state_publisher_node = Node(
package="robot_state_publisher",
executable="robot_state_publisher",
name="robot_state_publisher",
output="screen",
parameters=[{"robot_description": robot_description}],
)
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(get_package_share_directory("gazebo_ros"), "launch", "gazebo.launch.py")
),
launch_arguments={
"verbose": "false",
"world": os.path.join(get_package_share_directory("rl_sar"), "worlds", wname + ".world"),
}.items(),
)
spawn_entity = Node(
package="gazebo_ros",
executable="spawn_entity.py",
arguments=["-topic", "/robot_description", "-entity", "robot_model"],
output="screen",
)
joint_state_broadcaster_node = Node(
package="controller_manager",
executable="spawner.py",
arguments=["joint_state_broadcaster"],
output="screen",
)
robot_joint_controller_node = Node(
package="controller_manager",
executable="spawner.py",
arguments=["robot_joint_controller"],
output="screen",
)
param_node = Node(
package="demo_nodes_cpp",
executable="parameter_blackboard",
name="param_node",
parameters=[{
"robot_name": robot_name,
"gazebo_model_name": gazebo_model_name,
}],
)
return LaunchDescription([
DeclareLaunchArgument(
"rname",
description="Robot name (e.g., a1, go2)",
default_value=TextSubstitution(text=""),
),
DeclareLaunchArgument(
"framework",
description="Framework (isaacgym or isaacsim)",
default_value=TextSubstitution(text=""),
),
robot_state_publisher_node,
gazebo,
spawn_entity,
joint_state_broadcaster_node,
robot_joint_controller_node,
param_node,
])

View File

@ -486,6 +486,7 @@ void RL::CSVInit(std::string robot_name)
// csv_filename += "_" + timestamp;
csv_filename += ".csv";
std::cout << LOGGER::INFO << "Recording motor data in " << csv_filename << std::endl;
std::ofstream file(csv_filename.c_str());
for(int i = 0; i < 12; ++i) { file << "tau_cal_" << i << ","; }

View File

@ -11,10 +11,10 @@
namespace LOGGER
{
const char *const INFO = "\033[0;37m[INFO]\033[0m ";
const char *const WARNING = "\033[0;33m[WARNING]\033[0m ";
const char *const ERROR = "\033[0;31m[ERROR]\033[0m ";
const char *const DEBUG = "\033[0;32m[DEBUG]\033[0m ";
const std::string INFO = "\033[0;37m[INFO]\033[0m ";
const std::string WARNING = "\033[0;33m[WARNING]\033[0m ";
const std::string ERROR = "\033[0;31m[ERROR]\033[0m ";
const std::string DEBUG = "\033[0;32m[DEBUG]\033[0m ";
}
template <typename T>
@ -45,7 +45,7 @@ struct RobotState
std::vector<T> q = std::vector<T>(32, 0.0);
std::vector<T> dq = std::vector<T>(32, 0.0);
std::vector<T> ddq = std::vector<T>(32, 0.0);
std::vector<T> tauEst = std::vector<T>(32, 0.0);
std::vector<T> tau_est = std::vector<T>(32, 0.0);
std::vector<T> cur = std::vector<T>(32, 0.0);
} motor_state;
};
@ -156,7 +156,7 @@ public:
// others
std::string robot_name;
STATE running_state = STATE_RL_RUNNING; // default running_state set to STATE_RL_RUNNING
bool simulation_running = false;
bool simulation_running = true;
// protect func
void TorqueProtect(torch::Tensor origin_output_torques);

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<package format="2">
<package format="3">
<name>rl_sar</name>
<version>2.0.0</version>
<description>The rl_sar package</description>
@ -8,29 +8,19 @@
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<buildtool_depend>genmsg</buildtool_depend>
<build_depend>controller_manager</build_depend>
<build_depend>joint_state_controller</build_depend>
<build_depend>robot_state_publisher</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>controller_manager</build_export_depend>
<build_export_depend>joint_state_controller</build_export_depend>
<build_export_depend>robot_state_publisher</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>controller_manager</exec_depend>
<exec_depend>joint_state_controller</exec_depend>
<exec_depend>robot_state_publisher</exec_depend>
<exec_depend>roscpp</exec_depend>
<exec_depend>std_msgs</exec_depend>
<build_depend>rospy</build_depend>
<exec_depend>rospy</exec_depend>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>std_msgs</depend>
<depend>gazebo_ros</depend>
<depend>yaml-cpp</depend>
<depend>robot_msgs</depend>
<depend>robot_joint_controller</depend>
<depend>controller_manager</depend>
<depend>joint_state_controller</depend>
<depend>robot_state_publisher</depend>
<depend>rospy</depend>
<export>
<build_type>ament_cmake</build_type>
</export>
</package>

4
src/rl_sar/scripts/actuator_net.py Normal file → Executable file
View File

@ -1,3 +1,4 @@
#!/usr/bin/env python3
import os
import argparse
from matplotlib import pyplot as plt
@ -8,8 +9,9 @@ import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
from torch.optim import Adam
import pandas as pd
from ament_index_python.packages import get_package_share_directory
BASE_PATH = os.path.join(os.path.dirname(__file__), "../")
BASE_PATH = os.path.join(get_package_share_directory('rl_sar'))
class Config:
def __init__(self):

0
src/rl_sar/scripts/observation_buffer.py Normal file → Executable file
View File

17
src/rl_sar/scripts/rl_sdk.py Normal file → Executable file
View File

@ -41,7 +41,7 @@ class RobotState:
self.q = [0.0] * 32
self.dq = [0.0] * 32
self.ddq = [0.0] * 32
self.tauEst = [0.0] * 32
self.tau_est = [0.0] * 32
self.cur = [0.0] * 32
class STATE(Enum):
@ -123,7 +123,7 @@ class RL:
# others
self.robot_name = ""
self.running_state = STATE.STATE_RL_RUNNING # default running_state set to STATE_RL_RUNNING
self.simulation_running = False
self.simulation_running = True
### protected in cpp ###
# rl module
@ -228,10 +228,10 @@ class RL:
self.getup_percent = min(self.getup_percent, 1.0)
for i in range(self.params.num_of_dofs):
command.motor_command.q[i] = (1 - self.getup_percent) * self.now_state.motor_state.q[i] + self.getup_percent * self.params.default_dof_pos[0][i].item()
command.motor_command.dq[i] = 0
command.motor_command.dq[i] = 0.0
command.motor_command.kp[i] = self.params.fixed_kp[0][i].item()
command.motor_command.kd[i] = self.params.fixed_kd[0][i].item()
command.motor_command.tau[i] = 0
command.motor_command.tau[i] = 0.0
print("\r" + LOGGER.INFO + f"Getting up {self.getup_percent * 100.0:.1f}", end='', flush=True)
if self.control.control_state == STATE.STATE_RL_INIT:
@ -261,10 +261,10 @@ class RL:
print("\r" + LOGGER.INFO + f"RL Controller x: {self.control.x:.1f} y: {self.control.y:.1f} yaw: {self.control.yaw:.1f}", end='', flush=True)
for i in range(self.params.num_of_dofs):
command.motor_command.q[i] = self.output_dof_pos[0][i].item()
command.motor_command.dq[i] = 0
command.motor_command.dq[i] = 0.0
command.motor_command.kp[i] = self.params.rl_kp[0][i].item()
command.motor_command.kd[i] = self.params.rl_kd[0][i].item()
command.motor_command.tau[i] = 0
command.motor_command.tau[i] = 0.0
if self.control.control_state == STATE.STATE_POS_GETDOWN:
self.control.control_state = STATE.STATE_WAITING
@ -289,10 +289,10 @@ class RL:
self.getdown_percent = min(1.0, self.getdown_percent)
for i in range(self.params.num_of_dofs):
command.motor_command.q[i] = (1 - self.getdown_percent) * self.now_state.motor_state.q[i] + self.getdown_percent * self.start_state.motor_state.q[i]
command.motor_command.dq[i] = 0
command.motor_command.dq[i] = 0.0
command.motor_command.kp[i] = self.params.fixed_kp[0][i].item()
command.motor_command.kd[i] = self.params.fixed_kd[0][i].item()
command.motor_command.tau[i] = 0
command.motor_command.tau[i] = 0.0
print("\r" + LOGGER.INFO + f"Getting down {self.getdown_percent * 100.0:.1f}", end='', flush=True)
if self.getdown_percent == 1:
@ -424,6 +424,7 @@ class RL:
# self.csv_filename += f"_{timestamp}"
self.csv_filename += ".csv"
print(LOGGER.INFO + f"Recording motor data in '{os.path.abspath(self.csv_filename)}'")
with open(self.csv_filename, 'w', newline='') as file:
writer = csv.writer(file)

223
src/rl_sar/scripts/rl_sim.py Normal file → Executable file
View File

@ -1,90 +1,94 @@
import sys
#!/usr/bin/env python3
import os
import torch
import threading
import time
import rospy
import numpy as np
from gazebo_msgs.msg import ModelStates
from sensor_msgs.msg import JointState
from geometry_msgs.msg import Twist, Pose
from robot_msgs.msg import MotorCommand
from gazebo_msgs.srv import SetModelState, SetModelStateRequest
import rclpy
from rclpy.node import Node
from rclpy.qos import qos_profile_system_default
from sensor_msgs.msg import Imu
from geometry_msgs.msg import Twist
from robot_msgs.msg import RobotCommand as RobotCommandMsg
from robot_msgs.msg import RobotState as RobotStateMsg
from robot_msgs.msg import MotorCommand as MotorCommandMsg
from robot_msgs.msg import MotorState as MotorStateMsg
from gazebo_msgs.srv import SetModelState
from std_srvs.srv import Empty
path = os.path.abspath(".")
sys.path.insert(0, path + "/src/rl_sar/scripts")
from rcl_interfaces.srv import GetParameters
from ament_index_python.packages import get_package_share_directory
from rl_sdk import *
from observation_buffer import *
CSV_LOGGER = False
CSV_LOGGER = True
class RL_Sim(RL):
class RL_Sim(RL, Node):
def __init__(self):
super().__init__()
Node.__init__(self, "rl_sim_node")
RL.__init__(self)
# member variables for RL_Sim
self.vel = Twist()
self.pose = Pose()
self.cmd_vel = Twist()
self.gazebo_imu = Imu()
self.robot_state_subscriber_msg = RobotStateMsg()
self.robot_command_publisher_msg = RobotCommandMsg()
# start ros node
rospy.init_node("rl_sim")
self.ros_namespace = self.get_namespace()
# get params from param_node
self.param_client = self.create_client(GetParameters, '/param_node/get_parameters')
while not self.param_client.wait_for_service(timeout_sec=1.0):
self.get_logger().warn("Waiting for param_node service to be available...")
request = GetParameters.Request()
request.names = ['robot_name', 'gazebo_model_name']
future = self.param_client.call_async(request)
rclpy.spin_until_future_complete(self, future)
if len(future.result().values) < 2:
self.get_logger().warn("Failed to get all parameters from param_node")
else:
self.robot_name = future.result().values[0].string_value
self.gazebo_model_name = future.result().values[1].string_value
self.get_logger().info(f"Get param robot_name: {self.robot_name}")
self.get_logger().info(f"Get param gazebo_model_name: {self.gazebo_model_name}")
# read params from yaml
self.robot_name = rospy.get_param("robot_name", "")
self.ReadYaml(self.robot_name)
for i in range(len(self.params.observations)):
if self.params.observations[i] == "ang_vel":
self.params.observations[i] = "ang_vel_world"
# history
# init rl
torch.set_grad_enabled(False)
if len(self.params.observations_history) != 0:
self.history_obs_buf = ObservationBuffer(1, self.params.num_observations, len(self.params.observations_history))
# Due to the fact that the robot_state_publisher sorts the joint names alphabetically,
# the mapping table is established according to the order defined in the YAML file
sorted_joint_controller_names = sorted(self.params.joint_controller_names)
self.sorted_to_original_index = {}
for i in range(len(self.params.joint_controller_names)):
self.sorted_to_original_index[sorted_joint_controller_names[i]] = i
self.mapped_joint_positions = [0.0] * self.params.num_of_dofs
self.mapped_joint_velocities = [0.0] * self.params.num_of_dofs
self.mapped_joint_efforts = [0.0] * self.params.num_of_dofs
# init
torch.set_grad_enabled(False)
self.joint_publishers_commands = [MotorCommand() for _ in range(self.params.num_of_dofs)]
self.robot_command_publisher_msg.motor_command = [MotorCommandMsg() for _ in range(self.params.num_of_dofs)]
self.robot_state_subscriber_msg.motor_state = [MotorStateMsg() for _ in range(self.params.num_of_dofs)]
self.InitObservations()
self.InitOutputs()
self.InitControl()
self.running_state = STATE.STATE_RL_RUNNING
# model
model_path = os.path.join(os.path.dirname(__file__), f"../models/{self.robot_name}/{self.params.model_name}")
model_path = os.path.join(get_package_share_directory('rl_sar'), 'models', self.robot_name, self.params.model_name)
self.model = torch.jit.load(model_path)
# publisher
self.ros_namespace = rospy.get_param("ros_namespace", "")
self.joint_publishers = {}
for i in range(self.params.num_of_dofs):
topic_name = f"{self.ros_namespace}{self.params.joint_controller_names[i]}/command"
self.joint_publishers[self.params.joint_controller_names[i]] = rospy.Publisher(topic_name, MotorCommand, queue_size=10)
self.robot_command_publisher = self.create_publisher(RobotCommandMsg, self.ros_namespace + "robot_joint_controller/command", qos_profile_system_default)
# subscriber
self.cmd_vel_subscriber = rospy.Subscriber("/cmd_vel", Twist, self.CmdvelCallback, queue_size=10)
self.model_state_subscriber = rospy.Subscriber("/gazebo/model_states", ModelStates, self.ModelStatesCallback, queue_size=10)
joint_states_topic = f"{self.ros_namespace}joint_states"
self.joint_state_subscriber = rospy.Subscriber(joint_states_topic, JointState, self.JointStatesCallback, queue_size=10)
self.cmd_vel_subscriber = self.create_subscription(Twist, "/cmd_vel", self.CmdvelCallback, qos_profile_system_default)
self.gazebo_imu_subscriber = self.create_subscription(Imu, "/imu", self.GazeboImuCallback, qos_profile_system_default)
self.robot_state_subscriber = self.create_subscription(RobotStateMsg, self.ros_namespace + "robot_joint_controller/state", self.RobotStateCallback, qos_profile_system_default)
# service
self.gazebo_model_name = rospy.get_param("gazebo_model_name", "")
self.gazebo_set_model_state_client = rospy.ServiceProxy("/gazebo/set_model_state", SetModelState)
self.gazebo_pause_physics_client = rospy.ServiceProxy("/gazebo/pause_physics", Empty)
self.gazebo_unpause_physics_client = rospy.ServiceProxy("/gazebo/unpause_physics", Empty)
self.gazebo_set_model_state_client = self.create_client(SetModelState, "/gazebo/set_model_state")
self.gazebo_pause_physics_client = self.create_client(Empty, "/gazebo/pause_physics")
self.gazebo_unpause_physics_client = self.create_client(Empty, "/gazebo/unpause_physics")
# loops
self.thread_control = threading.Thread(target=self.ThreadControl)
self.thread_rl = threading.Thread(target=self.ThreadRL)
self.thread_control.daemon = True
self.thread_rl.daemon = True
self.thread_control.start()
self.thread_rl.start()
@ -96,87 +100,82 @@ class RL_Sim(RL):
if CSV_LOGGER:
self.CSVInit(self.robot_name)
print(LOGGER.INFO + "RL_Sim start")
self.get_logger().info("RL_Sim start")
def __del__(self):
print(LOGGER.INFO + "RL_Sim exit")
self.get_logger().info("RL_Sim exit")
def GetState(self, state):
if self.params.framework == "isaacgym":
state.imu.quaternion[3] = self.pose.orientation.w
state.imu.quaternion[0] = self.pose.orientation.x
state.imu.quaternion[1] = self.pose.orientation.y
state.imu.quaternion[2] = self.pose.orientation.z
state.imu.quaternion[3] = self.gazebo_imu.orientation.w
state.imu.quaternion[0] = self.gazebo_imu.orientation.x
state.imu.quaternion[1] = self.gazebo_imu.orientation.y
state.imu.quaternion[2] = self.gazebo_imu.orientation.z
elif self.params.framework == "isaacsim":
state.imu.quaternion[0] = self.pose.orientation.w
state.imu.quaternion[1] = self.pose.orientation.x
state.imu.quaternion[2] = self.pose.orientation.y
state.imu.quaternion[3] = self.pose.orientation.z
state.imu.quaternion[0] = self.gazebo_imu.orientation.w
state.imu.quaternion[1] = self.gazebo_imu.orientation.x
state.imu.quaternion[2] = self.gazebo_imu.orientation.y
state.imu.quaternion[3] = self.gazebo_imu.orientation.z
state.imu.gyroscope[0] = self.vel.angular.x
state.imu.gyroscope[1] = self.vel.angular.y
state.imu.gyroscope[2] = self.vel.angular.z
state.imu.gyroscope[0] = self.gazebo_imu.angular_velocity.x
state.imu.gyroscope[1] = self.gazebo_imu.angular_velocity.y
state.imu.gyroscope[2] = self.gazebo_imu.angular_velocity.z
# state.imu.accelerometer
state.imu.accelerometer[0] = self.gazebo_imu.linear_acceleration.x
state.imu.accelerometer[1] = self.gazebo_imu.linear_acceleration.y
state.imu.accelerometer[2] = self.gazebo_imu.linear_acceleration.z
for i in range(self.params.num_of_dofs):
state.motor_state.q[i] = self.mapped_joint_positions[i]
state.motor_state.dq[i] = self.mapped_joint_velocities[i]
state.motor_state.tauEst[i] = self.mapped_joint_efforts[i]
state.motor_state.q[i] = self.robot_state_subscriber_msg.motor_state[i].q
state.motor_state.dq[i] = self.robot_state_subscriber_msg.motor_state[i].dq
state.motor_state.tau_est[i] = self.robot_state_subscriber_msg.motor_state[i].tau_est
def SetCommand(self, command):
for i in range(self.params.num_of_dofs):
self.joint_publishers_commands[i].q = command.motor_command.q[i]
self.joint_publishers_commands[i].dq = command.motor_command.dq[i]
self.joint_publishers_commands[i].kp = command.motor_command.kp[i]
self.joint_publishers_commands[i].kd = command.motor_command.kd[i]
self.joint_publishers_commands[i].tau = command.motor_command.tau[i]
self.robot_command_publisher_msg.motor_command[i].q = float(command.motor_command.q[i])
self.robot_command_publisher_msg.motor_command[i].dq = float(command.motor_command.dq[i])
self.robot_command_publisher_msg.motor_command[i].kp = float(command.motor_command.kp[i])
self.robot_command_publisher_msg.motor_command[i].kd = float(command.motor_command.kd[i])
self.robot_command_publisher_msg.motor_command[i].tau = float(command.motor_command.tau[i])
for i in range(self.params.num_of_dofs):
self.joint_publishers[self.params.joint_controller_names[i]].publish(self.joint_publishers_commands[i])
self.robot_command_publisher.publish(self.robot_command_publisher_msg)
def RobotControl(self):
if self.control.control_state == STATE.STATE_RESET_SIMULATION:
set_model_state = SetModelStateRequest().model_state
set_model_state.model_name = self.gazebo_model_name
set_model_state.pose.position.z = 1.0
set_model_state.reference_frame = "world"
self.gazebo_set_model_state_client(set_model_state)
self.control.control_state = STATE.STATE_WAITING
if self.control.control_state == STATE.STATE_TOGGLE_SIMULATION:
if self.simulation_running:
self.gazebo_pause_physics_client()
print("\r\n" + LOGGER.INFO + "Simulation Stop")
else:
self.gazebo_unpause_physics_client()
print("\r\n" + LOGGER.INFO + "Simulation Start")
self.simulation_running = not self.simulation_running
self.control.control_state = STATE.STATE_WAITING
# NOT AVAILABLE NOW
# if self.control.control_state == STATE.STATE_RESET_SIMULATION:
# set_model_state = SetModelState.Request()
# set_model_state.model_state.model_name = self.gazebo_model_name
# set_model_state.model_state.pose.position.z = 1.0
# set_model_state.model_state.reference_frame = "world"
# self.gazebo_set_model_state_client.call_async(set_model_state)
# self.control.control_state = STATE.STATE_WAITING
# if self.control.control_state == STATE.STATE_TOGGLE_SIMULATION:
# if self.simulation_running:
# self.gazebo_pause_physics_client.call_async(Empty.Request())
# self.get_logger().info("Simulation Stop")
# else:
# self.gazebo_unpause_physics_client.call_async(Empty.Request())
# self.get_logger().info("Simulation Start")
# self.simulation_running = not self.simulation_running
# self.control.control_state = STATE.STATE_WAITING
if self.simulation_running:
self.GetState(self.robot_state)
self.StateController(self.robot_state, self.robot_command)
self.SetCommand(self.robot_command)
def ModelStatesCallback(self, msg):
self.vel = msg.twist[2]
self.pose = msg.pose[2]
def GazeboImuCallback(self, msg):
self.gazebo_imu = msg
def CmdvelCallback(self, msg):
self.cmd_vel = msg
def MapData(self, source_data, target_data):
for i in range(len(source_data)):
target_data[i] = source_data[self.sorted_to_original_index[self.params.joint_controller_names[i]]]
def JointStatesCallback(self, msg):
self.MapData(msg.position, self.mapped_joint_positions)
self.MapData(msg.velocity, self.mapped_joint_velocities)
self.MapData(msg.effort, self.mapped_joint_efforts)
def RobotStateCallback(self, msg):
self.robot_state_subscriber_msg = msg
def RunModel(self):
if self.running_state == STATE.STATE_RL_RUNNING and self.simulation_running:
self.obs.lin_vel = torch.tensor([[self.vel.linear.x, self.vel.linear.y, self.vel.linear.z]])
# self.obs.lin_vel NOT USE
self.obs.ang_vel = torch.tensor(self.robot_state.imu.gyroscope).unsqueeze(0)
# self.obs.commands = torch.tensor([[self.cmd_vel.linear.x, self.cmd_vel.linear.y, self.cmd_vel.angular.z]])
self.obs.commands = torch.tensor([[self.control.x, self.control.y, self.control.yaw]])
@ -199,7 +198,9 @@ class RL_Sim(RL):
self.output_dof_pos = self.ComputePosition(self.obs.actions)
if CSV_LOGGER:
tau_est = torch.tensor(self.mapped_joint_efforts).unsqueeze(0)
tau_est = torch.empty(1, self.params.num_of_dofs, dtype=torch.float32)
for i in range(self.params.num_of_dofs):
tau_est[0, i] = self.robot_state_subscriber_msg.motor_state[i].tau_est
self.CSVLogger(self.output_torques, tau_est, self.obs.dof_pos, self.output_dof_pos, self.obs.dof_vel)
def Forward(self):
@ -219,21 +220,27 @@ class RL_Sim(RL):
def ThreadControl(self):
thread_period = self.params.dt
thread_name = "thread_control"
print(f"[Thread Start] named: {thread_name}, period: {thread_period * 1000:.0f}(ms), cpu unspecified")
while not rospy.is_shutdown():
self.get_logger().info(f"[Thread Start] named: {thread_name}, period: {thread_period * 1000:.0f}(ms), cpu unspecified")
while rclpy.ok():
self.RobotControl()
time.sleep(thread_period)
print("[Thread End] named: " + thread_name)
self.get_logger().info("[Thread End] named: " + thread_name)
def ThreadRL(self):
thread_period = self.params.dt * self.params.decimation
thread_name = "thread_rl"
print(f"[Thread Start] named: {thread_name}, period: {thread_period * 1000:.0f}(ms), cpu unspecified")
while not rospy.is_shutdown():
self.get_logger().info(f"[Thread Start] named: {thread_name}, period: {thread_period * 1000:.0f}(ms), cpu unspecified")
while rclpy.ok():
self.RunModel()
time.sleep(thread_period)
print("[Thread End] named: " + thread_name)
self.get_logger().info("[Thread End] named: " + thread_name)
if __name__ == "__main__":
rclpy.init()
rl_sim = RL_Sim()
rospy.spin()
try:
rclpy.spin(rl_sim)
except KeyboardInterrupt:
rl_sim.get_logger().info("Shutdown signal received, shutting down...")
rclpy.shutdown()

View File

@ -116,7 +116,7 @@ void RL_Real::GetState(RobotState<double> *state)
{
state->motor_state.q[i] = this->unitree_low_state.motorState[state_mapping[i]].q;
state->motor_state.dq[i] = this->unitree_low_state.motorState[state_mapping[i]].dq;
state->motor_state.tauEst[i] = this->unitree_low_state.motorState[state_mapping[i]].tauEst;
state->motor_state.tau_est[i] = this->unitree_low_state.motorState[state_mapping[i]].tauEst;
}
}
@ -178,7 +178,7 @@ void RL_Real::RunModel()
this->output_dof_pos = this->ComputePosition(this->obs.actions);
#ifdef CSV_LOGGER
torch::Tensor tau_est = torch::tensor(this->robot_state.motor_state.tauEst).unsqueeze(0);
torch::Tensor tau_est = torch::tensor(this->robot_state.motor_state.tau_est).unsqueeze(0);
this->CSVLogger(this->output_torques, tau_est, this->obs.dof_pos, this->output_dof_pos, this->obs.dof_vel);
#endif
}

View File

@ -122,7 +122,7 @@ void RL_Real::GetState(RobotState<double> *state)
{
state->motor_state.q[i] = this->unitree_low_state.motor_state()[state_mapping[i]].q();
state->motor_state.dq[i] = this->unitree_low_state.motor_state()[state_mapping[i]].dq();
state->motor_state.tauEst[i] = this->unitree_low_state.motor_state()[state_mapping[i]].tau_est();
state->motor_state.tau_est[i] = this->unitree_low_state.motor_state()[state_mapping[i]].tau_est();
}
}
@ -183,7 +183,7 @@ void RL_Real::RunModel()
this->output_dof_pos = this->ComputePosition(this->obs.actions);
#ifdef CSV_LOGGER
torch::Tensor tau_est = torch::tensor(this->robot_state.motor_state.tauEst).unsqueeze(0);
torch::Tensor tau_est = torch::tensor(this->robot_state.motor_state.tau_est).unsqueeze(0);
this->CSVLogger(this->output_torques, tau_est, this->obs.dof_pos, this->output_dof_pos, this->obs.dof_vel);
#endif
}

View File

@ -1,14 +1,43 @@
#include "rl_sim.hpp"
// #define PLOT
// #define CSV_LOGGER
#define CSV_LOGGER
RL_Sim::RL_Sim()
: rclcpp::Node("rl_sim_node")
{
ros::NodeHandle nh;
this->ros_namespace = this->get_namespace();
// get params from param_node
param_client = this->create_client<rcl_interfaces::srv::GetParameters>("/param_node/get_parameters");
while (!param_client->wait_for_service(std::chrono::seconds(1)))
{
std::cout << LOGGER::WARNING << "Waiting for param_node service to be available..." << std::endl;
}
auto request = std::make_shared<rcl_interfaces::srv::GetParameters::Request>();
request->names.push_back("robot_name");
request->names.push_back("gazebo_model_name");
auto future = param_client->async_send_request(request);
rclcpp::spin_until_future_complete(this->get_node_base_interface(), future);
if (future.get()->values.size() < 2)
{
std::cout << LOGGER::WARNING << "Failed to get all parameters from param_node" << std::endl;
}
else
{
this->robot_name = future.get()->values[0].string_value;
this->gazebo_model_name = future.get()->values[1].string_value;
std::cout << LOGGER::INFO << "Get param robot_name: " << this->robot_name << std::endl;
std::cout << LOGGER::INFO << "Get param gazebo_model_name: " << this->gazebo_model_name << std::endl;
}
// // get params from this node
// this->declare_parameter<std::string>("robot_name", "");
// this->get_parameter("robot_name", this->robot_name);
// this->declare_parameter<std::string>("gazebo_model_name", "");
// this->get_parameter("gazebo_model_name", this->gazebo_model_name);
// read params from yaml
nh.param<std::string>("robot_name", this->robot_name, "");
this->ReadYaml(this->robot_name);
for (std::string &observation : this->params.observations)
{
@ -18,17 +47,6 @@ RL_Sim::RL_Sim()
observation = "ang_vel_world";
}
}
// Due to the fact that the robot_state_publisher sorts the joint names alphabetically,
// the mapping table is established according to the order defined in the YAML file
std::vector<std::string> sorted_joint_controller_names = this->params.joint_controller_names;
std::sort(sorted_joint_controller_names.begin(), sorted_joint_controller_names.end());
for (size_t i = 0; i < this->params.joint_controller_names.size(); ++i)
{
this->sorted_to_original_index[sorted_joint_controller_names[i]] = i;
}
this->mapped_joint_positions = std::vector<double>(this->params.num_of_dofs, 0.0);
this->mapped_joint_velocities = std::vector<double>(this->params.num_of_dofs, 0.0);
this->mapped_joint_efforts = std::vector<double>(this->params.num_of_dofs, 0.0);
// init rl
torch::autograd::GradMode::set_enabled(false);
@ -36,7 +54,8 @@ RL_Sim::RL_Sim()
{
this->history_obs_buf = ObservationBuffer(1, this->params.num_observations, this->params.observations_history.size());
}
this->joint_publishers_commands.resize(this->params.num_of_dofs);
this->robot_command_publisher_msg.motor_command.resize(this->params.num_of_dofs);
this->robot_state_subscriber_msg.motor_state.resize(this->params.num_of_dofs);
this->InitObservations();
this->InitOutputs();
this->InitControl();
@ -47,24 +66,26 @@ RL_Sim::RL_Sim()
this->model = torch::jit::load(model_path);
// publisher
nh.param<std::string>("ros_namespace", this->ros_namespace, "");
for (int i = 0; i < this->params.num_of_dofs; ++i)
{
// joint need to rename as xxx_joint
this->joint_publishers[this->params.joint_controller_names[i]] =
nh.advertise<robot_msgs::MotorCommand>(this->ros_namespace + this->params.joint_controller_names[i] + "/command", 10);
}
this->robot_command_publisher = this->create_publisher<robot_msgs::msg::RobotCommand>(
this->ros_namespace + "robot_joint_controller/command", rclcpp::SystemDefaultsQoS());
// subscriber
this->cmd_vel_subscriber = nh.subscribe<geometry_msgs::Twist>("/cmd_vel", 10, &RL_Sim::CmdvelCallback, this);
this->model_state_subscriber = nh.subscribe<gazebo_msgs::ModelStates>("/gazebo/model_states", 10, &RL_Sim::ModelStatesCallback, this);
this->joint_state_subscriber = nh.subscribe<sensor_msgs::JointState>(this->ros_namespace + "joint_states", 10, &RL_Sim::JointStatesCallback, this);
this->cmd_vel_subscriber = this->create_subscription<geometry_msgs::msg::Twist>(
"/cmd_vel", rclcpp::SystemDefaultsQoS(),
[this] (const geometry_msgs::msg::Twist::SharedPtr msg) {this->CmdvelCallback(msg);}
);
this->gazebo_imu_subscriber = this->create_subscription<sensor_msgs::msg::Imu>(
"/imu", rclcpp::SystemDefaultsQoS(), [this] (const sensor_msgs::msg::Imu::SharedPtr msg) {this->GazeboImuCallback(msg);}
);
this->robot_state_subscriber = this->create_subscription<robot_msgs::msg::RobotState>(
this->ros_namespace + "robot_joint_controller/state", rclcpp::SystemDefaultsQoS(),
[this] (const robot_msgs::msg::RobotState::SharedPtr msg) {this->RobotStateCallback(msg);}
);
// service
nh.param<std::string>("gazebo_model_name", this->gazebo_model_name, "");
this->gazebo_set_model_state_client = nh.serviceClient<gazebo_msgs::SetModelState>("/gazebo/set_model_state");
this->gazebo_pause_physics_client = nh.serviceClient<std_srvs::Empty>("/gazebo/pause_physics");
this->gazebo_unpause_physics_client = nh.serviceClient<std_srvs::Empty>("/gazebo/unpause_physics");
this->gazebo_set_model_state_client = this->create_client<gazebo_msgs::srv::SetModelState>("/gazebo/set_model_state");
this->gazebo_pause_physics_client = this->create_client<std_srvs::srv::Empty>("/gazebo/pause_physics");
this->gazebo_unpause_physics_client = this->create_client<std_srvs::srv::Empty>("/gazebo/unpause_physics");
// loop
this->loop_control = std::make_shared<LoopFunc>("loop_control", this->params.dt, std::bind(&RL_Sim::RobotControl, this));
@ -107,30 +128,32 @@ void RL_Sim::GetState(RobotState<double> *state)
{
if (this->params.framework == "isaacgym")
{
state->imu.quaternion[3] = this->pose.orientation.w;
state->imu.quaternion[0] = this->pose.orientation.x;
state->imu.quaternion[1] = this->pose.orientation.y;
state->imu.quaternion[2] = this->pose.orientation.z;
state->imu.quaternion[3] = this->gazebo_imu.orientation.w;
state->imu.quaternion[0] = this->gazebo_imu.orientation.x;
state->imu.quaternion[1] = this->gazebo_imu.orientation.y;
state->imu.quaternion[2] = this->gazebo_imu.orientation.z;
}
else if (this->params.framework == "isaacsim")
{
state->imu.quaternion[0] = this->pose.orientation.w;
state->imu.quaternion[1] = this->pose.orientation.x;
state->imu.quaternion[2] = this->pose.orientation.y;
state->imu.quaternion[3] = this->pose.orientation.z;
state->imu.quaternion[0] = this->gazebo_imu.orientation.w;
state->imu.quaternion[1] = this->gazebo_imu.orientation.x;
state->imu.quaternion[2] = this->gazebo_imu.orientation.y;
state->imu.quaternion[3] = this->gazebo_imu.orientation.z;
}
state->imu.gyroscope[0] = this->vel.angular.x;
state->imu.gyroscope[1] = this->vel.angular.y;
state->imu.gyroscope[2] = this->vel.angular.z;
state->imu.gyroscope[0] = this->gazebo_imu.angular_velocity.x;
state->imu.gyroscope[1] = this->gazebo_imu.angular_velocity.y;
state->imu.gyroscope[2] = this->gazebo_imu.angular_velocity.z;
// state->imu.accelerometer
state->imu.accelerometer[0] = this->gazebo_imu.linear_acceleration.x;
state->imu.accelerometer[1] = this->gazebo_imu.linear_acceleration.y;
state->imu.accelerometer[2] = this->gazebo_imu.linear_acceleration.z;
for (int i = 0; i < this->params.num_of_dofs; ++i)
{
state->motor_state.q[i] = this->mapped_joint_positions[i];
state->motor_state.dq[i] = this->mapped_joint_velocities[i];
state->motor_state.tauEst[i] = this->mapped_joint_efforts[i];
state->motor_state.q[i] = this->robot_state_subscriber_msg.motor_state[i].q;
state->motor_state.dq[i] = this->robot_state_subscriber_msg.motor_state[i].dq;
state->motor_state.tau_est[i] = this->robot_state_subscriber_msg.motor_state[i].tau_est;
}
}
@ -138,49 +161,79 @@ void RL_Sim::SetCommand(const RobotCommand<double> *command)
{
for (int i = 0; i < this->params.num_of_dofs; ++i)
{
this->joint_publishers_commands[i].q = command->motor_command.q[i];
this->joint_publishers_commands[i].dq = command->motor_command.dq[i];
this->joint_publishers_commands[i].kp = command->motor_command.kp[i];
this->joint_publishers_commands[i].kd = command->motor_command.kd[i];
this->joint_publishers_commands[i].tau = command->motor_command.tau[i];
this->robot_command_publisher_msg.motor_command[i].q = command->motor_command.q[i];
this->robot_command_publisher_msg.motor_command[i].dq = command->motor_command.dq[i];
this->robot_command_publisher_msg.motor_command[i].kp = command->motor_command.kp[i];
this->robot_command_publisher_msg.motor_command[i].kd = command->motor_command.kd[i];
this->robot_command_publisher_msg.motor_command[i].tau = command->motor_command.tau[i];
}
for (int i = 0; i < this->params.num_of_dofs; ++i)
{
this->joint_publishers[this->params.joint_controller_names[i]].publish(this->joint_publishers_commands[i]);
}
this->robot_command_publisher->publish(this->robot_command_publisher_msg);
}
void RL_Sim::RobotControl()
{
std::lock_guard<std::mutex> lock(robot_state_mutex);
if (this->control.control_state == STATE_RESET_SIMULATION)
{
gazebo_msgs::SetModelState set_model_state;
set_model_state.request.model_state.model_name = this->gazebo_model_name;
set_model_state.request.model_state.pose.position.z = 1.0;
set_model_state.request.model_state.reference_frame = "world";
this->gazebo_set_model_state_client.call(set_model_state);
this->control.control_state = STATE_WAITING;
}
if (this->control.control_state == STATE_TOGGLE_SIMULATION)
{
std_srvs::Empty empty;
if (simulation_running)
{
this->gazebo_pause_physics_client.call(empty);
std::cout << std::endl << LOGGER::INFO << "Simulation Stop" << std::endl;
}
else
{
this->gazebo_unpause_physics_client.call(empty);
std::cout << std::endl << LOGGER::INFO << "Simulation Start" << std::endl;
}
simulation_running = !simulation_running;
this->control.control_state = STATE_WAITING;
}
// if (this->control.control_state == STATE_RESET_SIMULATION)
// {
// auto set_model_state_request = std::make_shared<gazebo_msgs::srv::SetModelState::Request>();
// set_model_state_request->model_state.model_name = this->gazebo_model_name;
// set_model_state_request->model_state.pose.position.z = 1.0;
// set_model_state_request->model_state.reference_frame = "world";
// this->gazebo_set_model_state_client->async_send_request(set_model_state_request,
// [this](rclcpp::Client<gazebo_msgs::srv::SetModelState>::SharedFuture future)
// {
// if (future.get())
// {
// std::cout << LOGGER::INFO << "Reset Simulation" << std::endl;
// this->control.control_state = STATE_WAITING;
// }
// else
// {
// std::cout << LOGGER::WARNING << "Failed to reset simulation" << std::endl;
// }
// }
// );
// }
// if (this->control.control_state == STATE_TOGGLE_SIMULATION)
// {
// auto empty_request = std::make_shared<std_srvs::srv::Empty::Request>();
// if (simulation_running)
// {
// this->gazebo_pause_physics_client->async_send_request(empty_request,
// [this](rclcpp::Client<std_srvs::srv::Empty>::SharedFuture future)
// {
// if (future.get())
// {
// std::cout << LOGGER::INFO << "Simulation Stop" << std::endl;
// }
// else
// {
// std::cout << LOGGER::WARNING << "Failed to toggle simulation" << std::endl;
// }
// }
// );
// }
// else
// {
// this->gazebo_unpause_physics_client->async_send_request(empty_request,
// [this](rclcpp::Client<std_srvs::srv::Empty>::SharedFuture future)
// {
// if (future.get())
// {
// std::cout << LOGGER::INFO << "Simulation Start" << std::endl;
// }
// else
// {
// std::cout << LOGGER::WARNING << "Failed to toggle simulation" << std::endl;
// }
// }
// );
// }
// simulation_running = !simulation_running;
// this->control.control_state = STATE_WAITING;
// }
if (simulation_running)
{
this->motiontime++;
@ -190,30 +243,19 @@ void RL_Sim::RobotControl()
}
}
void RL_Sim::ModelStatesCallback(const gazebo_msgs::ModelStates::ConstPtr &msg)
void RL_Sim::GazeboImuCallback(const sensor_msgs::msg::Imu::SharedPtr msg)
{
this->vel = msg->twist[2];
this->pose = msg->pose[2];
this->gazebo_imu = *msg;
}
void RL_Sim::CmdvelCallback(const geometry_msgs::Twist::ConstPtr &msg)
void RL_Sim::CmdvelCallback(const geometry_msgs::msg::Twist::SharedPtr msg)
{
this->cmd_vel = *msg;
}
void RL_Sim::MapData(const std::vector<double> &source_data, std::vector<double> &target_data)
void RL_Sim::RobotStateCallback(const robot_msgs::msg::RobotState::SharedPtr msg)
{
for (size_t i = 0; i < source_data.size(); ++i)
{
target_data[i] = source_data[this->sorted_to_original_index[this->params.joint_controller_names[i]]];
}
}
void RL_Sim::JointStatesCallback(const sensor_msgs::JointState::ConstPtr &msg)
{
MapData(msg->position, this->mapped_joint_positions);
MapData(msg->velocity, this->mapped_joint_velocities);
MapData(msg->effort, this->mapped_joint_efforts);
this->robot_state_subscriber_msg = *msg;
}
void RL_Sim::RunModel()
@ -222,7 +264,7 @@ void RL_Sim::RunModel()
if (this->running_state == STATE_RL_RUNNING && simulation_running)
{
this->obs.lin_vel = torch::tensor({{this->vel.linear.x, this->vel.linear.y, this->vel.linear.z}});
// this->obs.lin_vel NOT USE
this->obs.ang_vel = torch::tensor(this->robot_state.imu.gyroscope).unsqueeze(0);
// this->obs.commands = torch::tensor({{this->cmd_vel.linear.x, this->cmd_vel.linear.y, this->cmd_vel.angular.z}});
this->obs.commands = torch::tensor({{this->control.x, this->control.y, this->control.yaw}});
@ -247,7 +289,11 @@ void RL_Sim::RunModel()
this->output_dof_pos = this->ComputePosition(this->obs.actions);
#ifdef CSV_LOGGER
torch::Tensor tau_est = torch::tensor(this->mapped_joint_efforts).unsqueeze(0);
torch::Tensor tau_est = torch::empty({1, this->params.num_of_dofs}, torch::kFloat);
for (int i = 0; i < this->params.num_of_dofs; ++i)
{
tau_est[0][i] = this->robot_state_subscriber_msg.motor_state[i].tau_est;
}
this->CSVLogger(this->output_torques, tau_est, this->obs.dof_pos, this->output_dof_pos, this->obs.dof_vel);
#endif
}
@ -291,8 +337,8 @@ void RL_Sim::Plot()
{
this->plot_real_joint_pos[i].erase(this->plot_real_joint_pos[i].begin());
this->plot_target_joint_pos[i].erase(this->plot_target_joint_pos[i].begin());
this->plot_real_joint_pos[i].push_back(this->mapped_joint_positions[i]);
this->plot_target_joint_pos[i].push_back(this->joint_publishers_commands[i].q);
this->plot_real_joint_pos[i].push_back(this->robot_state_subscriber_msg.motor_state[i].q);
this->plot_target_joint_pos[i].push_back(this->robot_command_publisher_msg.motor_command[i].q);
plt::subplot(4, 3, i + 1);
plt::named_plot("_real_joint_pos", this->plot_t, this->plot_real_joint_pos[i], "r");
plt::named_plot("_target_joint_pos", this->plot_t, this->plot_target_joint_pos[i], "b");
@ -302,17 +348,10 @@ void RL_Sim::Plot()
plt::pause(0.01);
}
void signalHandler(int signum)
{
ros::shutdown();
exit(0);
}
int main(int argc, char **argv)
{
signal(SIGINT, signalHandler);
ros::init(argc, argv, "rl_sar");
RL_Sim rl_sar;
ros::spin();
rclcpp::init(argc, argv);
rclcpp::spin(std::make_shared<RL_Sim>());
rclcpp::shutdown();
return 0;
}

View File

@ -1,31 +1,66 @@
cmake_minimum_required(VERSION 2.8.3)
cmake_minimum_required(VERSION 3.5)
project(robot_joint_controller)
find_package(catkin REQUIRED COMPONENTS
controller_interface
hardware_interface
pluginlib
roscpp
realtime_tools
robot_msgs
if(DEFINED ENV{ROS_DISTRO})
set(ROS_DISTRO_ENV $ENV{ROS_DISTRO})
if(ROS_DISTRO_ENV STREQUAL "foxy")
add_definitions(-DROS_DISTRO_FOXY)
elseif(ROS_DISTRO_ENV STREQUAL "humble")
add_definitions(-DROS_DISTRO_HUMBLE)
else()
add_definitions(-DROS_DISTRO_UNKNOWN)
endif()
endif()
find_package(ament_cmake REQUIRED)
find_package(rclcpp REQUIRED)
find_package(urdf REQUIRED)
find_package(control_toolbox REQUIRED)
find_package(realtime_tools REQUIRED)
find_package(hardware_interface REQUIRED)
find_package(controller_interface REQUIRED)
find_package(pluginlib REQUIRED)
find_package(robot_msgs REQUIRED)
find_package(geometry_msgs REQUIRED)
find_package(rcl_interfaces REQUIRED)
include_directories(include)
add_library(${PROJECT_NAME} SHARED
src/robot_joint_controller.cpp
src/robot_joint_controller_group.cpp
)
catkin_package(
CATKIN_DEPENDS
robot_msgs
controller_interface
hardware_interface
pluginlib
roscpp
INCLUDE_DIRS include
LIBRARIES ${PROJECT_NAME}
target_include_directories(${PROJECT_NAME} PRIVATE include)
ament_target_dependencies(${PROJECT_NAME}
rclcpp
urdf
control_toolbox
realtime_tools
hardware_interface
controller_interface
pluginlib
robot_msgs
geometry_msgs
rcl_interfaces
)
include_directories(include ${catkin_INCLUDE_DIRS})
pluginlib_export_plugin_description_file(controller_interface robot_joint_controller_plugins.xml)
link_directories(${catkin_LIB_DIRS} lib)
add_library(robot_joint_controller
src/robot_joint_controller.cpp
install(DIRECTORY include/
DESTINATION include/${PROJECT_NAME}
)
target_link_libraries(robot_joint_controller ${catkin_LIBRARIES})
ament_export_libraries(${PROJECT_NAME})
ament_export_dependencies(rclcpp urdf control_toolbox realtime_tools hardware_interface controller_interface pluginlib robot_msgs geometry_msgs rcl_interfaces)
install(
TARGETS ${PROJECT_NAME}
EXPORT ${PROJECT_NAME}
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)
ament_package()

View File

@ -1,72 +0,0 @@
#ifndef ROBOT_JOINT_CONTROLLER_H
#define ROBOT_JOINT_CONTROLLER_H
#include <ros/node_handle.h>
#include <urdf/model.h>
#include <control_toolbox/pid.h>
#include <realtime_tools/realtime_publisher.h>
#include <hardware_interface/joint_command_interface.h>
#include <controller_interface/controller.h>
#include <std_msgs/Float64.h>
#include <realtime_tools/realtime_buffer.h>
#include <controller_interface/controller.h>
#include <hardware_interface/joint_command_interface.h>
#include "robot_msgs/MotorCommand.h"
#include "robot_msgs/MotorState.h"
#include <geometry_msgs/WrenchStamped.h>
#include <stdio.h>
#include <stdint.h>
#include <algorithm>
#include <math.h>
#define PosStopF (2.146E+9f)
#define VelStopF (16000.0f)
typedef struct
{
uint8_t mode;
double pos;
double posStiffness;
double vel;
double velStiffness;
double torque;
} ServoCommand;
namespace robot_joint_controller
{
class RobotJointController : public controller_interface::Controller<hardware_interface::EffortJointInterface>
{
private:
hardware_interface::JointHandle joint;
ros::Subscriber sub_command, sub_ft;
control_toolbox::Pid pid_controller_;
std::unique_ptr<realtime_tools::RealtimePublisher<robot_msgs::MotorState>> controller_state_publisher_;
public:
std::string name_space;
std::string joint_name;
urdf::JointConstSharedPtr joint_urdf;
realtime_tools::RealtimeBuffer<robot_msgs::MotorCommand> command;
robot_msgs::MotorCommand lastCommand;
robot_msgs::MotorState lastState;
ServoCommand servoCommand;
RobotJointController();
~RobotJointController();
virtual bool init(hardware_interface::EffortJointInterface *robot, ros::NodeHandle &n);
virtual void starting(const ros::Time &time);
virtual void update(const ros::Time &time, const ros::Duration &period);
virtual void stopping();
void setCommandCB(const robot_msgs::MotorCommandConstPtr &msg);
void positionLimits(double &position);
void velocityLimits(double &velocity);
void effortLimits(double &effort);
void setGains(const double &p, const double &i, const double &d, const double &i_max, const double &i_min, const bool &antiwindup = false);
void getGains(double &p, double &i, double &d, double &i_max, double &i_min, bool &antiwindup);
void getGains(double &p, double &i, double &d, double &i_max, double &i_min);
};
}
#endif

View File

@ -0,0 +1,92 @@
#ifndef ROBOT_JOINT_CONTROLLER_HPP
#define ROBOT_JOINT_CONTROLLER_HPP
#include "rclcpp/logging.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp"
#include "rclcpp_lifecycle/state.hpp"
#include <urdf/model.h>
#include <realtime_tools/realtime_publisher.h>
#include <realtime_tools/realtime_buffer.h>
#include "controller_interface/controller_interface.hpp"
#include <std_msgs/msg/float64.hpp>
#include <rcl_interfaces/srv/get_parameters.hpp>
#include "robot_msgs/msg/motor_command.hpp"
#include "robot_msgs/msg/motor_state.hpp"
#include "visibility_control.h"
#include <stdio.h>
#include <stdint.h>
#include <algorithm>
#include <math.h>
#include <cstdlib>
#include <memory>
#define PosStopF (2.146E+9f)
#define VelStopF (16000.0f)
typedef struct
{
uint8_t mode;
double pos;
double pos_stiffness;
double vel;
double vel_stiffness;
double torque;
} ServoCommand;
namespace robot_joint_controller
{
using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;
class RobotJointController : public controller_interface::ControllerInterface
{
public:
ROBOT_JOINT_CONTROLLER_PUBLIC
RobotJointController();
#if defined(ROS_DISTRO_FOXY)
ROBOT_JOINT_CONTROLLER_PUBLIC
controller_interface::return_type update() override;
#elif defined(ROS_DISTRO_HUMBLE)
ROBOT_JOINT_CONTROLLER_PUBLIC
controller_interface::return_type update(const rclcpp::Time &time, const rclcpp::Duration &period) override;
#endif
ROBOT_JOINT_CONTROLLER_PUBLIC
controller_interface::InterfaceConfiguration command_interface_configuration() const override;
ROBOT_JOINT_CONTROLLER_PUBLIC
controller_interface::InterfaceConfiguration state_interface_configuration() const override;
// ROBOT_JOINT_CONTROLLER_PUBLIC
// CallbackReturn on_init() override;
ROBOT_JOINT_CONTROLLER_PUBLIC
CallbackReturn on_configure(const rclcpp_lifecycle::State &previous_state) override;
ROBOT_JOINT_CONTROLLER_PUBLIC
CallbackReturn on_activate(const rclcpp_lifecycle::State &previous_state) override;
ROBOT_JOINT_CONTROLLER_PUBLIC
CallbackReturn on_deactivate(const rclcpp_lifecycle::State &previous_state) override;
void UpdateFunc(const double &period_seconds);
void SetCommandCallback(const robot_msgs::msg::MotorCommand::SharedPtr msg);
void PositionLimit(double &position);
void VelocityLimit(double &velocity);
void EffortLimit(double &effort);
protected:
std::string name_space_;
std::string joint_name_;
realtime_tools::RealtimeBuffer<robot_msgs::msg::MotorCommand> rt_command_ptr_;
robot_msgs::msg::MotorCommand last_command_;
robot_msgs::msg::MotorState last_state_;
ServoCommand servo_command_;
urdf::JointConstSharedPtr joints_urdf_;
rclcpp::Client<rcl_interfaces::srv::GetParameters>::SharedPtr robot_description_client_;
rclcpp::Subscription<robot_msgs::msg::MotorCommand>::SharedPtr joints_command_subscriber_;
std::shared_ptr<realtime_tools::RealtimePublisher<robot_msgs::msg::MotorState>> controller_state_publisher_;
#if defined(ROS_DISTRO_FOXY)
rclcpp::Time previous_update_timestamp_{0};
#endif
};
} // namespace robot_joint_controller
#endif // ROBOT_JOINT_CONTROLLER_HPP

View File

@ -0,0 +1,92 @@
#ifndef ROBOT_JOINT_CONTROLLER_GROUP_HPP
#define ROBOT_JOINT_CONTROLLER_GROUP_HPP
#include "rclcpp/logging.hpp"
#include "rclcpp/qos.hpp"
#include "rclcpp_lifecycle/node_interfaces/lifecycle_node_interface.hpp"
#include "rclcpp_lifecycle/state.hpp"
#include <urdf/model.h>
#include <realtime_tools/realtime_publisher.h>
#include <realtime_tools/realtime_buffer.h>
#include "controller_interface/controller_interface.hpp"
#include <std_msgs/msg/float64.hpp>
#include <rcl_interfaces/srv/get_parameters.hpp>
#include "robot_msgs/msg/robot_command.hpp"
#include "robot_msgs/msg/robot_state.hpp"
#include "visibility_control.h"
#include <stdio.h>
#include <stdint.h>
#include <algorithm>
#include <math.h>
#include <cstdlib>
#include <memory>
#define PosStopF (2.146E+9f)
#define VelStopF (16000.0f)
typedef struct
{
uint8_t mode;
double pos;
double pos_stiffness;
double vel;
double vel_stiffness;
double torque;
} ServoCommand;
namespace robot_joint_controller
{
using CallbackReturn = rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn;
class RobotJointControllerGroup : public controller_interface::ControllerInterface
{
public:
ROBOT_JOINT_CONTROLLER_PUBLIC
RobotJointControllerGroup();
#if defined(ROS_DISTRO_FOXY)
ROBOT_JOINT_CONTROLLER_PUBLIC
controller_interface::return_type update() override;
#elif defined(ROS_DISTRO_HUMBLE)
ROBOT_JOINT_CONTROLLER_PUBLIC
controller_interface::return_type update(const rclcpp::Time &time, const rclcpp::Duration &period) override;
#endif
ROBOT_JOINT_CONTROLLER_PUBLIC
controller_interface::InterfaceConfiguration command_interface_configuration() const override;
ROBOT_JOINT_CONTROLLER_PUBLIC
controller_interface::InterfaceConfiguration state_interface_configuration() const override;
// ROBOT_JOINT_CONTROLLER_PUBLIC
// CallbackReturn on_init() override;
ROBOT_JOINT_CONTROLLER_PUBLIC
CallbackReturn on_configure(const rclcpp_lifecycle::State &previous_state) override;
ROBOT_JOINT_CONTROLLER_PUBLIC
CallbackReturn on_activate(const rclcpp_lifecycle::State &previous_state) override;
ROBOT_JOINT_CONTROLLER_PUBLIC
CallbackReturn on_deactivate(const rclcpp_lifecycle::State &previous_state) override;
void UpdateFunc(const double &period_seconds);
void SetCommandCallback(const robot_msgs::msg::RobotCommand::SharedPtr msg);
void PositionLimit(double &position, int &index);
void VelocityLimit(double &velocity, int &index);
void EffortLimit(double &effort, int &index);
protected:
std::string name_space_;
std::vector<std::string> joint_names_;
realtime_tools::RealtimeBuffer<robot_msgs::msg::RobotCommand> rt_command_ptr_;
robot_msgs::msg::RobotCommand last_command_;
robot_msgs::msg::RobotState last_state_;
ServoCommand servo_command_;
std::vector<urdf::JointConstSharedPtr> joints_urdf_;
rclcpp::Client<rcl_interfaces::srv::GetParameters>::SharedPtr robot_description_client_;
rclcpp::Subscription<robot_msgs::msg::RobotCommand>::SharedPtr joints_command_subscriber_;
std::shared_ptr<realtime_tools::RealtimePublisher<robot_msgs::msg::RobotState>> controller_state_publisher_;
#if defined(ROS_DISTRO_FOXY)
rclcpp::Time previous_update_timestamp_{0};
#endif
};
} // namespace robot_joint_controller
#endif // ROBOT_JOINT_CONTROLLER_GROUP_HPP

View File

@ -0,0 +1,35 @@
#ifndef ROBOT_JOINT_CONTROLLER__VISIBILITY_CONTROL_H_
#define ROBOT_JOINT_CONTROLLER__VISIBILITY_CONTROL_H_
// This logic was borrowed (then namespaced) from the examples on the gcc wiki:
// https://gcc.gnu.org/wiki/Visibility
#if defined _WIN32 || defined __CYGWIN__
#ifdef __GNUC__
#define ROBOT_JOINT_CONTROLLER_EXPORT __attribute__((dllexport))
#define ROBOT_JOINT_CONTROLLER_IMPORT __attribute__((dllimport))
#else
#define ROBOT_JOINT_CONTROLLER_EXPORT __declspec(dllexport)
#define ROBOT_JOINT_CONTROLLER_IMPORT __declspec(dllimport)
#endif
#ifdef ROBOT_JOINT_CONTROLLER_BUILDING_DLL
#define ROBOT_JOINT_CONTROLLER_PUBLIC ROBOT_JOINT_CONTROLLER_EXPORT
#else
#define ROBOT_JOINT_CONTROLLER_PUBLIC ROBOT_JOINT_CONTROLLER_IMPORT
#endif
#define ROBOT_JOINT_CONTROLLER_PUBLIC_TYPE ROBOT_JOINT_CONTROLLER_PUBLIC
#define ROBOT_JOINT_CONTROLLER_LOCAL
#else
#define ROBOT_JOINT_CONTROLLER_EXPORT __attribute__((visibility("default")))
#define ROBOT_JOINT_CONTROLLER_IMPORT
#if __GNUC__ >= 4
#define ROBOT_JOINT_CONTROLLER_PUBLIC __attribute__((visibility("default")))
#define ROBOT_JOINT_CONTROLLER_LOCAL __attribute__((visibility("hidden")))
#else
#define ROBOT_JOINT_CONTROLLER_PUBLIC
#define ROBOT_JOINT_CONTROLLER_LOCAL
#endif
#define ROBOT_JOINT_CONTROLLER_PUBLIC_TYPE
#endif
#endif // ROBOT_JOINT_CONTROLLER__VISIBILITY_CONTROL_H_

View File

@ -1,27 +1,27 @@
<?xml version="1.0"?>
<package format="2">
<name>robot_joint_controller</name>
<version>0.0.0</version>
<description>The robot_joint_controller package</description>
<maintainer email="fanziqi614@gmail.com">Ziqi Fan</maintainer>
<license>Apache</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>controller_interface</build_depend>
<build_depend>hardware_interface</build_depend>
<build_depend>pluginlib</build_depend>
<build_depend>roscpp</build_depend>
<build_export_depend>controller_interface</build_export_depend>
<build_export_depend>hardware_interface</build_export_depend>
<build_export_depend>pluginlib</build_export_depend>
<build_export_depend>roscpp</build_export_depend>
<exec_depend>controller_interface</exec_depend>
<exec_depend>hardware_interface</exec_depend>
<exec_depend>pluginlib</exec_depend>
<exec_depend>roscpp</exec_depend>
<depend>robot_msgs</depend>
<!-- The export tag contains other, unspecified, tags -->
<export>
<!-- Other tools can request additional information be placed here -->
<controller_interface plugin="${prefix}/robot_joint_controller_plugins.xml"/>
</export>
</package>
<package format="3">
<name>robot_joint_controller</name>
<version>0.0.0</version>
<description>The robot_joint_controller package</description>
<maintainer email="fanziqi614@gmail.com">Ziqi Fan</maintainer>
<license>Apache-2.0</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>rclcpp</depend>
<depend>urdf</depend>
<depend>control_toolbox</depend>
<depend>realtime_tools</depend>
<depend>hardware_interface</depend>
<depend>controller_interface</depend>
<depend>pluginlib</depend>
<depend>robot_msgs</depend>
<depend>geometry_msgs</depend>
<depend>rcl_interfaces</depend>
<export>
<build_type>ament_cmake</build_type>
<pluginlib plugin="${prefix}/share/${PROJECT_NAME}/robot_joint_controller_plugins.xml"/>
</export>
</package>

View File

@ -1,8 +1,12 @@
<library path="lib/librobot_joint_controller">
<class name="robot_joint_controller/RobotJointController"
type="robot_joint_controller::RobotJointController"
base_class_type="controller_interface::ControllerBase"/>
<description>
The robot joint controller.
</description>
<library path="robot_joint_controller">
<class name="robot_joint_controller/RobotJointController"
type="robot_joint_controller::RobotJointController"
base_class_type="controller_interface::ControllerInterface">
<description>The robot joint single controller</description>
</class>
<class name="robot_joint_controller/RobotJointControllerGroup"
type="robot_joint_controller::RobotJointControllerGroup"
base_class_type="controller_interface::ControllerInterface">
<description>The robot joint group controller</description>
</class>
</library>

View File

@ -1,198 +1,231 @@
#include "robot_joint_controller.h"
#include <pluginlib/class_list_macros.h>
// #define rqtTune // use rqt or not
double clamp(double &value, double min, double max)
{
if (value < min)
{
value = min;
}
else if (value > max)
{
value = max;
}
return value;
}
#include "robot_joint_controller.hpp"
#include "hardware_interface/types/hardware_interface_type_values.hpp"
#include <pluginlib/class_list_macros.hpp>
namespace robot_joint_controller
{
using hardware_interface::HW_IF_POSITION;
using hardware_interface::HW_IF_VELOCITY;
using hardware_interface::HW_IF_EFFORT;
RobotJointController::RobotJointController()
RobotJointController::RobotJointController()
: controller_interface::ControllerInterface(),
joints_command_subscriber_(nullptr),
controller_state_publisher_(nullptr)
{
memset(&last_command_, 0, sizeof(robot_msgs::msg::MotorCommand));
memset(&last_state_, 0, sizeof(robot_msgs::msg::MotorState));
memset(&servo_command_, 0, sizeof(ServoCommand));
}
// CallbackReturn RobotJointController::on_init()
// {
// return CallbackReturn::SUCCESS;
// }
CallbackReturn RobotJointController::on_configure(const rclcpp_lifecycle::State &previous_state)
{
name_space_ = get_node()->get_namespace();
if (!get_node()->get_parameter("joints", joint_name_))
{
memset(&lastCommand, 0, sizeof(robot_msgs::MotorCommand));
memset(&lastState, 0, sizeof(robot_msgs::MotorState));
memset(&servoCommand, 0, sizeof(ServoCommand));
RCLCPP_ERROR(get_node()->get_logger(), "No joint given in namespace: '%s'", name_space_.c_str());
return CallbackReturn::ERROR;
}
else
{
RCLCPP_WARN(get_node()->get_logger(), "joint_name_: %s", joint_name_.c_str());
}
RobotJointController::~RobotJointController()
{
sub_ft.shutdown();
sub_command.shutdown();
}
robot_description_client_ = get_node()->create_client<rcl_interfaces::srv::GetParameters>("/robot_state_publisher/get_parameters");
void RobotJointController::setCommandCB(const robot_msgs::MotorCommandConstPtr &msg)
{
lastCommand.q = msg->q;
lastCommand.kp = msg->kp;
lastCommand.dq = msg->dq;
lastCommand.kd = msg->kd;
lastCommand.tau = msg->tau;
// the writeFromNonRT can be used in RT, if you have the guarantee that
// * no non-rt thread is calling the same function (we're not subscribing to ros callbacks)
// * there is only one single rt thread
command.writeFromNonRT(lastCommand);
}
auto request = std::make_shared<rcl_interfaces::srv::GetParameters::Request>();
request->names.push_back("robot_description_");
// Controller initialization in non-realtime
bool RobotJointController::init(hardware_interface::EffortJointInterface *robot, ros::NodeHandle &n)
while (!robot_description_client_->wait_for_service(std::chrono::seconds(1)))
{
name_space = n.getNamespace();
if (!n.getParam("joint", joint_name))
if (!rclcpp::ok())
{
ROS_ERROR("No joint given in namespace: '%s')", n.getNamespace().c_str());
return false;
RCLCPP_ERROR(get_node()->get_logger(), "Interrupted while waiting for the service. Exiting.");
}
RCLCPP_WARN(get_node()->get_logger(), "Service not available, waiting again...");
}
auto response_received_callback = [this](rclcpp::Client<rcl_interfaces::srv::GetParameters>::SharedFuture future)
{
std::string robot_description = future.get()->values[0].string_value;
urdf::Model urdf;
if (!urdf.initString(robot_description))
{
RCLCPP_ERROR(get_node()->get_logger(), "Failed to parse urdf file");
}
// load pid param from ymal only if rqt need
#ifdef rqtTune
// Load PID Controller using gains set on parameter server
if (!pid_controller_.init(ros::NodeHandle(n, "pid")))
return false;
joints_urdf_ = urdf.getJoint(joint_name_);
if (!joints_urdf_)
{
RCLCPP_ERROR(get_node()->get_logger(),"Could not find joint '%s' in urdf", joint_name_.c_str());
}
};
auto future_result = robot_description_client_->async_send_request(request, response_received_callback);
// Start command subscriber
joints_command_subscriber_ = get_node()->create_subscription<robot_msgs::msg::MotorCommand>(
"~/command", rclcpp::SystemDefaultsQoS(), std::bind(&RobotJointController::SetCommandCallback, this, std::placeholders::_1));
// Start realtime state publisher
controller_state_publisher_ = std::make_shared<realtime_tools::RealtimePublisher<robot_msgs::msg::MotorState>>(
get_node()->create_publisher<robot_msgs::msg::MotorState>(/*name_space_ + */"~/state", rclcpp::SystemDefaultsQoS()));
#if defined(ROS_DISTRO_FOXY)
previous_update_timestamp_ = get_node()->get_clock()->now();
#endif
urdf::Model urdf; // Get URDF info about joint
if (!urdf.initParamWithNodeHandle("robot_description", n))
{
ROS_ERROR("Failed to parse urdf file");
return false;
}
joint_urdf = urdf.getJoint(joint_name);
if (!joint_urdf)
{
ROS_ERROR("Could not find joint '%s' in urdf", joint_name.c_str());
return false;
}
joint = robot->getHandle(joint_name);
RCLCPP_INFO(get_node()->get_logger(), "configure successful");
return CallbackReturn::SUCCESS;
}
// Start command subscriber
sub_command = n.subscribe("command", 20, &RobotJointController::setCommandCB, this);
controller_interface::InterfaceConfiguration RobotJointController::command_interface_configuration() const
{
controller_interface::InterfaceConfiguration command_interfaces_config;
command_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL;
// Start realtime state publisher
controller_state_publisher_.reset(
new realtime_tools::RealtimePublisher<robot_msgs::MotorState>(n, name_space + "/state", 1));
command_interfaces_config.names.push_back(joint_name_ + "/" + HW_IF_EFFORT);
return true;
}
return command_interfaces_config;
void RobotJointController::setGains(const double &p, const double &i, const double &d, const double &i_max, const double &i_min, const bool &antiwindup)
}
controller_interface::InterfaceConfiguration RobotJointController::state_interface_configuration() const
{
controller_interface::InterfaceConfiguration state_interfaces_config;
state_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL;
state_interfaces_config.names.push_back(joint_name_ + "/" + HW_IF_POSITION);
state_interfaces_config.names.push_back(joint_name_ + "/" + HW_IF_EFFORT);
return state_interfaces_config;
}
CallbackReturn RobotJointController::on_activate(const rclcpp_lifecycle::State &previous_state)
{
double init_pos = state_interfaces_[0].get_value();
last_command_.q = init_pos;
last_state_.q = init_pos;
last_command_.dq = 0;
last_state_.dq = 0;
last_command_.tau = 0;
last_state_.tau_est = 0;
// reset command buffer if a command came through callback when controller was inactive
rt_command_ptr_ = realtime_tools::RealtimeBuffer<robot_msgs::msg::MotorCommand>();
return CallbackReturn::SUCCESS;
}
CallbackReturn RobotJointController::on_deactivate(const rclcpp_lifecycle::State &previous_state)
{
// reset command buffer
rt_command_ptr_ = realtime_tools::RealtimeBuffer<robot_msgs::msg::MotorCommand>();
return CallbackReturn::SUCCESS;
}
#if defined(ROS_DISTRO_FOXY)
controller_interface::return_type RobotJointController::update()
{
const auto current_time = get_node()->get_clock()->now();
const auto period_seconds = (current_time - previous_update_timestamp_).seconds();
previous_update_timestamp_ = current_time;
auto joint_command = rt_command_ptr_.readFromRT();
// no command received yet
if (!joint_command)
{
pid_controller_.setGains(p, i, d, i_max, i_min, antiwindup);
return controller_interface::return_type::OK;
}
void RobotJointController::getGains(double &p, double &i, double &d, double &i_max, double &i_min, bool &antiwindup)
last_command_ = *(joint_command);
UpdateFunc(period_seconds);
return controller_interface::return_type::OK;
}
#elif defined(ROS_DISTRO_HUMBLE)
controller_interface::return_type RobotJointController::update(const rclcpp::Time &time, const rclcpp::Duration &period)
{
const auto period_seconds = period.seconds();
auto joint_command = rt_command_ptr_.readFromRT();
// no command received yet
if (!joint_command)
{
pid_controller_.getGains(p, i, d, i_max, i_min, antiwindup);
return controller_interface::return_type::OK;
}
void RobotJointController::getGains(double &p, double &i, double &d, double &i_max, double &i_min)
{
bool dummy;
pid_controller_.getGains(p, i, d, i_max, i_min, dummy);
}
// Controller startup in realtime
void RobotJointController::starting(const ros::Time &time)
{
double init_pos = joint.getPosition();
lastCommand.q = init_pos;
lastState.q = init_pos;
lastCommand.dq = 0;
lastState.dq = 0;
lastCommand.tau = 0;
lastState.tauEst = 0;
command.initRT(lastCommand);
pid_controller_.reset();
}
// Controller update loop in realtime
void RobotJointController::update(const ros::Time &time, const ros::Duration &period)
{
double currentPos, currentVel, calcTorque;
lastCommand = *(command.readFromRT());
// set command data
servoCommand.pos = lastCommand.q;
positionLimits(servoCommand.pos);
servoCommand.posStiffness = lastCommand.kp;
if (fabs(lastCommand.q - PosStopF) < 0.00001)
{
servoCommand.posStiffness = 0;
}
servoCommand.vel = lastCommand.dq;
velocityLimits(servoCommand.vel);
servoCommand.velStiffness = lastCommand.kd;
if (fabs(lastCommand.dq - VelStopF) < 0.00001)
{
servoCommand.velStiffness = 0;
}
servoCommand.torque = lastCommand.tau;
effortLimits(servoCommand.torque);
// rqt set P D gains
#ifdef rqtTune
double i, i_max, i_min;
getGains(servoCommand.posStiffness, i, servoCommand.velStiffness, i_max, i_min);
last_command_ = *(joint_command);
UpdateFunc(period_seconds);
return controller_interface::return_type::OK;
}
#endif
currentPos = joint.getPosition();
// currentVel = computeVel(currentPos, (double)lastState.q, (double)lastState.dq, period.toSec());
// calcTorque = computeTorque(currentPos, currentVel, servoCommand);
currentVel = (currentPos - (double)lastState.q) / period.toSec();
calcTorque = servoCommand.posStiffness * (servoCommand.pos - currentPos) + servoCommand.velStiffness * (servoCommand.vel - currentVel) + servoCommand.torque;
effortLimits(calcTorque);
void RobotJointController::UpdateFunc(const double &period_seconds)
{
double currentPos = 0.0;
double currentVel = 0.0;
double calcTorque = 0.0;
joint.setCommand(calcTorque);
lastState.q = currentPos;
lastState.dq = currentVel;
// lastState.tauEst = calcTorque;
lastState.tauEst = joint.getEffort();
// publish state
if (controller_state_publisher_ && controller_state_publisher_->trylock())
{
controller_state_publisher_->msg_.q = lastState.q;
controller_state_publisher_->msg_.dq = lastState.dq;
controller_state_publisher_->msg_.tauEst = lastState.tauEst;
controller_state_publisher_->unlockAndPublish();
}
}
// Controller stopping in realtime
void RobotJointController::stopping() {}
void RobotJointController::positionLimits(double &position)
// set command data
servo_command_.pos = last_command_.q;
PositionLimit(servo_command_.pos);
servo_command_.pos_stiffness = last_command_.kp;
if (fabs(last_command_.q - PosStopF) < 0.00001)
{
if (joint_urdf->type == urdf::Joint::REVOLUTE || joint_urdf->type == urdf::Joint::PRISMATIC)
clamp(position, joint_urdf->limits->lower, joint_urdf->limits->upper);
servo_command_.pos_stiffness = 0;
}
void RobotJointController::velocityLimits(double &velocity)
servo_command_.vel = last_command_.dq;
VelocityLimit(servo_command_.vel);
servo_command_.vel_stiffness = last_command_.kd;
if (fabs(last_command_.dq - VelStopF) < 0.00001)
{
if (joint_urdf->type == urdf::Joint::REVOLUTE || joint_urdf->type == urdf::Joint::PRISMATIC)
clamp(velocity, -joint_urdf->limits->velocity, joint_urdf->limits->velocity);
servo_command_.vel_stiffness = 0;
}
servo_command_.torque = last_command_.tau;
EffortLimit(servo_command_.torque);
void RobotJointController::effortLimits(double &effort)
currentPos = state_interfaces_[0].get_value();
currentVel = (currentPos - (double)(last_state_.q)) / period_seconds;
calcTorque = servo_command_.pos_stiffness * (servo_command_.pos - currentPos) + servo_command_.vel_stiffness * (servo_command_.vel - currentVel) + servo_command_.torque;
EffortLimit(calcTorque);
command_interfaces_[0].set_value(calcTorque);
last_state_.q = currentPos;
last_state_.dq = currentVel;
last_state_.tau_est = state_interfaces_[1].get_value();
// publish state
if (controller_state_publisher_ && controller_state_publisher_->trylock())
{
if (joint_urdf->type == urdf::Joint::REVOLUTE || joint_urdf->type == urdf::Joint::PRISMATIC)
clamp(effort, -joint_urdf->limits->effort, joint_urdf->limits->effort);
controller_state_publisher_->msg_ = last_state_;
controller_state_publisher_->unlockAndPublish();
}
}
} // namespace
void RobotJointController::SetCommandCallback(const robot_msgs::msg::MotorCommand::SharedPtr msg)
{
last_command_ = *msg;
rt_command_ptr_.writeFromNonRT(last_command_);
}
void RobotJointController::PositionLimit(double &position)
{
std::clamp(position, joints_urdf_->limits->lower, joints_urdf_->limits->upper);
}
void RobotJointController::VelocityLimit(double &velocity)
{
std::clamp(velocity, -joints_urdf_->limits->velocity, joints_urdf_->limits->velocity);
}
void RobotJointController::EffortLimit(double &effort)
{
std::clamp(effort, -joints_urdf_->limits->effort, joints_urdf_->limits->effort);
}
} // namespace robot_joint_controller
// Register controller to pluginlib
PLUGINLIB_EXPORT_CLASS(robot_joint_controller::RobotJointController, controller_interface::ControllerBase);
PLUGINLIB_EXPORT_CLASS(robot_joint_controller::RobotJointController, controller_interface::ControllerInterface)

View File

@ -0,0 +1,278 @@
#include "robot_joint_controller_group.hpp"
#include "hardware_interface/types/hardware_interface_type_values.hpp"
#include <pluginlib/class_list_macros.hpp>
namespace robot_joint_controller
{
using hardware_interface::HW_IF_POSITION;
using hardware_interface::HW_IF_VELOCITY;
using hardware_interface::HW_IF_EFFORT;
RobotJointControllerGroup::RobotJointControllerGroup()
: controller_interface::ControllerInterface(),
joints_command_subscriber_(nullptr),
controller_state_publisher_(nullptr)
{
memset(&servo_command_, 0, sizeof(ServoCommand));
}
// CallbackReturn RobotJointControllerGroup::on_init()
// {
// return CallbackReturn::SUCCESS;
// }
CallbackReturn RobotJointControllerGroup::on_configure(const rclcpp_lifecycle::State &previous_state)
{
name_space_ = get_node()->get_namespace();
joint_names_ = get_node()->get_parameter("joints").as_string_array();
if (joint_names_.empty())
{
RCLCPP_ERROR(get_node()->get_logger(), "'joints' parameter was empty");
return CallbackReturn::ERROR;
}
else
{
for (const auto& joint_name : joint_names_)
{
RCLCPP_WARN(get_node()->get_logger(), "joint_name: %s", joint_name.c_str());
}
}
robot_description_client_ = get_node()->create_client<rcl_interfaces::srv::GetParameters>("/robot_state_publisher/get_parameters");
auto request = std::make_shared<rcl_interfaces::srv::GetParameters::Request>();
request->names.push_back("robot_description");
while (!robot_description_client_->wait_for_service(std::chrono::seconds(1)))
{
if (!rclcpp::ok())
{
RCLCPP_ERROR(get_node()->get_logger(), "Interrupted while waiting for the service. Exiting.");
}
RCLCPP_WARN(get_node()->get_logger(), "Service not available, waiting again...");
}
auto response_received_callback = [this](rclcpp::Client<rcl_interfaces::srv::GetParameters>::SharedFuture future)
{
std::string robot_description = future.get()->values[0].string_value;
urdf::Model urdf;
if (!urdf.initString(robot_description))
{
RCLCPP_ERROR(get_node()->get_logger(), "Failed to parse urdf file");
}
for (const auto& joint_name : joint_names_)
{
auto joint_urdf = urdf.getJoint(joint_name);
if (!joint_urdf)
{
RCLCPP_ERROR(get_node()->get_logger(),"Could not find joint '%s' in urdf", joint_name.c_str());
}
if (joint_urdf)
{
joints_urdf_.push_back(joint_urdf);
}
}
};
auto future_result = robot_description_client_->async_send_request(request, response_received_callback);
// Start command subscriber
joints_command_subscriber_ = get_node()->create_subscription<robot_msgs::msg::RobotCommand>(
"~/command", rclcpp::SystemDefaultsQoS(), std::bind(&RobotJointControllerGroup::SetCommandCallback, this, std::placeholders::_1));
// Start realtime state publisher
controller_state_publisher_ = std::make_shared<realtime_tools::RealtimePublisher<robot_msgs::msg::RobotState>>(
get_node()->create_publisher<robot_msgs::msg::RobotState>(/*name_space_ + */"~/state", rclcpp::SystemDefaultsQoS()));
#if defined(ROS_DISTRO_FOXY)
previous_update_timestamp_ = get_node()->get_clock()->now();
#endif
RCLCPP_INFO(get_node()->get_logger(), "configure successful");
return CallbackReturn::SUCCESS;
}
controller_interface::InterfaceConfiguration RobotJointControllerGroup::command_interface_configuration() const
{
controller_interface::InterfaceConfiguration command_interfaces_config;
command_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL;
for (const auto & joint_name : joint_names_)
{
command_interfaces_config.names.push_back(joint_name + "/" + HW_IF_EFFORT);
}
return command_interfaces_config;
}
controller_interface::InterfaceConfiguration RobotJointControllerGroup::state_interface_configuration() const
{
controller_interface::InterfaceConfiguration state_interfaces_config;
state_interfaces_config.type = controller_interface::interface_configuration_type::INDIVIDUAL;
for (const auto & joint_name : joint_names_)
{
state_interfaces_config.names.push_back(joint_name + "/" + HW_IF_POSITION);
state_interfaces_config.names.push_back(joint_name + "/" + HW_IF_EFFORT);
}
return state_interfaces_config;
}
CallbackReturn RobotJointControllerGroup::on_activate(const rclcpp_lifecycle::State &previous_state)
{
last_command_ = robot_msgs::msg::RobotCommand();
last_command_.motor_command.resize(joint_names_.size());
last_state_ = robot_msgs::msg::RobotState();
last_state_.motor_state.resize(joint_names_.size());
for (int index = 0; index < joint_names_.size(); ++index)
{
double init_pos = state_interfaces_[index * 2].get_value();
last_command_.motor_command[index].q = init_pos;
last_state_.motor_state[index].q = init_pos;
last_command_.motor_command[index].dq = 0;
last_state_.motor_state[index].dq = 0;
last_command_.motor_command[index].tau = 0;
last_state_.motor_state[index].tau_est = 0;
}
// reset command buffer if a command came through callback when controller was inactive
rt_command_ptr_ = realtime_tools::RealtimeBuffer<robot_msgs::msg::RobotCommand>();
rt_command_ptr_.writeFromNonRT(last_command_);
return CallbackReturn::SUCCESS;
}
CallbackReturn RobotJointControllerGroup::on_deactivate(const rclcpp_lifecycle::State &previous_state)
{
last_command_ = robot_msgs::msg::RobotCommand();
last_command_.motor_command.resize(joint_names_.size());
last_state_ = robot_msgs::msg::RobotState();
last_state_.motor_state.resize(joint_names_.size());
// reset command buffer
rt_command_ptr_ = realtime_tools::RealtimeBuffer<robot_msgs::msg::RobotCommand>();
rt_command_ptr_.writeFromNonRT(last_command_);
return CallbackReturn::SUCCESS;
}
#if defined(ROS_DISTRO_FOXY)
controller_interface::return_type RobotJointControllerGroup::update()
{
const auto current_time = get_node()->get_clock()->now();
const auto period_seconds = (current_time - previous_update_timestamp_).seconds();
previous_update_timestamp_ = current_time;
auto joint_commands = rt_command_ptr_.readFromRT();
// no command received yet
if (!joint_commands)
{
return controller_interface::return_type::OK;
}
if (joint_commands->motor_command.size() != joint_names_.size())
{
RCLCPP_ERROR_THROTTLE(get_node()->get_logger(), *get_node()->get_clock(), 1000,
"command size (%zu) does not match number of interfaces (%zu)",
joint_commands->motor_command.size(), joint_names_.size());
return controller_interface::return_type::ERROR;
}
last_command_ = *(joint_commands);
UpdateFunc(period_seconds);
return controller_interface::return_type::OK;
}
#elif defined(ROS_DISTRO_HUMBLE)
controller_interface::return_type RobotJointControllerGroup::update(const rclcpp::Time &time, const rclcpp::Duration &period)
{
const auto period_seconds = period.seconds();
auto joint_commands = rt_command_ptr_.readFromRT();
// no command received yet
if (!joint_commands)
{
return controller_interface::return_type::OK;
}
if (joint_commands->motor_command.size() != joint_names_.size())
{
RCLCPP_ERROR_THROTTLE(get_node()->get_logger(), *get_node()->get_clock(), 1000,
"command size (%zu) does not match number of interfaces (%zu)",
joint_commands->motor_command.size(), joint_names_.size());
return controller_interface::return_type::ERROR;
}
last_command_ = *(joint_commands);
UpdateFunc(period_seconds);
return controller_interface::return_type::OK;
}
#endif
void RobotJointControllerGroup::UpdateFunc(const double &period_seconds)
{
std::vector<double> currentPos(joint_names_.size(), 0.0);
std::vector<double> currentVel(joint_names_.size(), 0.0);
std::vector<double> calcTorque(joint_names_.size(), 0.0);
for (int index = 0; index < joint_names_.size(); ++index)
{
// set command data
servo_command_.pos = last_command_.motor_command[index].q;
PositionLimit(servo_command_.pos, index);
servo_command_.pos_stiffness = last_command_.motor_command[index].kp;
if (fabs(last_command_.motor_command[index].q - PosStopF) < 0.00001)
{
servo_command_.pos_stiffness = 0;
}
servo_command_.vel = last_command_.motor_command[index].dq;
VelocityLimit(servo_command_.vel, index);
servo_command_.vel_stiffness = last_command_.motor_command[index].kd;
if (fabs(last_command_.motor_command[index].dq - VelStopF) < 0.00001)
{
servo_command_.vel_stiffness = 0;
}
servo_command_.torque = last_command_.motor_command[index].tau;
EffortLimit(servo_command_.torque, index);
currentPos[index] = state_interfaces_[index * 2].get_value();
currentVel[index] = (currentPos[index] - (double)(last_state_.motor_state[index].q)) / period_seconds;
calcTorque[index] = servo_command_.pos_stiffness * (servo_command_.pos - currentPos[index]) + servo_command_.vel_stiffness * (servo_command_.vel - currentVel[index]) + servo_command_.torque;
EffortLimit(calcTorque[index], index);
command_interfaces_[index].set_value(calcTorque[index]);
last_state_.motor_state[index].q = currentPos[index];
last_state_.motor_state[index].dq = currentVel[index];
last_state_.motor_state[index].tau_est = state_interfaces_[index + 1].get_value();
}
// publish state
if (controller_state_publisher_ && controller_state_publisher_->trylock())
{
controller_state_publisher_->msg_.motor_state = last_state_.motor_state;
controller_state_publisher_->unlockAndPublish();
}
}
void RobotJointControllerGroup::SetCommandCallback(const robot_msgs::msg::RobotCommand::SharedPtr msg)
{
last_command_ = *msg;
rt_command_ptr_.writeFromNonRT(last_command_);
}
void RobotJointControllerGroup::PositionLimit(double &position, int &index)
{
std::clamp(position, joints_urdf_[index]->limits->lower, joints_urdf_[index]->limits->upper);
}
void RobotJointControllerGroup::VelocityLimit(double &velocity, int &index)
{
std::clamp(velocity, -joints_urdf_[index]->limits->velocity, joints_urdf_[index]->limits->velocity);
}
void RobotJointControllerGroup::EffortLimit(double &effort, int &index)
{
std::clamp(effort, -joints_urdf_[index]->limits->effort, joints_urdf_[index]->limits->effort);
}
} // namespace robot_joint_controller
// Register controller to pluginlib
PLUGINLIB_EXPORT_CLASS(robot_joint_controller::RobotJointControllerGroup, controller_interface::ControllerInterface)

View File

@ -1,44 +1,17 @@
cmake_minimum_required(VERSION 2.8.3)
cmake_minimum_required(VERSION 3.5)
project(robot_msgs)
find_package(catkin REQUIRED COMPONENTS
message_generation
std_msgs
geometry_msgs
sensor_msgs
# find dependencies
find_package(ament_cmake REQUIRED)
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/MotorCommand.msg"
"msg/MotorState.msg"
"msg/RobotCommand.msg"
"msg/RobotState.msg"
"msg/IMU.msg"
)
add_message_files(
FILES
MotorCommand.msg
MotorState.msg
RobotCommand.msg
RobotState.msg
IMU.msg
)
generate_messages(
DEPENDENCIES
std_msgs
geometry_msgs
sensor_msgs
)
catkin_package(
CATKIN_DEPENDS
message_runtime
std_msgs
geometry_msgs
sensor_msgs
)
#############
## Install ##
#############
# Mark topic names header files for installation
install(
DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
)
ament_package()

View File

@ -1,5 +1,5 @@
float32 q # motor current position (rad)
float32 dq # motor current speed (rad/s)
float32 ddq # motor current speed (rad/s)
float32 tauEst # current estimated output torque (N*m)
float32 q # motor current pos (rad)
float32 dq # motor current vel (rad/s)
float32 ddq # motor current acc (rad/s^2)
float32 tau_est # current estimated output torque (N*m)
float32 cur # current estimated output cur (N*m)

View File

@ -1 +1 @@
MotorCommand[32] motor_command
MotorCommand[] motor_command

View File

@ -1,2 +1,2 @@
IMU imu
MotorState[32] motor_state
MotorState[] motor_state

View File

@ -1,19 +1,19 @@
<?xml version="1.0"?>
<package format="2">
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
<name>robot_msgs</name>
<version>0.0.0</version>
<description>
The robot messgaes package.
</description>
<description>The robot messages package.</description>
<maintainer email="fanziqi614@gmail.com">Ziqi Fan</maintainer>
<license>Apache</license>
<buildtool_depend>catkin</buildtool_depend>
<depend>message_runtime</depend>
<depend>message_generation</depend>
<depend>std_msgs</depend>
<depend>geometry_msgs</depend>
<depend>sensor_msgs</depend>
</package>
<license>Apache 2.0</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<export>
<build_type>ament_cmake</build_type>
</export>
<build_depend>rosidl_default_generators</build_depend>
<exec_depend>rosidl_default_runtime</exec_depend>
<member_of_group>rosidl_interface_packages</member_of_group>
</package>

View File

@ -1,18 +1,22 @@
cmake_minimum_required(VERSION 2.8.3)
cmake_minimum_required(VERSION 3.8)
project(a1_description)
find_package(catkin REQUIRED COMPONENTS
genmsg
roscpp
std_msgs
tf
find_package(ament_cmake REQUIRED)
find_package(ament_lint_auto REQUIRED)
find_package(urdf REQUIRED)
find_package(xacro REQUIRED)
find_package(robot_state_publisher REQUIRED)
install(
DIRECTORY
config
launch
meshes
urdf
xacro
DESTINATION
share/${PROJECT_NAME}/
)
catkin_package(
CATKIN_DEPENDS
)
include_directories(
# include
${catkin_INCLUDE_DIRS}
)
ament_package()

View File

@ -1,70 +1,113 @@
a1_gazebo:
# Publish all joint states -----------------------------------
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 1000
controller_manager:
ros__parameters:
update_rate: 1000 # Hz
# use_sim_time: true # If running in simulation
# FL Controllers ---------------------------------------
FL_hip_controller:
type: robot_joint_controller/RobotJointController
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
imu_sensor_broadcaster:
type: imu_sensor_broadcaster/ImuSensorBroadcaster
# FL Controllers ---------------------------------------
FL_hip_controller:
type: robot_joint_controller/RobotJointController
FL_thigh_controller:
type: robot_joint_controller/RobotJointController
FL_calf_controller:
type: robot_joint_controller/RobotJointController
# FR Controllers ---------------------------------------
FR_hip_controller:
type: robot_joint_controller/RobotJointController
FR_thigh_controller:
type: robot_joint_controller/RobotJointController
FR_calf_controller:
type: robot_joint_controller/RobotJointController
# RL Controllers ---------------------------------------
RL_hip_controller:
type: robot_joint_controller/RobotJointController
RL_thigh_controller:
type: robot_joint_controller/RobotJointController
RL_calf_controller:
type: robot_joint_controller/RobotJointController
# RR Controllers ---------------------------------------
RR_hip_controller:
type: robot_joint_controller/RobotJointController
RR_thigh_controller:
type: robot_joint_controller/RobotJointController
RR_calf_controller:
type: robot_joint_controller/RobotJointController
# FL Controllers ---------------------------------------
FL_hip_controller:
ros__parameters:
joint: FL_hip_joint
pid: {p: 100.0, i: 0.0, d: 5.0}
FL_thigh_controller:
type: robot_joint_controller/RobotJointController
FL_thigh_controller:
ros__parameters:
joint: FL_thigh_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
FL_calf_controller:
type: robot_joint_controller/RobotJointController
FL_calf_controller:
ros__parameters:
joint: FL_calf_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
# FR Controllers ---------------------------------------
FR_hip_controller:
type: robot_joint_controller/RobotJointController
# FR Controllers ---------------------------------------
FR_hip_controller:
ros__parameters:
joint: FR_hip_joint
pid: {p: 100.0, i: 0.0, d: 5.0}
FR_thigh_controller:
type: robot_joint_controller/RobotJointController
FR_thigh_controller:
ros__parameters:
joint: FR_thigh_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
FR_calf_controller:
type: robot_joint_controller/RobotJointController
FR_calf_controller:
ros__parameters:
joint: FR_calf_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
# RL Controllers ---------------------------------------
RL_hip_controller:
type: robot_joint_controller/RobotJointController
# RL Controllers ---------------------------------------
RL_hip_controller:
ros__parameters:
joint: RL_hip_joint
pid: {p: 100.0, i: 0.0, d: 5.0}
RL_thigh_controller:
type: robot_joint_controller/RobotJointController
RL_thigh_controller:
ros__parameters:
joint: RL_thigh_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
RL_calf_controller:
type: robot_joint_controller/RobotJointController
RL_calf_controller:
ros__parameters:
joint: RL_calf_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
# RR Controllers ---------------------------------------
RR_hip_controller:
type: robot_joint_controller/RobotJointController
# RR Controllers ---------------------------------------
RR_hip_controller:
ros__parameters:
joint: RR_hip_joint
pid: {p: 100.0, i: 0.0, d: 5.0}
RR_thigh_controller:
type: robot_joint_controller/RobotJointController
RR_thigh_controller:
ros__parameters:
joint: RR_thigh_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
RR_calf_controller:
type: robot_joint_controller/RobotJointController
RR_calf_controller:
ros__parameters:
joint: RR_calf_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
imu_sensor_broadcaster:
ros__parameters:
sensor_name: "imu_sensor"
frame_id: imu_link

View File

@ -0,0 +1,34 @@
controller_manager:
ros__parameters:
update_rate: 1000 # Hz
# use_sim_time: true # If running in simulation
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
imu_sensor_broadcaster:
type: imu_sensor_broadcaster/ImuSensorBroadcaster
robot_joint_controller:
type: robot_joint_controller/RobotJointControllerGroup
robot_joint_controller:
ros__parameters:
joints:
- FL_hip_joint
- FL_thigh_joint
- FL_calf_joint
- FR_hip_joint
- FR_thigh_joint
- FR_calf_joint
- RL_hip_joint
- RL_thigh_joint
- RL_calf_joint
- RR_hip_joint
- RR_thigh_joint
- RR_calf_joint
imu_sensor_broadcaster:
ros__parameters:
sensor_name: "imu_sensor"
frame_id: imu_link

View File

@ -1,23 +0,0 @@
<launch>
<arg name="user_debug" default="false"/>
<param name="robot_description" command="$(find xacro)/xacro --inorder '$(find a1_description)/xacro/robot.xacro'
DEBUG:=$(arg user_debug)"/>
<!-- for higher robot_state_publisher average rate-->
<!-- <param name="rate" value="1000"/> -->
<!-- send fake joint values -->
<node pkg="joint_state_publisher" type="joint_state_publisher" name="joint_state_publisher">
<param name="use_gui" value="TRUE"/>
</node>
<node pkg="robot_state_publisher" type="robot_state_publisher" name="robot_state_publisher">
<param name="publish_frequency" type="double" value="1000.0"/>
</node>
<node pkg="rviz" type="rviz" name="rviz" respawn="false" output="screen"
args="-d $(find a1_description)/launch/check_joint.rviz"/>
</launch>

View File

@ -0,0 +1,83 @@
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
from launch.conditions import IfCondition
import xacro
def generate_launch_description():
####### DATA INPUT ##########
# urdf_file = 'moonbotX.urdf'
package_description = "a1_description"
use_sim_time = LaunchConfiguration('use_sim_time')
use_joint_state_publisher = LaunchConfiguration('use_joint_state_publisher')
# Process the URDF file
pkg_path = os.path.join(get_package_share_directory(package_description))
xacro_file = os.path.join(pkg_path,'xacro','robot.xacro')
robot_description_config = xacro.process_file(xacro_file)
jsp_arg = DeclareLaunchArgument(
'use_joint_state_publisher',
default_value='True'
)
# Create a robot_state_publisher node
params = {'robot_description': robot_description_config.toxml(), 'use_sim_time': use_sim_time}
robot_state_publisher_node = Node(
package='robot_state_publisher',
executable='robot_state_publisher',
name='robot_state_publisher_node',
emulate_tty=True,
output='screen',
parameters=[params]
)
# Joint State Publisher
joint_state_publisher_node = Node(
package='joint_state_publisher',
executable='joint_state_publisher',
output='screen',
condition=IfCondition(use_joint_state_publisher)
)
# RVIZ Configuration
rviz_config_dir = os.path.join(
get_package_share_directory(package_description),
'launch',
'check_joint.rviz'
)
rviz_node = Node(
package='rviz2',
executable='rviz2',
output='screen',
name='rviz_node',
parameters=[{'use_sim_time': True}],
arguments=['-d', rviz_config_dir]
)
return LaunchDescription([
DeclareLaunchArgument(
'use_sim_time',
default_value='false',
description='Use sim time if true'),
jsp_arg,
# map_publisher_node,
robot_state_publisher_node,
joint_state_publisher_node,
rviz_node
])

View File

@ -1,38 +1,33 @@
Panels:
- Class: rviz/Displays
- Class: rviz_common/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Status1
- /RobotModel1
Splitter Ratio: 0.5
Tree Height: 420
- Class: rviz/Selection
Tree Height: 617
- Class: rviz_common/Selection
Name: Selection
- Class: rviz/Tool Properties
- Class: rviz_common/Tool Properties
Expanded:
- /2D Pose Estimate1
- /2D Nav Goal1
- /2D Goal Pose1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz/Views
- Class: rviz_common/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Experimental: false
Name: Time
SyncMode: 0
SyncSource: ""
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz/Grid
Class: rviz_default_plugins/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
@ -49,8 +44,16 @@ Visualization Manager:
Reference Frame: <Fixed Frame>
Value: true
- Alpha: 1
Class: rviz/RobotModel
Class: rviz_default_plugins/RobotModel
Collision Enabled: false
Description File: ""
Description Source: Topic
Description Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /robot_description
Enabled: true
Links:
All Links Enabled: true
@ -174,92 +177,86 @@ Visualization Manager:
Show Trail: false
Value: true
Name: RobotModel
Robot Description: robot_description
TF Prefix: ""
Update Interval: 0
Value: true
Visual Enabled: true
- Class: rviz/Axes
Enabled: false
Length: 1
Name: Axes
Radius: 0.10000000149011612
Reference Frame: <Fixed Frame>
Value: false
- Class: rviz/TF
Enabled: false
Frame Timeout: 15
Frames:
All Enabled: true
Marker Scale: 1
Name: TF
Show Arrows: true
Show Axes: true
Show Names: true
Tree:
{}
Update Interval: 0
Value: false
Enabled: true
Global Options:
Background Color: 238; 238; 238
Default Light: true
Background Color: 48; 48; 48
Fixed Frame: base
Frame Rate: 30
Name: root
Tools:
- Class: rviz/Interact
- Class: rviz_default_plugins/Interact
Hide Inactive Objects: true
- Class: rviz/MoveCamera
- Class: rviz/Select
- Class: rviz/FocusCamera
- Class: rviz/Measure
- Class: rviz/SetInitialPose
Topic: /initialpose
- Class: rviz/SetGoal
Topic: /move_base_simple/goal
- Class: rviz/PublishPoint
- Class: rviz_default_plugins/MoveCamera
- Class: rviz_default_plugins/Select
- Class: rviz_default_plugins/FocusCamera
- Class: rviz_default_plugins/Measure
Line color: 128; 128; 0
- Class: rviz_default_plugins/SetInitialPose
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /initialpose
- Class: rviz_default_plugins/SetGoal
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /goal_pose
- Class: rviz_default_plugins/PublishPoint
Single click: true
Topic: /clicked_point
Topic:
Depth: 5
Durability Policy: Volatile
History Policy: Keep Last
Reliability Policy: Reliable
Value: /clicked_point
Transformation:
Current:
Class: rviz_default_plugins/TF
Value: true
Views:
Current:
Class: rviz/Orbit
Distance: 1.0307118892669678
Class: rviz_default_plugins/Orbit
Distance: 1.9769524335861206
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
X: 0.0760490670800209
Y: 0.11421932280063629
Z: -0.1576911211013794
Focal Shape Fixed Size: false
X: 0
Y: 0
Z: 0
Focal Shape Fixed Size: true
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
Pitch: 1.0047969818115234
Pitch: 0.21039816737174988
Target Frame: <Fixed Frame>
Value: Orbit (rviz)
Yaw: 4.558584690093994
Yaw: 0.9653980731964111
Saved: ~
Window Geometry:
Displays:
collapsed: false
Height: 627
Height: 846
Hide Left Dock: false
Hide Right Dock: false
QMainWindow State: 000000ff00000000fd00000004000000000000016a0000022ffc0200000009fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c00610079007301000000270000022f000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000c00430061006d00650072006101000001be000001900000000000000000000000010000010f000002e2fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a005600690065007700730000000028000002e2000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000006400000003efc0100000002fb0000000800540069006d0065000000000000000640000002eb00fffffffb0000000800540069006d00650100000000000004500000000000000000000002e40000022f00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
QMainWindow State: 000000ff00000000fd000000040000000000000156000002f4fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002f4000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002f4fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d000002f4000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004420000003efc0100000002fb0000000800540069006d00650100000000000004420000000000000000fb0000000800540069006d006501000000000000045000000000000000000000023f000002f400000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Time:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: false
Width: 1108
X: 812
Y: 241
Width: 1200
X: 617
Y: 102

View File

@ -0,0 +1,59 @@
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, RegisterEventHandler
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
from launch.event_handlers import OnProcessExit
import xacro
def generate_launch_description():
package_name = 'a1_description'
package_path = os.path.join(get_package_share_directory(package_name))
xacro_file = os.path.join(package_path, 'xacro', 'robot.xacro')
robot_description = xacro.process_file(xacro_file).toxml()
robot_state_publisher_node = Node(
package="robot_state_publisher",
executable="robot_state_publisher",
name='robot_state_publisher',
output="screen",
parameters=[{"robot_description": robot_description}],
)
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')
),
launch_arguments={'verbose': 'true'}.items()
)
spawn_entity = Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=['-topic', '/robot_description', '-entity', 'a1_gazebo'],
output='screen',
)
joint_state_broadcaster_node = Node(
package="controller_manager",
executable="spawner.py",
arguments=["joint_state_broadcaster"],
output='screen',
)
robot_joint_controller_node = Node(
package="controller_manager",
executable="spawner.py",
arguments=["robot_joint_controller"],
output='screen',
)
return LaunchDescription([
robot_state_publisher_node,
gazebo,
spawn_entity,
joint_state_broadcaster_node,
robot_joint_controller_node,
])

View File

@ -0,0 +1,59 @@
import os
from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import IncludeLaunchDescription, RegisterEventHandler
from launch.launch_description_sources import PythonLaunchDescriptionSource
from launch_ros.actions import Node
from launch.event_handlers import OnProcessExit
import xacro
def generate_launch_description():
package_name = 'a1_description'
package_path = os.path.join(get_package_share_directory(package_name))
xacro_file = os.path.join(package_path, 'xacro', 'robot.xacro')
robot_description = xacro.process_file(xacro_file).toxml()
robot_state_publisher_node = Node(
package="robot_state_publisher",
executable="robot_state_publisher",
name='robot_state_publisher',
output="screen",
parameters=[{"robot_description": robot_description}],
)
gazebo = IncludeLaunchDescription(
PythonLaunchDescriptionSource(
os.path.join(get_package_share_directory('gazebo_ros'), 'launch', 'gazebo.launch.py')
),
launch_arguments={'verbose': 'true'}.items()
)
spawn_entity = Node(
package='gazebo_ros',
executable='spawn_entity.py',
arguments=['-topic', '/robot_description', '-entity', 'a1_gazebo'],
output='screen',
)
controller_names = [
"joint_state_broadcaster",
"FL_hip_controller", "FL_thigh_controller", "FL_calf_controller",
"FR_hip_controller", "FR_thigh_controller", "FR_calf_controller",
"RL_hip_controller", "RL_thigh_controller", "RL_calf_controller",
"RR_hip_controller", "RR_thigh_controller", "RR_calf_controller"
]
controller_nodes = [Node(
package="controller_manager",
executable="spawner.py",
arguments=[name],
output='screen',
) for name in controller_names]
return LaunchDescription([
robot_state_publisher_node,
gazebo,
spawn_entity,
*controller_nodes,
])

View File

@ -1,14 +1,22 @@
<?xml version="1.0"?>
<package format="2">
<name>a1_description</name>
<version>0.0.0</version>
<description>The a1_description package</description>
<package format="3">
<name>a1_description</name>
<version>2.0.0</version>
<description>TODO: Package description</description>
<maintainer email="fanziqi614@gmail.com">Ziqi Fan</maintainer>
<license>Apache-2.0</license>
<maintainer email="laikago@unitree.cc">unitree</maintainer>
<license>TODO</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<depend>std_msgs</depend>
<depend>urdf</depend>
<depend>xacro</depend>
<depend>robot_state_publisher</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<build_type>ament_cmake</build_type>
<gazebo_ros gazebo_model_path="${prefix}/.."/>
</export>
</package>

View File

@ -44,12 +44,20 @@
<color rgba="1.0 1.0 1.0 1.0"/>
</material>
<!-- ros_control plugin -->
<gazebo>
<!-- <gazebo>
<plugin filename="libgazebo_ros_control.so" name="gazebo_ros_control">
<robotNamespace>/a1_gazebo</robotNamespace>
<robotSimType>gazebo_ros_control/DefaultRobotHWSim</robotSimType>
</plugin>
</gazebo>
</gazebo> -->
<gazebo>
<plugin name="gazebo_ros2_control" filename="libgazebo_ros2_control.so">
<robot_sim_type>gazebo_ros2_control/GazeboSystem</robot_sim_type>
<robot_param>robot_description</robot_param>
<robot_param_node>robot_state_publisher_node</robot_param_node>
<parameters>$(find a1_description)/config/robot_control.yaml</parameters>
</plugin>
</gazebo>
<!-- Show the trajectory of trunk center. -->
<gazebo>
<plugin filename="libLinkPlot3DPlugin.so" name="3dplotTrunk">

View File

@ -1,15 +1,7 @@
<?xml version="1.0"?>
<robot>
<!-- ros_control plugin -->
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
<robotNamespace>/a1_gazebo</robotNamespace>
<robotSimType>gazebo_ros_control/DefaultRobotHWSim</robotSimType>
</plugin>
</gazebo>
<!-- Show the trajectory of trunk center. -->
<gazebo>
<!-- <gazebo>
<plugin name="3dplot" filename="libLinkPlot3DPlugin.so">
<frequency>10</frequency>
<plot>
@ -18,7 +10,7 @@
<material>Gazebo/Yellow</material>
</plot>
</plugin>
</gazebo>
</gazebo> -->
<!-- Show the trajectory of foot. You can add another trajectory about another foot. -->
<!-- <gazebo>
@ -32,31 +24,80 @@
</plugin>
</gazebo> -->
<gazebo>
<!-- <gazebo>
<plugin filename="libgazebo_ros_force.so" name="gazebo_ros_force">
<bodyName>trunk</bodyName>
<topicName>/apply_force/trunk</topicName>
</plugin>
</gazebo>
</gazebo> -->
<gazebo reference="imu_link">
<gravity>true</gravity>
<sensor name="imu_sensor" type="imu">
<always_on>true</always_on>
<update_rate>1000</update_rate>
<visualize>true</visualize>
<topic>__default_topic__</topic>
<plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
<topicName>trunk_imu</topicName>
<bodyName>imu_link</bodyName>
<updateRateHZ>1000.0</updateRateHZ>
<gaussianNoise>0.0</gaussianNoise>
<xyzOffset>0 0 0</xyzOffset>
<rpyOffset>0 0 0</rpyOffset>
<frameName>imu_link</frameName>
</plugin>
<pose>0 0 0 0 0 0</pose>
</sensor>
<sensor name="imu_sensor" type="imu">
<plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
<ros>
<namespace>/</namespace>
<remapping>~/out:=imu</remapping>
</ros>
<initial_orientation_as_reference>false</initial_orientation_as_reference>
</plugin>
<always_on>true</always_on>
<update_rate>100</update_rate>
<visualize>true</visualize>
<imu>
<angular_velocity>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</z>
</angular_velocity>
<linear_acceleration>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</z>
</linear_acceleration>
</imu>
</sensor>
</gazebo>
<!-- Foot contacts. -->

9
src/robots/a1_description/xacro/robot.xacro Normal file → Executable file
View File

@ -9,6 +9,7 @@
<xacro:include filename="$(find a1_description)/xacro/leg.xacro"/>
<xacro:include filename="$(find a1_description)/xacro/stairs.xacro"/>
<xacro:include filename="$(find a1_description)/xacro/gazebo.xacro"/>
<xacro:include filename="$(find a1_description)/xacro/ros2_control.xacro"/>
<!-- <xacro:include filename="$(find a1_gazebo)/launch/stairs.urdf.xacro"/> -->
<!-- <xacro:stairs stairs="15" xpos="0" ypos="0" zpos="0" /> -->
@ -24,7 +25,7 @@
<parent link="world"/>
<child link="base"/>
</joint>
</xacro:if>
</xacro:if>
<link name="base">
<visual>
@ -61,7 +62,7 @@
<inertia
ixx="${trunk_ixx}" ixy="${trunk_ixy}" ixz="${trunk_ixz}"
iyy="${trunk_iyy}" iyz="${trunk_iyz}"
izz="${trunk_izz}"/>
izz="${trunk_izz}"/>
</inertial>
</link>
@ -91,10 +92,10 @@
<inertia
ixx="${stick_mass / 2.0 * (stick_radius*stick_radius)}" ixy="0.0" ixz="0.0"
iyy="${stick_mass / 12.0 * (3*stick_radius*stick_radius + stick_length*stick_length)}" iyz="0.0"
izz="${stick_mass / 12.0 * (3*stick_radius*stick_radius + stick_length*stick_length)}"/>
izz="${stick_mass / 12.0 * (3*stick_radius*stick_radius + stick_length*stick_length)}"/>
</inertial>
</link>
</xacro:if>
</xacro:if>
<joint name="imu_joint" type="fixed">
<parent link="trunk"/>

View File

@ -0,0 +1,137 @@
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
<ros2_control name="GazeboSystem" type="system">
<hardware>
<plugin>gazebo_ros2_control/GazeboSystem</plugin>
</hardware>
<joint name="FR_hip_joint">
<command_interface name="effort">
<param name="min">-${hip_torque_max}</param>
<param name="max">${hip_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FL_hip_joint">
<command_interface name="effort">
<param name="min">-${hip_torque_max}</param>
<param name="max">${hip_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RR_hip_joint">
<command_interface name="effort">
<param name="min">-${hip_torque_max}</param>
<param name="max">${hip_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RL_hip_joint">
<command_interface name="effort">
<param name="min">-${hip_torque_max}</param>
<param name="max">${hip_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FR_thigh_joint">
<command_interface name="effort">
<param name="min">-${thigh_torque_max}</param>
<param name="max">${thigh_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FL_thigh_joint">
<command_interface name="effort">
<param name="min">-${thigh_torque_max}</param>
<param name="max">${thigh_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RR_thigh_joint">
<command_interface name="effort">
<param name="min">-${thigh_torque_max}</param>
<param name="max">${thigh_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RL_thigh_joint">
<command_interface name="effort">
<param name="min">-${thigh_torque_max}</param>
<param name="max">${thigh_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FR_calf_joint">
<command_interface name="effort">
<param name="min">-${calf_torque_max}</param>
<param name="max">${calf_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FL_calf_joint">
<command_interface name="effort">
<param name="min">-${calf_torque_max}</param>
<param name="max">${calf_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RR_calf_joint">
<command_interface name="effort">
<param name="min">-${calf_torque_max}</param>
<param name="max">${calf_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RL_calf_joint">
<command_interface name="effort">
<param name="min">-${calf_torque_max}</param>
<param name="max">${calf_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
</ros2_control>
<gazebo>
<plugin name="gazebo_ros2_control" filename="libgazebo_ros2_control.so">
<parameters>$(find a1_description)/config/robot_control_group.yaml</parameters>
</plugin>
</gazebo>
</robot>

View File

@ -1,14 +1,22 @@
cmake_minimum_required(VERSION 2.8.3)
cmake_minimum_required(VERSION 3.8)
project(go2_description)
find_package(catkin REQUIRED)
find_package(ament_cmake REQUIRED)
find_package(ament_lint_auto REQUIRED)
find_package(urdf REQUIRED)
find_package(xacro REQUIRED)
find_package(robot_state_publisher REQUIRED)
catkin_package()
install(
DIRECTORY
config
launch
meshes
urdf
xacro
find_package(roslaunch)
DESTINATION
share/${PROJECT_NAME}/
)
foreach(dir config launch meshes urdf)
install(DIRECTORY ${dir}/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/${dir})
endforeach(dir)
ament_package()

109
src/robots/go2_description/config/robot_control.yaml Executable file → Normal file
View File

@ -1,70 +1,113 @@
go2_gazebo:
# Publish all joint states -----------------------------------
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 1000
controller_manager:
ros__parameters:
update_rate: 1000 # Hz
# use_sim_time: true # If running in simulation
# FL Controllers ---------------------------------------
FL_hip_controller:
type: robot_joint_controller/RobotJointController
joint_state_broadcaster:
type: joint_state_broadcaster/JointStateBroadcaster
imu_sensor_broadcaster:
type: imu_sensor_broadcaster/ImuSensorBroadcaster
# FL Controllers ---------------------------------------
FL_hip_controller:
type: robot_joint_controller/RobotJointController
FL_thigh_controller:
type: robot_joint_controller/RobotJointController
FL_calf_controller:
type: robot_joint_controller/RobotJointController
# FR Controllers ---------------------------------------
FR_hip_controller:
type: robot_joint_controller/RobotJointController
FR_thigh_controller:
type: robot_joint_controller/RobotJointController
FR_calf_controller:
type: robot_joint_controller/RobotJointController
# RL Controllers ---------------------------------------
RL_hip_controller:
type: robot_joint_controller/RobotJointController
RL_thigh_controller:
type: robot_joint_controller/RobotJointController
RL_calf_controller:
type: robot_joint_controller/RobotJointController
# RR Controllers ---------------------------------------
RR_hip_controller:
type: robot_joint_controller/RobotJointController
RR_thigh_controller:
type: robot_joint_controller/RobotJointController
RR_calf_controller:
type: robot_joint_controller/RobotJointController
# FL Controllers ---------------------------------------
FL_hip_controller:
ros__parameters:
joint: FL_hip_joint
pid: {p: 100.0, i: 0.0, d: 5.0}
FL_thigh_controller:
type: robot_joint_controller/RobotJointController
FL_thigh_controller:
ros__parameters:
joint: FL_thigh_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
FL_calf_controller:
type: robot_joint_controller/RobotJointController
FL_calf_controller:
ros__parameters:
joint: FL_calf_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
# FR Controllers ---------------------------------------
FR_hip_controller:
type: robot_joint_controller/RobotJointController
# FR Controllers ---------------------------------------
FR_hip_controller:
ros__parameters:
joint: FR_hip_joint
pid: {p: 100.0, i: 0.0, d: 5.0}
FR_thigh_controller:
type: robot_joint_controller/RobotJointController
FR_thigh_controller:
ros__parameters:
joint: FR_thigh_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
FR_calf_controller:
type: robot_joint_controller/RobotJointController
FR_calf_controller:
ros__parameters:
joint: FR_calf_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
# RL Controllers ---------------------------------------
RL_hip_controller:
type: robot_joint_controller/RobotJointController
# RL Controllers ---------------------------------------
RL_hip_controller:
ros__parameters:
joint: RL_hip_joint
pid: {p: 100.0, i: 0.0, d: 5.0}
RL_thigh_controller:
type: robot_joint_controller/RobotJointController
RL_thigh_controller:
ros__parameters:
joint: RL_thigh_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
RL_calf_controller:
type: robot_joint_controller/RobotJointController
RL_calf_controller:
ros__parameters:
joint: RL_calf_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
# RR Controllers ---------------------------------------
RR_hip_controller:
type: robot_joint_controller/RobotJointController
# RR Controllers ---------------------------------------
RR_hip_controller:
ros__parameters:
joint: RR_hip_joint
pid: {p: 100.0, i: 0.0, d: 5.0}
RR_thigh_controller:
type: robot_joint_controller/RobotJointController
RR_thigh_controller:
ros__parameters:
joint: RR_thigh_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
RR_calf_controller:
type: robot_joint_controller/RobotJointController
RR_calf_controller:
ros__parameters:
joint: RR_calf_joint
pid: {p: 300.0, i: 0.0, d: 8.0}
imu_sensor_broadcaster:
ros__parameters:
sensor_name: "imu_sensor"
frame_id: imu_link

View File

@ -1,21 +1,22 @@
<package format="2">
<?xml version="1.0"?>
<package format="3">
<name>go2_description</name>
<version>1.0.0</version>
<description>
<p>URDF Description package for go2_description</p>
<p>This package contains configuration data, 3D models and launch files
for go2_description robot</p>
</description>
<author>TODO</author>
<maintainer email="TODO@email.com" />
<license>BSD</license>
<buildtool_depend>catkin</buildtool_depend>
<depend>roslaunch</depend>
<version>2.0.0</version>
<description>TODO: Package description</description>
<maintainer email="fanziqi614@gmail.com">Ziqi Fan</maintainer>
<license>Apache-2.0</license>
<buildtool_depend>ament_cmake</buildtool_depend>
<depend>urdf</depend>
<depend>xacro</depend>
<depend>robot_state_publisher</depend>
<depend>rviz</depend>
<depend>joint_state_publisher_gui</depend>
<depend>gazebo</depend>
<test_depend>ament_lint_auto</test_depend>
<test_depend>ament_lint_common</test_depend>
<export>
<architecture_independent />
<build_type>ament_cmake</build_type>
<gazebo_ros gazebo_model_path="${prefix}/.."/>
</export>
</package>
</package>

View File

@ -1,13 +1,5 @@
<?xml version="1.0"?>
<robot>
<!-- ros_control plugin -->
<gazebo>
<plugin name="gazebo_ros_control" filename="libgazebo_ros_control.so">
<robotNamespace>/go2_gazebo</robotNamespace>
<robotSimType>gazebo_ros_control/DefaultRobotHWSim</robotSimType>
</plugin>
</gazebo>
<!-- Show the trajectory of trunk center. -->
<!--gazebo>
<plugin name="3dplot" filename="libLinkPlot3DPlugin.so">
@ -21,7 +13,7 @@
</gazebo-->
<!-- Show the trajectory of foot. You can add another trajectory about another foot. -->
<gazebo>
<!-- <gazebo>
<plugin name="3dplot" filename="libLinkPlot3DPlugin.so">
<frequency>100</frequency>
<plot>
@ -29,43 +21,86 @@
<pose>0 0 0 0 0 0</pose>
</plot>
</plugin>
</gazebo>
</gazebo> -->
<gazebo>
<!-- <gazebo>
<plugin filename="libgazebo_ros_force.so" name="gazebo_ros_force">
<bodyName>trunk</bodyName>
<topicName>/apply_force/trunk</topicName>
</plugin>
</gazebo>
</gazebo> -->
<gazebo reference="imu_link">
<gravity>true</gravity>
<sensor name="imu_sensor" type="imu">
<always_on>true</always_on>
<update_rate>1000</update_rate>
<visualize>true</visualize>
<topic>__default_topic__</topic>
<plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
<topicName>trunk_imu</topicName>
<bodyName>imu_link</bodyName>
<updateRateHZ>1000.0</updateRateHZ>
<gaussianNoise>0.0</gaussianNoise>
<xyzOffset>0 0 0</xyzOffset>
<rpyOffset>0 0 0</rpyOffset>
<frameName>imu_link</frameName>
</plugin>
<pose>0 0 0 0 0 0</pose>
</sensor>
<sensor name="imu_sensor" type="imu">
<plugin filename="libgazebo_ros_imu_sensor.so" name="imu_plugin">
<ros>
<namespace>/</namespace>
<remapping>~/out:=imu</remapping>
</ros>
<initial_orientation_as_reference>false</initial_orientation_as_reference>
</plugin>
<always_on>true</always_on>
<update_rate>100</update_rate>
<visualize>true</visualize>
<imu>
<angular_velocity>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>2e-4</stddev>
<bias_mean>0.0000075</bias_mean>
<bias_stddev>0.0000008</bias_stddev>
</noise>
</z>
</angular_velocity>
<linear_acceleration>
<x>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</x>
<y>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</y>
<z>
<noise type="gaussian">
<mean>0.0</mean>
<stddev>1.7e-2</stddev>
<bias_mean>0.1</bias_mean>
<bias_stddev>0.001</bias_stddev>
</noise>
</z>
</linear_acceleration>
</imu>
</sensor>
</gazebo>
<!-- Foot contacts. -->
<gazebo reference="FR_calf">
<!-- <gazebo reference="FR_calf">
<sensor name="FR_foot_contact" type="contact">
<update_rate>100</update_rate>
<plugin name="contactPlugin" filename="libunitreeFootContactPlugin.so"/>
@ -100,10 +135,10 @@
<collision>RL_calf_fixed_joint_lump__RL_foot_collision_1</collision>
</contact>
</sensor>
</gazebo>
</gazebo> -->
<!-- Visualization of Foot contacts. -->
<gazebo reference="FR_foot">
<!-- <gazebo reference="FR_foot">
<visual>
<plugin name="drawForcePlugin" filename="libunitreeDrawForcePlugin.so">
<topicName>FR_foot_contact</topicName>
@ -130,7 +165,7 @@
<topicName>RL_foot_contact</topicName>
</plugin>
</visual>
</gazebo>
</gazebo> -->
<gazebo reference="base">
<turnGravityOff>false</turnGravityOff>

View File

@ -9,6 +9,7 @@
<xacro:include filename="$(find go2_description)/xacro/leg.xacro"/>
<!-- <xacro:include filename="$(find go2_description)/xacro/stairs.xacro"/> -->
<xacro:include filename="$(find go2_description)/xacro/gazebo.xacro"/>
<xacro:include filename="$(find a1_description)/xacro/ros2_control.xacro"/>
<!-- <xacro:include filename="$(find go2_gazebo)/launch/stairs.urdf.xacro"/> -->
<!-- <xacro:stairs stairs="15" xpos="0" ypos="0" zpos="0" /> -->
@ -24,7 +25,7 @@
<parent link="world"/>
<child link="base"/>
</joint>
</xacro:if>
</xacro:if>
<link name="base">
<visual>
@ -61,7 +62,7 @@
<inertia
ixx="${trunk_ixx}" ixy="${trunk_ixy}" ixz="${trunk_ixz}"
iyy="${trunk_iyy}" iyz="${trunk_iyz}"
izz="${trunk_izz}"/>
izz="${trunk_izz}"/>
</inertial>
</link>

View File

@ -0,0 +1,137 @@
<?xml version="1.0"?>
<robot xmlns:xacro="http://www.ros.org/wiki/xacro">
<ros2_control name="GazeboSystem" type="system">
<hardware>
<plugin>gazebo_ros2_control/GazeboSystem</plugin>
</hardware>
<joint name="FR_hip_joint">
<command_interface name="effort">
<param name="min">-${hip_torque_max}</param>
<param name="max">${hip_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FL_hip_joint">
<command_interface name="effort">
<param name="min">-${hip_torque_max}</param>
<param name="max">${hip_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RR_hip_joint">
<command_interface name="effort">
<param name="min">-${hip_torque_max}</param>
<param name="max">${hip_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RL_hip_joint">
<command_interface name="effort">
<param name="min">-${hip_torque_max}</param>
<param name="max">${hip_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FR_thigh_joint">
<command_interface name="effort">
<param name="min">-${thigh_torque_max}</param>
<param name="max">${thigh_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FL_thigh_joint">
<command_interface name="effort">
<param name="min">-${thigh_torque_max}</param>
<param name="max">${thigh_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RR_thigh_joint">
<command_interface name="effort">
<param name="min">-${thigh_torque_max}</param>
<param name="max">${thigh_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RL_thigh_joint">
<command_interface name="effort">
<param name="min">-${thigh_torque_max}</param>
<param name="max">${thigh_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FR_calf_joint">
<command_interface name="effort">
<param name="min">-${calf_torque_max}</param>
<param name="max">${calf_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="FL_calf_joint">
<command_interface name="effort">
<param name="min">-${calf_torque_max}</param>
<param name="max">${calf_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RR_calf_joint">
<command_interface name="effort">
<param name="min">-${calf_torque_max}</param>
<param name="max">${calf_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
<joint name="RL_calf_joint">
<command_interface name="effort">
<param name="min">-${calf_torque_max}</param>
<param name="max">${calf_torque_max}</param>
</command_interface>
<state_interface name="position"/>
<state_interface name="velocity"/>
<state_interface name="effort"/>
</joint>
</ros2_control>
<gazebo>
<plugin name="gazebo_ros2_control" filename="libgazebo_ros2_control.so">
<parameters>$(find go2_description)/config/robot_control_group.yaml</parameters>
</plugin>
</gazebo>
</robot>

View File

@ -1,14 +0,0 @@
cmake_minimum_required(VERSION 3.0)
project(gr1t1_description)
find_package(catkin REQUIRED)
catkin_package()
find_package(roslaunch)
foreach(dir config launch meshes urdf)
install(DIRECTORY ${dir}/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/${dir})
endforeach(dir)

View File

@ -1,57 +0,0 @@
gr1t1_gazebo:
# Publish all joint states -----------------------------------
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 1000
# left leg Controllers ---------------------------------------
l_hip_roll_controller:
type: robot_joint_controller/RobotJointController
joint: l_hip_roll
pid: {p: 57.0, i: 0.0, d: 5.7}
l_hip_yaw_controller:
type: robot_joint_controller/RobotJointController
joint: l_hip_yaw
pid: {p: 43.0, i: 0.0, d: 4.3}
l_hip_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: l_hip_pitch
pid: {p: 114.0, i: 0.0, d: 11.4}
l_knee_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: l_knee_pitch
pid: {p: 114.0, i: 0.0, d: 11.4}
l_ankle_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: l_ankle_pitch
pid: {p: 15.3, i: 0.0, d: 1.5}
# right leg Controllers ---------------------------------------
r_hip_roll_controller:
type: robot_joint_controller/RobotJointController
joint: r_hip_roll
pid: {p: 57.0, i: 0.0, d: 5.7}
r_hip_yaw_controller:
type: robot_joint_controller/RobotJointController
joint: r_hip_yaw
pid: {p: 43.0, i: 0.0, d: 4.3}
r_hip_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: r_hip_pitch
pid: {p: 114.0, i: 0.0, d: 11.4}
r_knee_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: r_knee_pitch
pid: {p: 114.0, i: 0.0, d: 11.4}
r_ankle_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: r_ankle_pitch
pid: {p: 15.3, i: 0.0, d: 1.5}

View File

@ -1,20 +0,0 @@
<launch>
<arg
name="model" />
<param
name="robot_description"
textfile="$(find gr1t1_description)/urdf/GR1T1_lower_limb.urdf" />
<node
name="joint_state_publisher_gui"
pkg="joint_state_publisher_gui"
type="joint_state_publisher_gui" />
<node
name="robot_state_publisher"
pkg="robot_state_publisher"
type="robot_state_publisher" />
<node
name="rviz"
pkg="rviz"
type="rviz"
args="-d $(find gr1t1_description)/urdf.rviz" />
</launch>

View File

@ -1,20 +0,0 @@
<launch>
<include
file="$(find gazebo_ros)/launch/empty_world.launch" />
<node
name="tf_footprint_base"
pkg="tf"
type="static_transform_publisher"
args="0 0 0 0 0 0 base_link base_footprint 40" />
<node
name="spawn_model"
pkg="gazebo_ros"
type="spawn_model"
args="-file $(find gr1t1_description)/urdf/GR1T1_lower_limb.urdf -urdf -model gr1t1_description"
output="screen" />
<node
name="fake_joint_calibration"
pkg="rostopic"
type="rostopic"
args="pub /calibrated std_msgs/Bool true" />
</launch>

View File

@ -1,20 +0,0 @@
<package format="2">
<name>gr1t1_description</name>
<version>1.0.0</version>
<description>
<p>URDF Description package for gr1t1_description</p>
<p>This package contains configuration data, 3D models and launch files for fldlar_description robot</p>
</description>
<author>Ziqi Fan</author>
<maintainer email="fanziqi614@gmail.com" />
<license>Apache</license>
<buildtool_depend>catkin</buildtool_depend>
<depend>roslaunch</depend>
<depend>robot_state_publisher</depend>
<depend>rviz</depend>
<depend>joint_state_publisher_gui</depend>
<depend>gazebo</depend>
<export>
<architecture_independent />
</export>
</package>

View File

@ -1,225 +0,0 @@
Panels:
- Class: rviz/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Status1
Splitter Ratio: 0.5
Tree Height: 549
- Class: rviz/Selection
Name: Selection
- Class: rviz/Tool Properties
Expanded:
- /2D Pose Estimate1
- /2D Nav Goal1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Name: Time
SyncMode: 0
SyncSource: ""
Preferences:
PromptSaveOnExit: true
Toolbars:
toolButtonStyle: 2
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
Line Width: 0.029999999329447746
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 10
Reference Frame: <Fixed Frame>
Value: true
- Alpha: 1
Class: rviz/RobotModel
Collision Enabled: false
Enabled: true
Links:
10:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
11:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
12:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
13:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
20:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
21:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
22:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
23:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
30:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
31:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
32:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
33:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
40:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
41:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
42:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
43:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
All Links Enabled: true
Expand Joint Details: false
Expand Link Details: false
Expand Tree: false
Link Tree Style: Links in Alphabetic Order
base:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
base_link:
Alpha: 1
Show Axes: false
Show Trail: false
Value: true
Name: RobotModel
Robot Description: robot_description
TF Prefix: ""
Update Interval: 0
Value: true
Visual Enabled: true
Enabled: true
Global Options:
Background Color: 48; 48; 48
Default Light: true
Fixed Frame: base
Frame Rate: 30
Name: root
Tools:
- Class: rviz/Interact
Hide Inactive Objects: true
- Class: rviz/MoveCamera
- Class: rviz/Select
- Class: rviz/FocusCamera
- Class: rviz/Measure
- Class: rviz/SetInitialPose
Theta std deviation: 0.2617993950843811
Topic: /initialpose
X std deviation: 0.5
Y std deviation: 0.5
- Class: rviz/SetGoal
Topic: /move_base_simple/goal
- Class: rviz/PublishPoint
Single click: true
Topic: /clicked_point
Value: true
Views:
Current:
Class: rviz/Orbit
Distance: 2.634476661682129
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Field of View: 0.7853981852531433
Focal Point:
X: 0.0988716408610344
Y: 0.08353396505117416
Z: -0.19447802007198334
Focal Shape Fixed Size: true
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
Pitch: 0.5753985047340393
Target Frame: <Fixed Frame>
Yaw: 0.47539806365966797
Saved: ~
Window Geometry:
Displays:
collapsed: false
Height: 846
Hide Left Dock: false
Hide Right Dock: false
QMainWindow State: 000000ff00000000fd000000040000000000000156000002b0fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d000002b0000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002b0fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d000002b0000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004b00000003efc0100000002fb0000000800540069006d00650100000000000004b0000003bc00fffffffb0000000800540069006d006501000000000000045000000000000000000000023f000002b000000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Time:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: false
Width: 1200
X: 278
Y: 96

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
cmake_minimum_required(VERSION 3.0)
project(gr1t2_description)
find_package(catkin REQUIRED)
catkin_package()
find_package(roslaunch)
foreach(dir config launch meshes urdf)
install(DIRECTORY ${dir}/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/${dir})
endforeach(dir)

View File

@ -1,57 +0,0 @@
gr1t2_gazebo:
# Publish all joint states -----------------------------------
joint_state_controller:
type: joint_state_controller/JointStateController
publish_rate: 1000
# left leg Controllers ---------------------------------------
l_hip_roll_controller:
type: robot_joint_controller/RobotJointController
joint: l_hip_roll
pid: {p: 57.0, i: 0.0, d: 5.7}
l_hip_yaw_controller:
type: robot_joint_controller/RobotJointController
joint: l_hip_yaw
pid: {p: 43.0, i: 0.0, d: 4.3}
l_hip_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: l_hip_pitch
pid: {p: 114.0, i: 0.0, d: 11.4}
l_knee_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: l_knee_pitch
pid: {p: 114.0, i: 0.0, d: 11.4}
l_ankle_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: l_ankle_pitch
pid: {p: 15.3, i: 0.0, d: 1.5}
# right leg Controllers ---------------------------------------
r_hip_roll_controller:
type: robot_joint_controller/RobotJointController
joint: r_hip_roll
pid: {p: 57.0, i: 0.0, d: 5.7}
r_hip_yaw_controller:
type: robot_joint_controller/RobotJointController
joint: r_hip_yaw
pid: {p: 43.0, i: 0.0, d: 4.3}
r_hip_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: r_hip_pitch
pid: {p: 114.0, i: 0.0, d: 11.4}
r_knee_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: r_knee_pitch
pid: {p: 114.0, i: 0.0, d: 11.4}
r_ankle_pitch_controller:
type: robot_joint_controller/RobotJointController
joint: r_ankle_pitch
pid: {p: 15.3, i: 0.0, d: 1.5}

View File

@ -1,20 +0,0 @@
<launch>
<arg
name="model" />
<param
name="robot_description"
textfile="$(find gr1t2_description)/urdf/GR1T2_simple.urdf" />
<node
name="joint_state_publisher_gui"
pkg="joint_state_publisher_gui"
type="joint_state_publisher_gui" />
<node
name="robot_state_publisher"
pkg="robot_state_publisher"
type="robot_state_publisher" />
<node
name="rviz"
pkg="rviz"
type="rviz"
args="-d $(find gr1t2_description)/urdf.rviz" />
</launch>

View File

@ -1,20 +0,0 @@
<launch>
<include
file="$(find gazebo_ros)/launch/empty_world.launch" />
<node
name="tf_footprint_base"
pkg="tf"
type="static_transform_publisher"
args="0 0 0 0 0 0 base_link base_footprint 40" />
<node
name="spawn_model"
pkg="gazebo_ros"
type="spawn_model"
args="-file $(find gr1t2_description)/urdf/GR1T2_simple.urdf -urdf -model gr1t2_description"
output="screen" />
<node
name="fake_joint_calibration"
pkg="rostopic"
type="rostopic"
args="pub /calibrated std_msgs/Bool true" />
</launch>

Some files were not shown because too many files have changed in this diff Show More