From 8744d0b4f9a5344572b9a44827e8d50017066b47 Mon Sep 17 00:00:00 2001 From: Michitoshi Tsubaki Date: Fri, 17 Apr 2026 18:52:52 +0900 Subject: [PATCH 01/10] Support Euslisp model for Unitree G1 Humanoid --- jsk_g1_robot/g1eus/.gitignore | 2 + jsk_g1_robot/g1eus/CMakeLists.txt | 52 ++++++++++++++++++++ jsk_g1_robot/g1eus/README.md | 17 +++++++ jsk_g1_robot/g1eus/config/g1.yaml | 57 ++++++++++++++++++++++ jsk_g1_robot/g1eus/euslisp/g1-interface.l | 16 ++++++ jsk_g1_robot/g1eus/figs/g1eus.png | Bin 0 -> 35768 bytes jsk_g1_robot/g1eus/package.xml | 12 +++++ jsk_g1_robot/g1eus/ros-o.repos.yaml | 9 ++++ 8 files changed, 165 insertions(+) create mode 100644 jsk_g1_robot/g1eus/.gitignore create mode 100644 jsk_g1_robot/g1eus/CMakeLists.txt create mode 100644 jsk_g1_robot/g1eus/README.md create mode 100644 jsk_g1_robot/g1eus/config/g1.yaml create mode 100644 jsk_g1_robot/g1eus/euslisp/g1-interface.l create mode 100644 jsk_g1_robot/g1eus/figs/g1eus.png create mode 100644 jsk_g1_robot/g1eus/package.xml create mode 100644 jsk_g1_robot/g1eus/ros-o.repos.yaml diff --git a/jsk_g1_robot/g1eus/.gitignore b/jsk_g1_robot/g1eus/.gitignore new file mode 100644 index 0000000000..018fcba334 --- /dev/null +++ b/jsk_g1_robot/g1eus/.gitignore @@ -0,0 +1,2 @@ +euslisp/g1.l +models/g1.urdf \ No newline at end of file diff --git a/jsk_g1_robot/g1eus/CMakeLists.txt b/jsk_g1_robot/g1eus/CMakeLists.txt new file mode 100644 index 0000000000..8b898045f1 --- /dev/null +++ b/jsk_g1_robot/g1eus/CMakeLists.txt @@ -0,0 +1,52 @@ +cmake_minimum_required(VERSION 3.0.2) +project(g1eus) + +find_package(catkin REQUIRED COMPONENTS + euscollada + pr2eus + unitree_controller +) + +catkin_package( + CATKIN_DEPENDS euscollada pr2eus unitree_controller +) + +set(G1_DESCRIPTION_DIR ${unitree_controller_SOURCE_PREFIX}/../robots/g1_description) +set(G1_SOURCE_URDF ${G1_DESCRIPTION_DIR}/g1_29dof.urdf) +set(G1_GENERATED_URDF ${PROJECT_SOURCE_DIR}/models/g1.urdf) +set(G1_EUSLISP ${PROJECT_SOURCE_DIR}/euslisp/g1.l) + +if(NOT EXISTS ${G1_SOURCE_URDF}) + message(FATAL_ERROR "Could not find G1 URDF at ${G1_SOURCE_URDF}") +endif() + +file(READ ${G1_SOURCE_URDF} G1_URDF_CONTENT) +string(REPLACE + "filename=\"meshes/" + "filename=\"package://unitree_controller/../robots/g1_description/meshes/" + G1_URDF_CONTENT + "${G1_URDF_CONTENT}") +string(REPLACE + "" + "" + G1_URDF_CONTENT + "${G1_URDF_CONTENT}") +file(WRITE ${G1_GENERATED_URDF} "${G1_URDF_CONTENT}") + +add_custom_command( + OUTPUT ${G1_EUSLISP} + COMMAND rosrun euscollada collada2eus -I ${G1_GENERATED_URDF} -N g1 -C ${PROJECT_SOURCE_DIR}/config/g1.yaml -O ${G1_EUSLISP} + DEPENDS ${G1_GENERATED_URDF} ${PROJECT_SOURCE_DIR}/config/g1.yaml + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} + COMMENT "Generating G1 EusLisp model" +) + +add_custom_target(generate_g1_eus_model ALL DEPENDS ${G1_EUSLISP}) + +install(DIRECTORY config euslisp models + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} + USE_SOURCE_PERMISSIONS) + +install(FILES ${G1_GENERATED_URDF} ${G1_EUSLISP} + DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} + OPTIONAL) diff --git a/jsk_g1_robot/g1eus/README.md b/jsk_g1_robot/g1eus/README.md new file mode 100644 index 0000000000..59ff9d8b1c --- /dev/null +++ b/jsk_g1_robot/g1eus/README.md @@ -0,0 +1,17 @@ +# g1eus +![g1eus](./figs/g1eus.png) +## Setup + +Please install ROS 1 and some development tools like rosdep, vcstools at first. + +Then build the packages. + +```shell +source /opt/ros//setup.bash +mkdir -p /src +cd /src +wget https://raw.githubusercontent.com/jsk-ros-pkg/jsk_robot/refs/heads/master/jsk_g1_robot/g1eus/ros-o.repos.yaml -O- | vcs import +sudo apt update && rosdep update && rosdep install -iqry --from-paths . +cd .. +catkin build g1eus +``` diff --git a/jsk_g1_robot/g1eus/config/g1.yaml b/jsk_g1_robot/g1eus/config/g1.yaml new file mode 100644 index 0000000000..350f299cde --- /dev/null +++ b/jsk_g1_robot/g1eus/config/g1.yaml @@ -0,0 +1,57 @@ +torso: + - waist_yaw_joint : torso-waist-y + - waist_roll_joint : torso-waist-r + - waist_pitch_joint : torso-waist-p + +lleg: + - left_hip_pitch_joint : lleg-hip-p + - left_hip_roll_joint : lleg-hip-r + - left_hip_yaw_joint : lleg-hip-y + - left_knee_joint : lleg-knee-p + - left_ankle_pitch_joint : lleg-ankle-p + - left_ankle_roll_joint : lleg-ankle-r + +rleg: + - right_hip_pitch_joint : rleg-hip-p + - right_hip_roll_joint : rleg-hip-r + - right_hip_yaw_joint : rleg-hip-y + - right_knee_joint : rleg-knee-p + - right_ankle_pitch_joint : rleg-ankle-p + - right_ankle_roll_joint : rleg-ankle-r + +larm: + - left_shoulder_pitch_joint : larm-shoulder-p + - left_shoulder_roll_joint : larm-shoulder-r + - left_shoulder_yaw_joint : larm-shoulder-y + - left_elbow_joint : larm-elbow-p + - left_wrist_roll_joint : larm-wrist-r + - left_wrist_pitch_joint : larm-wrist-p + - left_wrist_yaw_joint : larm-wrist-y + +rarm: + - right_shoulder_pitch_joint : rarm-shoulder-p + - right_shoulder_roll_joint : rarm-shoulder-r + - right_shoulder_yaw_joint : rarm-shoulder-y + - right_elbow_joint : rarm-elbow-p + - right_wrist_roll_joint : rarm-wrist-r + - right_wrist_pitch_joint : rarm-wrist-p + - right_wrist_yaw_joint : rarm-wrist-y + +angle-vector: + reset-pose : [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + +larm-end-coords: + parent : left_wrist_yaw_link + translate : [0.1, 0.0, 0.0] + +rarm-end-coords: + parent : right_wrist_yaw_link + translate : [0.1, 0.0, 0.0] + +lleg-end-coords: + parent : left_ankle_roll_link + translate : [0.0, 0.0, 0.0] + +rleg-end-coords: + parent : right_ankle_roll_link + translate : [0.0, 0.0, 0.0] diff --git a/jsk_g1_robot/g1eus/euslisp/g1-interface.l b/jsk_g1_robot/g1eus/euslisp/g1-interface.l new file mode 100644 index 0000000000..62978affd9 --- /dev/null +++ b/jsk_g1_robot/g1eus/euslisp/g1-interface.l @@ -0,0 +1,16 @@ +(load "package://pr2eus/robot-interface.l") +(require :g1 "package://g1eus/euslisp/g1.l") + +(defclass g1-interface + :super robot-interface + :slots ()) + +(defmethod g1-interface + (:init (&rest args) + (send-super :init :robot g1-robot))) + +(defun g1-init () + (unless (boundp '*ri*) + (setq *ri* (instance g1-interface :init))) + (unless (boundp '*g1*) + (setq *g1* (instance g1-robot :init)))) diff --git a/jsk_g1_robot/g1eus/figs/g1eus.png b/jsk_g1_robot/g1eus/figs/g1eus.png new file mode 100644 index 0000000000000000000000000000000000000000..f9899fc088379e5f33f30568c7398775b964b73a GIT binary patch literal 35768 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 + + g1eus + 0.0.0 + This package provides EusLisp interface for Unitree G1 Robot + leus + BSD + euscollada + pr2eus + unitree_controller + catkin + diff --git a/jsk_g1_robot/g1eus/ros-o.repos.yaml b/jsk_g1_robot/g1eus/ros-o.repos.yaml new file mode 100644 index 0000000000..404a0d4992 --- /dev/null +++ b/jsk_g1_robot/g1eus/ros-o.repos.yaml @@ -0,0 +1,9 @@ +repositories: + unitree/unitree_ros: + type: git + url: https://github.com/unitreerobotics/unitree_ros.git + version: master + unitree/unitree_ros_to_real: + type: git + url: https://github.com/unitreerobotics/unitree_ros_to_real.git + version: master From f2c51e2440142076193ff8c4676ab82e650627e4 Mon Sep 17 00:00:00 2001 From: Michitoshi Tsubaki Date: Sat, 18 Apr 2026 00:47:05 +0900 Subject: [PATCH 02/10] Change controller from fullbody to upperbody --- jsk_g1_robot/g1eus/euslisp/g1-interface.l | 35 ++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/jsk_g1_robot/g1eus/euslisp/g1-interface.l b/jsk_g1_robot/g1eus/euslisp/g1-interface.l index 62978affd9..a25742ae21 100644 --- a/jsk_g1_robot/g1eus/euslisp/g1-interface.l +++ b/jsk_g1_robot/g1eus/euslisp/g1-interface.l @@ -6,8 +6,41 @@ :slots ()) (defmethod g1-interface + (:upper-body-controller + () + (list + (list + (cons :controller-action "upper_body_controller/follow_joint_trajectory") + (cons :controller-state "upper_body_controller/state") + (cons :action-type control_msgs::FollowJointTrajectoryAction) + (cons :joint-names (list + "waist_yaw_joint" + "waist_roll_joint" + "waist_pitch_joint" + "left_shoulder_pitch_joint" + "left_shoulder_roll_joint" + "left_shoulder_yaw_joint" + "left_elbow_joint" + "left_wrist_roll_joint" + "left_wrist_pitch_joint" + "left_wrist_yaw_joint" + "right_shoulder_pitch_joint" + "right_shoulder_roll_joint" + "right_shoulder_yaw_joint" + "right_elbow_joint" + "right_wrist_roll_joint" + "right_wrist_pitch_joint" + "right_wrist_yaw_joint"))))) + + (:default-controller + () + (append + (send self :upper-body-controller) + ) + ) + (:init (&rest args) - (send-super :init :robot g1-robot))) + (send-super* :init :robot g1-robot args))) (defun g1-init () (unless (boundp '*ri*) From cb7e6add969884ea577ebe3de779d18ac6c9d249 Mon Sep 17 00:00:00 2001 From: Michitoshi Tsubaki <149882374+Michi-Tsubaki@users.noreply.github.com> Date: Sat, 18 Apr 2026 12:30:12 +0900 Subject: [PATCH 03/10] Update package.xml --- jsk_g1_robot/g1eus/package.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/jsk_g1_robot/g1eus/package.xml b/jsk_g1_robot/g1eus/package.xml index fa90081a19..beedfd9099 100644 --- a/jsk_g1_robot/g1eus/package.xml +++ b/jsk_g1_robot/g1eus/package.xml @@ -3,7 +3,8 @@ g1eus 0.0.0 This package provides EusLisp interface for Unitree G1 Robot - leus + Kei Okada + Michitoshi Tsubaki BSD euscollada pr2eus From d511e452bae183f47ab28872b3e81823b53152a8 Mon Sep 17 00:00:00 2001 From: Michitoshi Tsubaki Date: Fri, 15 May 2026 18:46:00 +0900 Subject: [PATCH 04/10] Update readme --- jsk_g1_robot/g1eus/README.md | 120 +++++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 4 deletions(-) diff --git a/jsk_g1_robot/g1eus/README.md b/jsk_g1_robot/g1eus/README.md index 59ff9d8b1c..3f2a1d45c5 100644 --- a/jsk_g1_robot/g1eus/README.md +++ b/jsk_g1_robot/g1eus/README.md @@ -1,17 +1,129 @@ # g1eus ![g1eus](./figs/g1eus.png) + ## Setup +### Clone this repository in your catkin workspace (ros1) +``` +mkdir -p /src +cd /src +git clone git@github.com:Michi-Tsubaki/jsk_robot.git -b support-eus-unitree-g1 +``` + + +### Build package Please install ROS 1 and some development tools like rosdep, vcstools at first. -Then build the packages. +Then build the packages by running the following commands. ```shell source /opt/ros//setup.bash -mkdir -p /src -cd /src -wget https://raw.githubusercontent.com/jsk-ros-pkg/jsk_robot/refs/heads/master/jsk_g1_robot/g1eus/ros-o.repos.yaml -O- | vcs import +cd /src +wget https://raw.githubusercontent.com/Michi-Tsubaki/jsk_robot/refs/heads/support-eus-unitree-g1/jsk_g1_robot/g1eus/ros-o.repos.yaml -O- | vcs import sudo apt update && rosdep update && rosdep install -iqry --from-paths . cd .. catkin build g1eus ``` + + +## How to use real robot + +### Build g1_ros (ROS2 package) + +```bash +source /opt/ros//setup.bash +mkdir -p /src +cd /src +wget https://raw.githubusercontent.com/mqcmd196/g1_ros/refs/heads/master/jazzy.repos.yaml -O- | vcs import +sudo apt update && rosdep update && rosdep install -iqry --from-paths . +cd .. +colcon build --symlink-install --packages-up-to g1_bringup +``` + +For more information, please visit [g1_ros](https://github.com/mqcmd196/g1_ros) + +### Install ros1_bridge +ros1_bridge is a ROS2 package. Please check [here](https://github.com/ros-o/ros1_bridge) + +The deb file for this package is shared at https://drive.google.com/file/d/1jXZlvovTGa_PU6stJOznvv5ZYkarB62n/view?usp=sharing + +Please download this deb file and install the package: + +```bash +cd ~/Downloads +sudo apt install ./ros-jazzy-ros1-bridge_0.10.3-0noble_amd64.deb +``` + + +### Preparation + +#### Connect Ethernet cable from g1 to your computer + +Please connect your computer to the robot following [official instruction](https://support.unitree.com/home/en/G1_developer/quick_development#heading-7). Please check the network interface name. + +Also please allocate the correct IP adress instructed [official instruction](https://support.unitree.com/home/en/G1_developer/quick_development#heading-7) manually. + + +### Execution + +- terminal 1 + +```bash +source /setup.bash +roscore +``` + +- terminal 2 (Bringup hands) + +```bash +ssh unitree@192.168.123.164 # default password is 123 +cd dfx_inspire_service/build/ +sudo ./inspire_g1 -k -u +``` + +- terminal 3 (Bringup robot as a ROS2 robot) + +```bash +source /setup.bash +ros2 launch g1_bringup g1_bringup.launch.py network_interface:=enp0s31f6 hand_type:=inspire_dfq +``` + +- terminal 4 (Activate ros2_control upper_body_controller) +```bash +source /setup.bash +ros2 control set_controller_state upper_body_controller active +``` + +- terminal 5 (Bridge ros2 topic and action to ros1 topic and actionlib) +```bash +source /setup.bash +source /setup.bash +ros2 run ros1_bridge dynamic_bridge --bridge-all-topics +``` + +- terminal 6 (Please run your own program using g1-interface.l) +```bash +cd euslisp +roseus +load "g1-interface.l" +``` + + +## Tips + +- Hand Interface + +```roseus +(send *ri* :hand-angle-vector :larm #f(0 0 0 0 0 0) 1000) ;; to move left hand. + +;; Open +(send *ri* :stop-grasp :larm) ;; to move left hand. +;; Before grasping +(send *ri* :prepare-grasp :larm) ;; to move left hand. +;; Grasp +(send *ri* :start-grasp :larm) ;; to move left hand. +;; Power-of position +(send *ri* :default-grasp :larm) ;; to move left hand. +``` + +Other methods than the hand interface is inherit from pr2eus. \ No newline at end of file From a385c3cad5cffabe668f9bf7d69f0d0ad923ea40 Mon Sep 17 00:00:00 2001 From: Michitoshi Tsubaki Date: Fri, 15 May 2026 18:46:13 +0900 Subject: [PATCH 05/10] Add hand interface --- jsk_g1_robot/g1eus/euslisp/g1-interface.l | 137 +++++++++++++++++++++- 1 file changed, 135 insertions(+), 2 deletions(-) diff --git a/jsk_g1_robot/g1eus/euslisp/g1-interface.l b/jsk_g1_robot/g1eus/euslisp/g1-interface.l index a25742ae21..449a72d7bb 100644 --- a/jsk_g1_robot/g1eus/euslisp/g1-interface.l +++ b/jsk_g1_robot/g1eus/euslisp/g1-interface.l @@ -3,9 +3,38 @@ (defclass g1-interface :super robot-interface - :slots ()) + :slots (hand-actions- + hand-joint-names-)) (defmethod g1-interface + (:arm-to-hand-controller-name + (arm) + (case arm + (:rarm "right_hand_controller") + (:larm "left_hand_controller") + (t nil))) + + (:default-hand-joint-names + (arm) + (case arm + (:rarm + (list + "R_thumb_proximal_yaw_joint" + "R_thumb_proximal_pitch_joint" + "R_index_proximal_joint" + "R_middle_proximal_joint" + "R_ring_proximal_joint" + "R_pinky_proximal_joint")) + (:larm + (list + "L_thumb_proximal_yaw_joint" + "L_thumb_proximal_pitch_joint" + "L_index_proximal_joint" + "L_middle_proximal_joint" + "L_ring_proximal_joint" + "L_pinky_proximal_joint")) + (t nil))) + (:upper-body-controller () (list @@ -40,7 +69,111 @@ ) (:init (&rest args) - (send-super* :init :robot g1-robot args))) + (send-super* :init :robot g1-robot args) + (setq hand-actions- (make-hash-table)) + (setq hand-joint-names- (make-hash-table)) + (dolist (arm (list :rarm :larm)) + (let* ((controller-name (send self :arm-to-hand-controller-name arm)) + (action-name (format nil "~a/follow_joint_trajectory" controller-name)) + (joint-names (ros::get-param (format nil "~a/joints" controller-name) + (send self :default-hand-joint-names arm))) + action) + (sethash arm hand-joint-names- joint-names) + (setq action + (instance ros::simple-action-client :init + action-name + control_msgs::FollowJointTrajectoryAction + :groupname groupname)) + (if (and joint-action-enable (send action :wait-for-server 3)) + (sethash arm hand-actions- action) + (ros::ros-warn "~A is not respond" action))))) + +;; (:larm (&rest args) +;; (send* self :limb :larm args)) + +;; (:rarm (&rest args) +;; (send* self :limb :rarm args)) + +;; (:limb +;; (arm &rest args) +;; (case (car args) +;; (:hand-angle-vector +;; (send* self :hand-angle-vector arm (cdr args))) +;; (:cancel-hand-angle-vector +;; (send self :cancel-hand-angle-vector arm)) +;; (:hand-interpolatingp +;; (send self :hand-interpolatingp arm)) +;; (t +;; (send* robot arm args)))) + + (:stop-grasp + (arm) + (send self :hand-angle-vector arm #f(0 0 0 0 0 0) 1000)) + + (:prepare-grasp + (arm) + (send self :hand-angle-vector arm #f(100 0 0 0 0 0) 1000)) + + (:start-grasp + (arm) + (send self :hand-angle-vector arm #f(40 20 80 80 80 80) 1000)) + + (:default-grasp + (arm) + (send self :hand-angle-vector arm #f(10 30 100 100 100 100) 1000)) + + (:hand-angle-vector + (arm av tm &key (wait t)) + (let ((action (gethash arm hand-actions-)) + (names (gethash arm hand-joint-names-))) + (cond + ((null action) + (ros::ros-warn "hand action for ~A is not available" arm) + nil) + ((null names) + (ros::ros-warn "joint names for ~A hand are not available" arm) + nil) + ((/= (length av) (length names)) + (ros::ros-warn "hand angle-vector length ~A does not match joint names length ~A for ~A" + (length av) (length names) arm) + nil) + (t + (let ((av-list (coerce av cons)) + res + (goal (instance control_msgs::FollowJointTrajectoryActionGoal :init)) + (traj (instance trajectory_msgs::JointTrajectory :init))) + (send traj :header :seq 1) + (send traj :header :stamp (ros::time-now)) + (send traj :joint_names names) + (send traj :points + (list (instance trajectory_msgs::JointTrajectoryPoint + :init + :positions (mapcar #'deg2rad av-list) + :time_from_start (ros::time (/ tm 1000))))) + (send goal :goal :trajectory traj) + (send action :send-goal goal) + (setq res (send action :get-result)) + (when wait + (send action :wait-for-result) + (setq res (send action :get-result))) + (unless (eq (send res :error_code) 0) + (warning-message 3 ":hand-angle-vector error code ~A returns from JTA: ~A~%" + (send res :error_code) (send res :error_string))) + res))))) + + (:cancel-hand-angle-vector + (arm) + (let ((action (gethash arm hand-actions-))) + (if action + (send action :cancel-goal) + (ros::ros-warn "hand action for ~A is not available" arm)))) + + (:hand-interpolatingp + (arm) + (send self :spin-once) + (let ((action (gethash arm hand-actions-))) + (and action + (eq (send action :get-state) ros::*simple-goal-state-active*))))) (defun g1-init () (unless (boundp '*ri*) From 8c304c19e2dea942ac6500fab58611f655111862 Mon Sep 17 00:00:00 2001 From: Michitoshi Tsubaki Date: Wed, 20 May 2026 12:33:33 +0900 Subject: [PATCH 06/10] Update README --- jsk_g1_robot/g1eus/README.md | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/jsk_g1_robot/g1eus/README.md b/jsk_g1_robot/g1eus/README.md index 3f2a1d45c5..8543f60963 100644 --- a/jsk_g1_robot/g1eus/README.md +++ b/jsk_g1_robot/g1eus/README.md @@ -69,7 +69,7 @@ Also please allocate the correct IP adress instructed [official instruction](htt - terminal 1 ```bash -source /setup.bash +source /devel/setup.bash roscore ``` @@ -84,30 +84,48 @@ sudo ./inspire_g1 -k -u - terminal 3 (Bringup robot as a ROS2 robot) ```bash -source /setup.bash -ros2 launch g1_bringup g1_bringup.launch.py network_interface:=enp0s31f6 hand_type:=inspire_dfq +source /install/setup.bash +ros2 launch g1_bringup g1_bringup.launch.py network_interface:= hand_type:=inspire_dfq ``` - terminal 4 (Activate ros2_control upper_body_controller) ```bash -source /setup.bash +source /install/setup.bash ros2 control set_controller_state upper_body_controller active ``` - terminal 5 (Bridge ros2 topic and action to ros1 topic and actionlib) ```bash -source /setup.bash -source /setup.bash +source /install/setup.bash +source /devel/setup.bash ros2 run ros1_bridge dynamic_bridge --bridge-all-topics ``` -- terminal 6 (Please run your own program using g1-interface.l) +- terminal 6 ~ (Please run your own program using g1-interface.l) ```bash cd euslisp roseus load "g1-interface.l" ``` +### If you want to do teleoperation using spacenav + +- terminal 6 + +``` bash +source /devel/setup.bash +roscd jsk_generic_teleop/launch # When you can't reach this package, please install the package. +roslaunch spacenav_classic.launch +``` + +- terminal 7 + +``` bash +source /devel/setup.bash +roscd jsk_generic_teleop/sample +roseus spacenav_classic.launch +``` + ## Tips From c74c26211e8f8ebc41221e8b4810f0298eaa90f1 Mon Sep 17 00:00:00 2001 From: Yoshiki Obinata Date: Thu, 21 May 2026 15:14:14 +0900 Subject: [PATCH 07/10] [g1eus] update README for readability and fix g1-interface.l path --- jsk_g1_robot/g1eus/README.md | 16 ++++++++++------ jsk_g1_robot/g1eus/{euslisp => }/g1-interface.l | 0 2 files changed, 10 insertions(+), 6 deletions(-) rename jsk_g1_robot/g1eus/{euslisp => }/g1-interface.l (100%) diff --git a/jsk_g1_robot/g1eus/README.md b/jsk_g1_robot/g1eus/README.md index 8543f60963..f6f4f91359 100644 --- a/jsk_g1_robot/g1eus/README.md +++ b/jsk_g1_robot/g1eus/README.md @@ -101,11 +101,15 @@ source /devel/setup.bash ros2 run ros1_bridge dynamic_bridge --bridge-all-topics ``` -- terminal 6 ~ (Please run your own program using g1-interface.l) -```bash -cd euslisp -roseus -load "g1-interface.l" +- terminal 6 ~ (Optional) +Please run your own program using g1-interface.l like + +```shell +source /devel/setup.bash +``` + +```lisp +(load "package://g1eus/g1-interface.l") ``` ### If you want to do teleoperation using spacenav @@ -144,4 +148,4 @@ roseus spacenav_classic.launch (send *ri* :default-grasp :larm) ;; to move left hand. ``` -Other methods than the hand interface is inherit from pr2eus. \ No newline at end of file +Other methods than the hand interface is inherit from pr2eus. diff --git a/jsk_g1_robot/g1eus/euslisp/g1-interface.l b/jsk_g1_robot/g1eus/g1-interface.l similarity index 100% rename from jsk_g1_robot/g1eus/euslisp/g1-interface.l rename to jsk_g1_robot/g1eus/g1-interface.l From 5df4f7d5ca52c8bc3417b505fac78e5658695ae0 Mon Sep 17 00:00:00 2001 From: Yoshiki Obinata Date: Thu, 21 May 2026 15:29:51 +0900 Subject: [PATCH 08/10] [g1eus] update docs for using squashed version of spacenav teleop --- jsk_g1_robot/g1eus/README.md | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/jsk_g1_robot/g1eus/README.md b/jsk_g1_robot/g1eus/README.md index f6f4f91359..025abbb40c 100644 --- a/jsk_g1_robot/g1eus/README.md +++ b/jsk_g1_robot/g1eus/README.md @@ -118,16 +118,7 @@ source /devel/setup.bash ``` bash source /devel/setup.bash -roscd jsk_generic_teleop/launch # When you can't reach this package, please install the package. -roslaunch spacenav_classic.launch -``` - -- terminal 7 - -``` bash -source /devel/setup.bash -roscd jsk_generic_teleop/sample -roseus spacenav_classic.launch +roslaunch jsk_generic_teleop spacenav_classic.launch ``` From 3ddb4239664091753bd30cca4c1c8d9e73f448b0 Mon Sep 17 00:00:00 2001 From: Michitoshi Tsubaki Date: Fri, 22 May 2026 15:13:03 +0900 Subject: [PATCH 09/10] Fix path of g1.l and README following jsk_generic_teleop --- jsk_g1_robot/g1eus/.gitignore | 2 +- jsk_g1_robot/g1eus/CMakeLists.txt | 4 ++-- jsk_g1_robot/g1eus/README.md | 4 ++-- jsk_g1_robot/g1eus/g1-interface.l | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/jsk_g1_robot/g1eus/.gitignore b/jsk_g1_robot/g1eus/.gitignore index 018fcba334..b8af841467 100644 --- a/jsk_g1_robot/g1eus/.gitignore +++ b/jsk_g1_robot/g1eus/.gitignore @@ -1,2 +1,2 @@ -euslisp/g1.l +g1.l models/g1.urdf \ No newline at end of file diff --git a/jsk_g1_robot/g1eus/CMakeLists.txt b/jsk_g1_robot/g1eus/CMakeLists.txt index 8b898045f1..8e0920c79d 100644 --- a/jsk_g1_robot/g1eus/CMakeLists.txt +++ b/jsk_g1_robot/g1eus/CMakeLists.txt @@ -14,7 +14,7 @@ catkin_package( set(G1_DESCRIPTION_DIR ${unitree_controller_SOURCE_PREFIX}/../robots/g1_description) set(G1_SOURCE_URDF ${G1_DESCRIPTION_DIR}/g1_29dof.urdf) set(G1_GENERATED_URDF ${PROJECT_SOURCE_DIR}/models/g1.urdf) -set(G1_EUSLISP ${PROJECT_SOURCE_DIR}/euslisp/g1.l) +set(G1_EUSLISP ${PROJECT_SOURCE_DIR}/g1.l) if(NOT EXISTS ${G1_SOURCE_URDF}) message(FATAL_ERROR "Could not find G1 URDF at ${G1_SOURCE_URDF}") @@ -47,6 +47,6 @@ install(DIRECTORY config euslisp models DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} USE_SOURCE_PERMISSIONS) -install(FILES ${G1_GENERATED_URDF} ${G1_EUSLISP} +install(FILES ${G1_GENERATED_URDF} ${G1_EUSLISP} g1-interface.l DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION} OPTIONAL) diff --git a/jsk_g1_robot/g1eus/README.md b/jsk_g1_robot/g1eus/README.md index 025abbb40c..6dd3d499b2 100644 --- a/jsk_g1_robot/g1eus/README.md +++ b/jsk_g1_robot/g1eus/README.md @@ -118,7 +118,7 @@ source /devel/setup.bash ``` bash source /devel/setup.bash -roslaunch jsk_generic_teleop spacenav_classic.launch +roslaunch jsk_generic_teleop g1_spacenav_teleop.launch ``` @@ -126,7 +126,7 @@ roslaunch jsk_generic_teleop spacenav_classic.launch - Hand Interface -```roseus +```lisp (send *ri* :hand-angle-vector :larm #f(0 0 0 0 0 0) 1000) ;; to move left hand. ;; Open diff --git a/jsk_g1_robot/g1eus/g1-interface.l b/jsk_g1_robot/g1eus/g1-interface.l index 449a72d7bb..203674a729 100644 --- a/jsk_g1_robot/g1eus/g1-interface.l +++ b/jsk_g1_robot/g1eus/g1-interface.l @@ -1,5 +1,5 @@ (load "package://pr2eus/robot-interface.l") -(require :g1 "package://g1eus/euslisp/g1.l") +(require :g1 "package://g1eus/g1.l") (defclass g1-interface :super robot-interface From 6de778a25f10eada291e89d9989186ad7ba99075 Mon Sep 17 00:00:00 2001 From: Michitoshi Tsubaki Date: Mon, 8 Jun 2026 15:14:44 +0900 Subject: [PATCH 10/10] Fix rounded seconds --- jsk_g1_robot/g1eus/g1-interface.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jsk_g1_robot/g1eus/g1-interface.l b/jsk_g1_robot/g1eus/g1-interface.l index 203674a729..78ff7b094e 100644 --- a/jsk_g1_robot/g1eus/g1-interface.l +++ b/jsk_g1_robot/g1eus/g1-interface.l @@ -149,7 +149,7 @@ (list (instance trajectory_msgs::JointTrajectoryPoint :init :positions (mapcar #'deg2rad av-list) - :time_from_start (ros::time (/ tm 1000))))) + :time_from_start (ros::time (/ tm 1000.0))))) (send goal :goal :trajectory traj) (send action :send-goal goal) (setq res (send action :get-result))