unitreerobotics / unitree_ros

BSD 3-Clause "New" or "Revised" License
612 stars 268 forks source link

Minimal example ROS driver #8

Open SteveMacenski opened 3 years ago

SteveMacenski commented 3 years ago

Hi,

Most robots have some node that will connect to the robot and stream data (images, imu, odometry, joint states, etc) and accept a command velocity Twist message (like drive forward at X m/s, turn at M rad/s). Does this have that node? If so, where is it?

I see in this repo examples of launching in simulation and how to run on the real robot if we wanted to change the low level controllers. But if I'm totally fine with the low level controllers and just want to control the higher level functions of the robot to make it autonomous, how do I do that?

Examples:

I see that most, if not all, of this is in your high level control mode API, but I don't see code examples of these here and some of the info is missing (programmatically know if its in the fault mode when it flips over or mode is missing the fast "trot/run" mode and not just walk or make it do a flip) that the remote controller can do

SteveMacenski commented 3 years ago

I'm also looking for this in ROS 2, though I'd be happy to help translate to ROS2 if necessary if there's something in ROS 1 or non-ROS example code for these items.

tahir1069 commented 3 years ago

Most robots have some node that will connect to the robot and stream data (images, imu, odometry, joint states, etc) and accept a command velocity Twist message (like drive forward at X m/s, turn at M rad/s). Does this have that node? If so, where is it?

We are working on that you can find minimal working code here. I hope this will solve your above mentioned issues, I have tested the code on real robot.

I see in this repo examples of launching in simulation and how to run on the real robot if we wanted to change the low level controllers. But if I'm totally fine with the low level controllers and just want to control the higher level functions of the robot to make it autonomous, how do I do that?

With above mentioned you can control with ROS. What you want to achieve, may be elaborate a little.

I see that most, if not all, of this is in your high level control mode API, but I don't see code examples of these here and some of the info is missing (programmatically know if its in the fault mode when it flips over or mode is missing the fast "trot/run" mode and not just walk or make it do a flip) that the remote controller can do

We are actively developing, hopefully this will be available soon on our Github.

tahir1069 commented 3 years ago

I'm also looking for this in ROS 2, though I'd be happy to help translate to ROS2 if necessary if there's something in ROS 1 or non-ROS example code for these items.

Contact me if you want to contribute we can collaborate.

SteveMacenski commented 3 years ago

I'm not sure how much more I can elaborate - if you look at what a "typical" ROS driver is for a robot platform, you'll typically see something that accepts velocity commands, publishes out internal metadata/state/sensor info, and exposes relevant services specific to that robot (for instance here, roll over or power off).

Within Unitree-language, this would be high-level control rather than low-level control of the robot system. I can totally see uses for people wanting to send over a stream of join torques/poses/velocities, but to make use of their internally built ones (which I would imagine are better than whatever I could throw together for a demo) and use the Unitree robots like any other robot, I need just an interface to give it robot-level commands rather than joint/SDK-level commands.

ChristyanCruz11 commented 3 years ago

Some pages are not able !

Hi,

Most robots have some node that will connect to the robot and stream data (images, imu, odometry, joint states, etc) and accept a command velocity Twist message (like drive forward at X m/s, turn at M rad/s). Does this have that node? If so, where is it?

I see in this repo examples of launching in simulation and how to run on the real robot if we wanted to change the low level controllers. But if I'm totally fine with the low level controllers and just want to control the higher level functions of the robot to make it autonomous, how do I do that?

Examples:

* topic to report if in recovery mode from having flipped over / internal state necessary

* command velocity for base to track `cmd_vel` topic

* get IMU (`imu`) / image / joint states / odometry `odom` / sensor data

