Unitree D1 Arm Setup
1. Install the Unitree SDK
git clone https://github.com/unitreerobotics/unitree_sdk2.git
cd unitree_sdk2
mkdir build && cd build
cmake ..
sudo make install
2. Build the D1 SDK
Download d1_sdk.zip from Unitree, then:
unzip d1_sdk.zip
cd d1_sdk
mkdir build && cd build
cmake ..
make
If the build cannot find the DDS headers, add this to CMakeLists.txt:
include_directories(/usr/local/include/ddscxx /usr/local/include/iceoryx/v2.0.2 /usr/local/lib)
3. Make the libraries visible to the linker
echo "/usr/local/lib" | sudo tee /etc/ld.so.conf.d/local-lib.conf
sudo ldconfig
If that is not enough, these sometimes help:
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
sudo chmod +r /usr/local/lib/libddsc.so.0
4. Configure the network
Give the Ethernet interface connected to the arm a static address in the
192.168.123.0/24 subnet, for example 192.168.123.99 with netmask
255.255.255.0 and no gateway. Note the interface name with ip addr.
5. Run the bundled controller
cd <path/to/d1_sdk>/build
sudo ./arm_zero_control enp86s0 # your interface name
6. Send joint positions from the command line
The arm listens on the rt/arm_Command topic for a JSON string. The program below
takes seven angles (six joints and the gripper), builds that JSON and publishes it once.
Save it as examples/interactive_joint_control.cpp.
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
#include "unitree/robot/channel/channel_publisher.hpp"
#include "unitree/common/time/time_tool.hpp"
#include "msg/ArmString_.hpp"
#define TOPIC "rt/arm_Command"
using namespace unitree::robot;
using namespace unitree::common;
int main(int argc, char *argv[]) {
if (argc != 8) {
std::cerr << "Usage: " << argv[0] << " a0 a1 a2 a3 a4 a5 a6" << std::endl;
std::cerr << "Example: " << argv[0] << " 0 -60 60 0 30 0 0" << std::endl;
return 1;
}
std::vector<double> angles;
for (int i = 1; i < argc; ++i) angles.push_back(std::stod(argv[i]));
ChannelFactory::Instance()->Init(0);
ChannelPublisher<unitree_arm::msg::dds_::ArmString_> publisher(TOPIC);
publisher.InitChannel();
// {"seq":4,"address":1,"funcode":2,"data":{"mode":1,"angle0":0,"angle1":-60,...}}
std::stringstream ss;
ss << "{\"seq\":4,\"address\":1,\"funcode\":2,\"data\":{\"mode\":1,";
for (size_t i = 0; i < angles.size(); ++i) {
ss << "\"angle" << i << "\":" << angles[i] << (i + 1 == angles.size() ? "" : ",");
}
ss << "}}";
unitree_arm::msg::dds_::ArmString_ msg{};
msg.data_() = ss.str();
std::cout << "Sending: " << msg.data_() << std::endl;
publisher.Write(msg);
return 0;
}
Register it in the root CMakeLists.txt of d1_sdk:
add_executable(interactive_joint_control examples/interactive_joint_control.cpp)
target_link_libraries(interactive_joint_control ${PROJECT_NAME})
Build and run:
cd d1_sdk/build
cmake ..
make -j4
sudo ./interactive_joint_control 0 -60 60 0 30 0 0