* Robot specific services (change modes, command to self right, any other mode change or features for the robots that aren't just getting data or commanding velocities in your SDK)

* power on / off

I see that most, if not all, of this is in your high level control mode API, but I don't see code examples of these here and some of the info is missing (programmatically know if its in the fault mode when it flips over or mode is missing the fast "trot/run" mode and not just walk or make it do a flip) that the remote controller can do

dlee640 commented 3 years ago

@tahir1069 @SteveMacenski Hello. My team and I are currently also working on ROS2 version for unitree_ros (or finding the right solution to have nav2 on ros2 end and the unitree_ros + controller on ros1 end and have them communicate to each other using bridge solution) mostly for the purpose of utilizing nav2 & behaviortree based solution to navigation. Please let me know if I can find a way to collaborate? Thanks.

MAVProxyUser commented 2 years ago

@TrivasZhang has any of this changed? I recently got the CyberDog from Xiaomi and was able to very quickly get the ROS setup interacting with custom code. There is an example "centroid follower" (https://github.com/linzhibo/Cyberdog_utils) that is very much like the TurtleBot follower (https://wiki.ros.org/turtlebot_follower/Tutorials/Demo)

I very quickly was able to work with the ROS components with minimal hassle. https://twitter.com/d0tslash/status/1568496092404224000

I simple ssh into the Xiaomi dog, download the Cyberdog_utils repo, use colcon, and reboot dog. Literally took minutes. Can Unitree go1 have similar example?

image

MAVProxyUser commented 2 years ago

@dlee640 @tahir1069 @SteveMacenski have you seen the ROS2 implementation for A1? I wonder if we can make it work on go1 also!? https://github.com/crystaldust/unitree_a1_ros2

MAVProxyUser commented 2 years ago

This seems to address the ROS2 problem directly with support from Unitree eh? https://github.com/unitreerobotics/unitree_ros2_to_real/blob/main/ros2_unitree_legged_msgs/CMakeLists.txt

jmsalash commented 1 year ago

From the readme: "Please be aware that the Gazebo simulation cannot do high-level control, namely walking"

It's been two years now since this issue was opened - low level control may be useful for gait research, but not much beyond that.

Are there any plans to implement a full ROS driver as @SteveMacenski suggested?

I found this ROS package for quadruped control that includes your robots, but ideally we should be able to move from sim to real robot with minor modifications on the code.

https://github.com/chvmp/champ

MAVProxyUser commented 1 year ago

@tahir1069 what happened to mbs_unitree_ros? The repo seems to be gone? https://github.com/MYBOTSHOP/mbs_unitree_ros

MAVProxyUser commented 1 year ago

I've found today that the ROS2 example is seemingly crippled on purpose via a change to convert.h https://github.com/unitreerobotics/unitree_ros2_to_real/issues/1#issuecomment-1371409995 210647839-fd548b79-8e59-4667-9da3-beb008f476ac

MAVProxyUser commented 1 year ago

I've almost got the ROS2 example rebuilt, I've got one of the types wrong somewhere... https://github.com/unitreerobotics/unitree_ros2_to_real/compare/main...MAVProxyUser:unitree_ros2_to_real:main

Starting >>> unitree_legged_real
--- stderr: unitree_legged_real                             
/usr/bin/ld: CMakeFiles/ros2_twist_sub.dir/src/ros2_twist_sub.cpp.o: in function `std::_Function_handler<std::shared_ptr<rclcpp::SubscriptionBase> (rclcpp::node_interfaces::NodeBaseInterface*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rclcpp::QoS const&), rclcpp::create_subscription_factory<geometry_msgs::msg::Twist_<std::allocator<void> >, void (&)(std::shared_ptr<geometry_msgs::msg::Twist_<std::allocator<void> > const>), std::allocator<void>, geometry_msgs::msg::Twist_<std::allocator<void> >, rclcpp::Subscription<geometry_msgs::msg::Twist_<std::allocator<void> >, std::allocator<void>, rclcpp::message_memory_strategy::MessageMemoryStrategy<geometry_msgs::msg::Twist_<std::allocator<void> >, std::allocator<void> > >, rclcpp::message_memory_strategy::MessageMemoryStrategy<geometry_msgs::msg::Twist_<std::allocator<void> >, std::allocator<void> > >(void (&)(std::shared_ptr<geometry_msgs::msg::Twist_<std::allocator<void> > const>), rclcpp::SubscriptionOptionsWithAllocator<std::allocator<void> > const&, rclcpp::message_memory_strategy::MessageMemoryStrategy<geometry_msgs::msg::Twist_<std::allocator<void> >, std::allocator<void> >::SharedPtr, std::shared_ptr<rclcpp::topic_statistics::SubscriptionTopicStatistics<geometry_msgs::msg::Twist_<std::allocator<void> > > >)::{lambda(rclcpp::node_interfaces::NodeBaseInterface*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rclcpp::QoS const&)#1}>::_M_invoke(std::_Any_data const&, rclcpp::node_interfaces::NodeBaseInterface*&&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, rclcpp::QoS const&)':
ros2_twist_sub.cpp:(.text._ZNSt17_Function_handlerIFSt10shared_ptrIN6rclcpp16SubscriptionBaseEEPNS1_15node_interfaces17NodeBaseInterfaceERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS1_3QoSEEZNS1_27create_subscription_factoryIN13geometry_msgs3msg6Twist_ISaIvEEERFvS0_IKSO_EESN_SO_NS1_12SubscriptionISO_SN_NS1_23message_memory_strategy21MessageMemoryStrategyISO_SN_EEEESW_EENS1_19SubscriptionFactoryEOT0_RKNS1_32SubscriptionOptionsWithAllocatorIT1_EENT4_9SharedPtrES0_INS1_16topic_statistics27SubscriptionTopicStatisticsIT2_EEEEUlS6_SE_SH_E_E9_M_invokeERKSt9_Any_dataOS6_SE_SH_[_ZNSt17_Function_handlerIFSt10shared_ptrIN6rclcpp16SubscriptionBaseEEPNS1_15node_interfaces17NodeBaseInterfaceERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEERKNS1_3QoSEEZNS1_27create_subscription_factoryIN13geometry_msgs3msg6Twist_ISaIvEEERFvS0_IKSO_EESN_SO_NS1_12SubscriptionISO_SN_NS1_23message_memory_strategy21MessageMemoryStrategyISO_SN_EEEESW_EENS1_19SubscriptionFactoryEOT0_RKNS1_32SubscriptionOptionsWithAllocatorIT1_EENT4_9SharedPtrES0_INS1_16topic_statistics27SubscriptionTopicStatisticsIT2_EEEEUlS6_SE_SH_E_E9_M_invokeERKSt9_Any_dataOS6_SE_SH_]+0x4a): undefined reference to `rosidl_message_type_support_t const* rosidl_typesupport_cpp::get_message_type_support_handle<geometry_msgs::msg::Twist_<std::allocator<void> > >()'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/ros2_twist_sub.dir/build.make:137: ros2_twist_sub] Error 1
make[1]: *** [CMakeFiles/Makefile2:165: CMakeFiles/ros2_twist_sub.dir/all] Error 2
make: *** [Makefile:141: all] Error 2
---
Failed   <<< unitree_legged_real [0.53s, exited with code 2]

Summary: 0 packages finished [0.82s]
  1 package failed: unitree_legged_real
  1 package had stderr output: unitree_legged_real