first commit

This commit is contained in:
Agnel Wang 2022-09-13 19:52:44 +08:00
parent 5221e95827
commit 0b7b40d4d0
22 changed files with 673 additions and 427 deletions

1
.gitignore vendored
View File

@ -1 +0,0 @@
build

View File

@ -5,6 +5,7 @@ project(z1_sdk)
include_directories(
include
unitreeArm
# ${EIGEN_PATH}
)
@ -12,24 +13,14 @@ link_directories(lib)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3 -pthread")
# file(GLOB_RECURSE ADD_SRC_LIST
# src/*.cpp
# )
# set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/../lib) # SHARED:CMAKE_LIBRARY_OUTPUT_DIRECTORY STATIC:CMAKE_ARCHIVE_OUTPUT_DIRECTORY
# add_library(Z1_SDK_Linux64 SHARED ${ADD_SRC_LIST})
add_executable(example_lowCmd_send examples/example_lowCmd_send.cpp)
target_link_libraries(example_lowCmd_send Z1_SDK_Linux64)
add_executable(example_state_send examples/example_state_send.cpp)
target_link_libraries(example_state_send Z1_SDK_Linux64)
add_executable(example_state_recv examples/example_state_recv.cpp)
target_link_libraries(example_state_recv Z1_SDK_Linux64)
add_executable(example_keyboard_recv examples/example_keyboard_recv.cpp)
target_link_libraries(example_keyboard_recv Z1_SDK_Linux64)
add_executable(example_keyboard_send examples/example_keyboard_send.cpp)
target_link_libraries(example_keyboard_send Z1_SDK_Linux64)
add_executable(bigDemo examples/bigDemo.cpp)
target_link_libraries(bigDemo Z1_SDK_Linux64)
add_executable(getJointGripperState examples/getJointGripperState.cpp)
target_link_libraries(getJointGripperState Z1_SDK_Linux64)

View File

@ -1,76 +1 @@
# v3.6.1
The z1_sdk is mainly used for communication between z1_controller and command panel(keyboard, joystick, user control panel etc).
## Notice
support robot: Z1(v3.6.1)
not support robot: Z1(v3.4, v3.5)
## Dependencies
- build-essential
```bash
sudo apt install build-essential
```
- Boost (version 1.5.4 or higher)
```bash
dpkg -S /usr/include/boost/version.hpp # check boost version
sudo apt install libboost-dev # install boost
```
- CMake (version 2.8.3 or higher)
```bash
cmake --version # check cmake version
sudo apt install cmake # install cmake
```
- [Eigen](https://gitlab.com/libeigen/eigen/-/releases/3.3.9) (version 3.3.9 or higher)
```bash
cd eigen-3.3.9
mkdir build && cd build
cmake ..
sudo make install
sudo ln -s /usr/local/include/eigen3 /usr/include/eigen3
sudo ln -s /usr/local/include/eigen3/Eigen /usr/local/include/Eigen
```
## Example
There are three examples of command panel control based on SDK in this project, you can use it fllowing the steps below.
### State change
- First, set(CTRL_PANEL SDK) # z1_ws/src/z1_controller/CMakeList.txtand then rebuild the z1_ws to generate z1_ctrl, then open a teminal to run z1_ctrl
```
cd /<path to>/z1_controller/build
sudo ./z1_ctrl
```
- Sencond, build the z1_sdk, and then open another terminal to run example.
```
cd /<path to>/z1_sdk && mkdir build && cd build
cmake ..
make -j4
./example_state_send
```
### Low level control
```
sudo ./z1_ctrl # Running in a terminal
./example_lowCmd_send # Running in another terminal
```
### Keyboard control
```
sudo ./z1_ctrl # Running in a terminal
./example_keyboard_send # Running in another terminal
```
see [unitree-z1-docs](http://dev-z1.unitree.com/)

119
examples/bigDemo.cpp Normal file
View File

@ -0,0 +1,119 @@
#include "unitreeArm.h"
class Custom : public unitreeArm{
public:
Custom(){};
~Custom(){};
void armCtrlByFSM();
void armCtrlByTraj();
};
void Custom::armCtrlByFSM() {
Vec6 posture[2];
std::cout << "[JOINTCTRL]" << std::endl;
setFsm(ArmFSMState::JOINTCTRL);
sleep(1);// wait for a while for the command to execute
std::cout << "[TOSTATE] forward" << std::endl;
labelRun("forward");
sleep(1);
std::cout << "[MOVEJ]" << std::endl;
posture[0]<<0.5,0.1,0.1,0.5,-0.2,0.5;
MoveJ(posture[0], -1.0);
sleep(1);
std::cout << "[MOVEL]" << std::endl;
posture[0] << 0,0,0,0.45,-0.2,0.2;
MoveL(posture[0]);
sleep(1);
std::cout << "[MOVEC]" << std::endl;
posture[0] << 0,0,0,0.4,0,0.3;
posture[1] << 0,0,0,0.45,0.2,0.2;
MoveC(posture[0], posture[1]);
sleep(1);
std::cout << "[BACKTOSTART]" << std::endl;
backToStart();
sleep(1);
}
void Custom::armCtrlByTraj(){
Vec6 posture[2];
std::cout << "[TOSTATE] forward" << std::endl;
labelRun("forward");
sleep(1);
int order=1;
// No.1 trajectory
_trajCmd.trajOrder = order++;
_trajCmd.trajType = TrajType::MoveJ;
_trajCmd.maxSpeed = 0.3;
_trajCmd.gripperPos = -1.0;
posture[0] << 0.5,0.1,0.1,0.5,-0.2,0.5;
// posture[0] << 0.0,0.0,0,0.5,-0.2,0.5;
_trajCmd.posture[0] = Vec6toPosture(posture[0]);
setTraj(_trajCmd);
usleep(500000);
// No.2 trajectory
_trajCmd.trajOrder = order++;
_trajCmd.trajType = TrajType::MoveL;
_trajCmd.maxSpeed = 0.2;
_trajCmd.gripperPos = 0.0;
posture[0] << 0,0,0,0.45,-0.2,0.2;
_trajCmd.posture[0] = Vec6toPosture(posture[0]);
setTraj(_trajCmd);
usleep(500000);
// No.4 trajectory
_trajCmd.trajOrder = order++;
_trajCmd.trajType = TrajType::Stop;
_trajCmd.stopTime = 2.0;
_trajCmd.gripperPos = 0.0;
setTraj(_trajCmd);
usleep(500000);
// No.4 trajectory
_trajCmd.trajOrder = order++;
_trajCmd.trajType = TrajType::MoveC;
_trajCmd.maxSpeed = 0.3;
_trajCmd.gripperPos = -1.0;
posture[0] << 0,0,0,0.45,0,0.4;
posture[1] << 0,0,0,0.45,0.2,0.2;
_trajCmd.posture[0] = Vec6toPosture(posture[0]);
_trajCmd.posture[1] = Vec6toPosture(posture[1]);
setTraj(_trajCmd);
usleep(500000);
//run
setFsm(ArmFSMState::TRAJECTORY);
// wait for completion
while (_recvState.state != ArmFSMState::JOINTCTRL){
usleep(4000);
}
}
int main() {
Custom custom;
custom.backToStart();
sleep(1);
if(false){
custom.armCtrlByFSM();
}else{
custom.armCtrlByTraj();
}
custom.backToStart();
return 0;
}

View File

@ -1,53 +0,0 @@
/*****************************************************************
Copyright (c) 2022, Unitree Robotics.Co.Ltd. All rights reserved.
*****************************************************************/
#include "unitree_arm_sdk/unitree_arm_sdk.h"
bool running = true;
// over watch the ctrl+c command
void ShutDown(int sig){
std::cout << "[STATE] stop the controller" << std::endl;
running = false;
}
int main(){
EmptyAction emptyAction((int)ArmFSMState::INVALID);
std::vector<KeyAction*> events;
CmdPanel *cmdPanel;
events.push_back(new StateAction("`", (int)ArmFSMState::BACKTOSTART));
events.push_back(new StateAction("1", (int)ArmFSMState::PASSIVE));
events.push_back(new StateAction("2", (int)ArmFSMState::JOINTCTRL));
events.push_back(new StateAction("3", (int)ArmFSMState::CARTESIAN));
events.push_back(new StateAction("4", (int)ArmFSMState::MOVEJ));
events.push_back(new StateAction("5", (int)ArmFSMState::MOVEL));
events.push_back(new StateAction("6", (int)ArmFSMState::MOVEC));
events.push_back(new StateAction("7", (int)ArmFSMState::TEACH));
events.push_back(new StateAction("8", (int)ArmFSMState::TEACHREPEAT));
events.push_back(new StateAction("9", (int)ArmFSMState::SAVESTATE));
events.push_back(new StateAction("0", (int)ArmFSMState::TOSTATE));
events.push_back(new StateAction("-", (int)ArmFSMState::TRAJECTORY));
events.push_back(new StateAction("=", (int)ArmFSMState::CALIBRATION));
events.push_back(new StateAction("]", (int)ArmFSMState::NEXT));
events.push_back(new StateAction("/", (int)ArmFSMState::LOWCMD));
events.push_back(new ValueAction("q", "a", 1.0));
events.push_back(new ValueAction("w", "s", 1.0));
events.push_back(new ValueAction("e", "d", 1.0));
events.push_back(new ValueAction("r", "f", 1.0));
events.push_back(new ValueAction("t", "g", 1.0));
events.push_back(new ValueAction("y", "h", 1.0));
events.push_back(new ValueAction("down", "up", 1.0));
cmdPanel = new UnitreeKeyboardUDPRecv(events, emptyAction);
while(true){
std::cout << "state:" << (int)cmdPanel->getState() << std::endl;
std::cout << "value:" << cmdPanel->getValues().at(0) << std::endl;
usleep(1000000);
}
delete cmdPanel;
return 0;
}

View File

@ -1,27 +0,0 @@
/*****************************************************************
Copyright (c) 2022, Unitree Robotics.Co.Ltd. All rights reserved.
*****************************************************************/
#include "unitree_arm_sdk/unitree_arm_sdk.h"
int main(){
UDPPort udp("127.0.0.1", 8072, 8071, sizeof(SendCmd), BlockYN::NO, 500000);
SendCmd sendCmd;
RecvState recvState;
sendCmd = {0};
recvState = {0};
recvState.head[0] = 0xFE;
recvState.head[1] = 0xFF;
bool turn = true;
while(true){
udp.send((uint8_t*)&recvState, sizeof(RecvState));
udp.recv((uint8_t*)&sendCmd, sizeof(SendCmd));
printf("%d \n", (int)sendCmd.state);
usleep(2000);
}
return 0;
}

View File

@ -1,219 +0,0 @@
/*****************************************************************
Copyright (c) 2022, Unitree Robotics.Co.Ltd. All rights reserved.
*****************************************************************/
#include "unitree_arm_sdk/unitree_arm_sdk.h"
SendCmd sendCmd;
RecvState recvState;
UDPPort udp("127.0.0.1", 8071, 8072, sizeof(RecvState), BlockYN::NO, 500000);
void UDPCommunication(){
udp.send((uint8_t*)&sendCmd, sizeof(SendCmd));
udp.recv((uint8_t*)&recvState, sizeof(RecvState));
}
int main(){
sendCmd = {0};
recvState = {0};
sendCmd.head[0] = 0xFE;
sendCmd.head[1] = 0xFF;
sendCmd.state = ArmFSMState::INVALID;
float deltaTime = 4000; // us
LoopFunc *udpCommunication;
udpCommunication = new LoopFunc("udp", 0.002, boost::bind(&UDPCommunication));
udpCommunication->start();
std::cout << "[PASSIVE]" << std::endl;
sendCmd.state = ArmFSMState::PASSIVE;
while (recvState.state != ArmFSMState::PASSIVE){
usleep(deltaTime);
}
std::cout << "[BACKTOSTART]" << std::endl;
sendCmd.state = ArmFSMState::BACKTOSTART;
while (recvState.state != ArmFSMState::BACKTOSTART){
usleep(deltaTime);
}
sendCmd.state = ArmFSMState::INVALID;
while (recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
std::cout << "[CARTESIAN]" << std::endl;
sendCmd.state = ArmFSMState::CARTESIAN;
while (recvState.state != ArmFSMState::CARTESIAN){
usleep(deltaTime);
}
for(int i(0); i<2000; ++i){
if(i<500){
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::E;
}
else if(i<1000){
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::Q;
}
else if(i<1500){
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::D;
}
else{
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::Q;
}
// printf("------state:%d-------\n", (int)recvState.state);
// printf("Pos:%f \n", recvState.jointState[0].Pos);
// printf("Pos:%f \n", recvState.jointState[1].Pos);
// printf("Pos:%f \n", recvState.jointState[2].Pos);
// printf("roll:%f \n", recvState.cartesianState.roll);
// printf("pitch:%f \n", recvState.cartesianState.pitch);
// printf("yaw:%f \n", recvState.cartesianState.yaw);
usleep(deltaTime);
}
std::cout << "[JOINTCTRL]" << std::endl;
sendCmd.state = ArmFSMState::JOINTCTRL;
while (recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
for(int i(0); i<1800; ++i){
if(i<300){
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::Q;
}
else if(i<600){
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::W;
}
else if(i<900){
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::D;
}
else if(i<1200){
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::R;
}
else if(i<1500){
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::T;
}
else{
sendCmd.state = ArmFSMState::INVALID;
sendCmd.value = ArmFSMValue::Y;
}
// printf("------state:%d-------\n", (int)recvState.state);
// printf("Pos:%f \n", recvState.jointState[0].Pos);
// printf("Pos:%f \n", recvState.jointState[1].Pos);
// printf("Pos:%f \n", recvState.jointState[2].Pos);
// printf("roll:%f \n", recvState.cartesianState.roll);
// printf("pitch:%f \n", recvState.cartesianState.pitch);
// printf("yaw:%f \n", recvState.cartesianState.yaw);
usleep(deltaTime);
}
std::cout << "[SAVESTATE]" << std::endl;
std::string test = "test";
sendCmd.state = ArmFSMState::SAVESTATE;
strcpy(sendCmd.valueUnion.saveState, test.c_str());
usleep(deltaTime);
std::cout << "[BACKTOSTART]" << std::endl;
sendCmd.state = ArmFSMState::BACKTOSTART;
while(recvState.state != ArmFSMState::BACKTOSTART){
usleep(deltaTime);
}
sendCmd.state = ArmFSMState::INVALID;
while (recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
std::cout << "[TOSTATE]" << std::endl;
sendCmd.state = ArmFSMState::TOSTATE;
strcpy(sendCmd.valueUnion.toState, test.c_str());
while (recvState.state != ArmFSMState::TOSTATE){
usleep(deltaTime);
}
sendCmd.state = ArmFSMState::INVALID;
while (recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
std::cout << "[BACKTOSTART]" << std::endl;
sendCmd.state = ArmFSMState::BACKTOSTART;
while (recvState.state != ArmFSMState::BACKTOSTART){
usleep(deltaTime);
}
sendCmd.state = ArmFSMState::INVALID;
while (recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
std::cout << "[MoveJ]" << std::endl;
sendCmd.state = ArmFSMState::MOVEJ;
sendCmd.valueUnion.moveJ.roll = 0;
sendCmd.valueUnion.moveJ.pitch = 0;
sendCmd.valueUnion.moveJ.yaw = 0;
sendCmd.valueUnion.moveJ.x = 0.5;
sendCmd.valueUnion.moveJ.y = -0.3;
sendCmd.valueUnion.moveJ.z = 0.5;
while (recvState.state != ArmFSMState::MOVEJ){
usleep(deltaTime);
}
sendCmd.state = ArmFSMState::INVALID;
while (recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
std::cout << "[MoveL]" << std::endl;
sendCmd.state = ArmFSMState::MOVEL;
sendCmd.valueUnion.moveL.roll = 0;
sendCmd.valueUnion.moveL.pitch = 0;
sendCmd.valueUnion.moveL.yaw = 0;
sendCmd.valueUnion.moveL.x = 0.5;
sendCmd.valueUnion.moveL.y = 0.4;
sendCmd.valueUnion.moveL.z = 0.3;
while (recvState.state != ArmFSMState::MOVEL){
usleep(deltaTime);
}
sendCmd.state = ArmFSMState::INVALID;
while (recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
std::cout << "[MoveC]" << std::endl;
sendCmd.state = ArmFSMState::MOVEC;
sendCmd.valueUnion.moveC[0].roll = 0;
sendCmd.valueUnion.moveC[0].pitch = 0;
sendCmd.valueUnion.moveC[0].yaw = 0;
sendCmd.valueUnion.moveC[0].x = 0.5;
sendCmd.valueUnion.moveC[0].y = 0;
sendCmd.valueUnion.moveC[0].z = 0.5;
sendCmd.valueUnion.moveC[1].roll = 0;
sendCmd.valueUnion.moveC[1].pitch = 0;
sendCmd.valueUnion.moveC[1].yaw = 0;
sendCmd.valueUnion.moveC[1].x = 0.5;
sendCmd.valueUnion.moveC[1].y = -0.4;
sendCmd.valueUnion.moveC[1].z = 0.3;
while (recvState.state != ArmFSMState::MOVEC){
usleep(deltaTime);
}
sendCmd.state = ArmFSMState::INVALID;
while (recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
std::cout << "[BACKTOSTART]" << std::endl;
sendCmd.state = ArmFSMState::BACKTOSTART;
while (recvState.state != ArmFSMState::BACKTOSTART){
usleep(deltaTime);
}
return 0;
}

View File

@ -0,0 +1,50 @@
#include "unitreeArm.h"
class Custom : public unitreeArm {
public:
Custom(){};
~Custom(){};
void printJointGripperState();
Posture _gripperState;
};
void Custom::printJointGripperState() {
getJointState(_jointState);
std::cout<<std::endl;
std::cout<<"------ joint Pos ------"<<std::endl;
std::cout<<"joint0: "<<_jointState[0].Pos<<std::endl;
std::cout<<"joint1: "<<_jointState[1].Pos<<std::endl;
std::cout<<"joint2: "<<_jointState[2].Pos<<std::endl;
std::cout<<"joint3: "<<_jointState[3].Pos<<std::endl;
std::cout<<"joint4: "<<_jointState[4].Pos<<std::endl;
std::cout<<"joint5: "<<_jointState[5].Pos<<std::endl;
std::cout<<"------ joint Pos ------"<<std::endl;
std::cout<<std::endl;
getGripperState(_gripperState);
std::cout<<std::endl;
std::cout<<"------ GripperState ------"<<std::endl;
std::cout<<"roll: "<<_gripperState.roll<<std::endl;
std::cout<<"pitch: "<<_gripperState.pitch<<std::endl;
std::cout<<"yaw: "<<_gripperState.yaw<<std::endl;
std::cout<<"x: "<<_gripperState.x<<std::endl;
std::cout<<"y: "<<_gripperState.y<<std::endl;
std::cout<<"z: "<<_gripperState.z<<std::endl;
std::cout<<"------ GripperState Pos ------"<<std::endl;
std::cout<<std::endl;
}
int main() {
Custom custom;
LoopFunc loop_udpSendRecv("udp", 0.002, boost::bind(&Custom::UDPSendRecv,&custom));
LoopFunc loop_printJointState("printJointState", 1, boost::bind(&Custom::printJointGripperState,&custom));
loop_udpSendRecv.start();
loop_printJointState.start();
while (1) {
usleep(1000000);
}
}

View File

@ -77,7 +77,7 @@ public:
void setDt(double dt);
double getValue();
double getDValue();
double setValue(double value){_value = value;}
void setValue(double value){_value = value;}
private:
double _value;
double _changeDirection;
@ -112,6 +112,7 @@ public:
virtual SendCmd getSendCmd();
virtual void getRecvState(RecvState recvState);
bool isDisConnect;
protected:
virtual void _read() = 0;
void _start();
@ -120,9 +121,6 @@ protected:
void _pressKeyboard();
void _releaseKeyboard();
static void* _runStatic(void* obj);
static void* _readStatic(void* obj);
LoopFunc *_runThread;
LoopFunc *_readThread;

View File

@ -0,0 +1,159 @@
#ifndef _UNITREE_ARM_ALIENGO_COMMON_H_
#define _UNITREE_ARM_ALIENGO_COMMON_H_
#include <stdint.h>
namespace UNITREE_LEGGED_SDK
{
constexpr int HIGHLEVEL = 0x00;
constexpr int LOWLEVEL = 0xff;
constexpr double PosStopF = (2.146E+9f);
constexpr double VelStopF = (16000.0f);
#pragma pack(1)
typedef struct
{
float x;
float y;
float z;
} Cartesian;
typedef struct
{
float quaternion[4]; // quaternion, normalized, (w,x,y,z)
float gyroscope[3]; // angular velocity unit: rad/s)
float accelerometer[3]; // m/(s2)
float rpy[3]; // euler angleunit: rad)
int8_t temperature;
} IMU; // when under accelerated motion, the attitude of the robot calculated by IMU will drift.
typedef struct
{
uint8_t r;
uint8_t g;
uint8_t b;
} LED; // foot led brightness: 0~255
typedef struct
{
uint8_t mode; // motor working mode
float q; // current angle (unit: radian)
float dq; // current velocity (unit: radian/second)
float ddq; // current acc (unit: radian/second*second)
float tauEst; // current estimated output torque (unit: N.m)
float q_raw; // current angle (unit: radian)
float dq_raw; // current velocity (unit: radian/second)
float ddq_raw;
int8_t temperature; // current temperature (temperature conduction is slow that leads to lag)
uint32_t reserve[2]; // in reserve[1] returns the brake state.
} MotorState; // motor feedback
typedef struct
{
uint8_t mode; // desired working mode
float q; // desired angle (unit: radian)
float dq; // desired velocity (unit: radian/second)
float tau; // desired output torque (unit: N.m)
float Kp; // desired position stiffness (unit: N.m/rad )
float Kd; // desired velocity stiffness (unit: N.m/(rad/s) )
uint32_t reserve[3]; // in reserve[0] sends the brake cmd.
} MotorCmd; // motor control
typedef struct
{
uint8_t levelFlag; // flag to distinguish high level or low level
uint16_t commVersion;
uint16_t robotID;
uint32_t SN;
uint8_t bandWidth;
IMU imu;
MotorState motorState[20];
int16_t footForce[4]; // force sensors
int16_t footForceEst[4]; // force sensors
uint32_t tick; // reference real-time from motion controller (unit: us)
uint8_t wirelessRemote[40]; // wireless commands
uint32_t reserve;
uint32_t crc;
} LowState; // low level feedback
typedef struct
{
uint8_t levelFlag;
uint16_t commVersion;
uint16_t robotID;
uint32_t SN;
uint8_t bandWidth;
MotorCmd motorCmd[20];
LED led[4];
uint8_t wirelessRemote[40];
uint32_t reserve;
uint32_t crc;
} LowCmd; // low level control
typedef struct
{
uint8_t levelFlag;
uint16_t commVersion;
uint16_t robotID;
uint32_t SN;
uint8_t bandWidth;
uint8_t mode;
IMU imu;
float position[3]; // (unit: m), from robot own odometry in inertial frame, usually drift
float velocity[3]; // (unit: m/s), forwardSpeed, sideSpeed, updownSpeed in body frame
float yawSpeed; // (unit: rad/s), rotateSpeed in body frame.
Cartesian footPosition2Body[4]; // foot position relative to body
Cartesian footSpeed2Body[4]; // foot speed relative to body
int16_t footForce[4];
uint8_t wirelessRemote[40];
uint32_t reserve;
uint32_t crc;
} HighState; // high level feedback
typedef struct
{
uint8_t levelFlag;
uint16_t commVersion;
uint16_t robotID;
uint32_t SN;
uint8_t bandWidth;
uint8_t mode; // 0.idle, default stand | 1.force stand (controlled by dBodyHeight + rpy)
// 2.target velocity walking (controlled by velocity + yawSpeed)
// 3.target position walking (controlled by position + rpy[2])
// 4. path mode walking (reserve for future release)
// 5. position stand down. |6. position stand up |7. damping mode | 8. recovery mode
uint8_t gaitType; // 0.trot | 1. trot running | 2.climb stair
uint8_t speedLevel; // 0. default low speed. 1. medium speed 2. high speed. during walking
float dFootRaiseHeight; // (unit: m), swing foot height adjustment from default swing height.
float dBodyHeight; // (unit: m), body height adjustment from default body height.
float position[2]; // (unit: m), desired x and y position in inertial frame.
float rpy[3]; // (unit: rad), desired yaw-pitch-roll euler angle, expressed in roll(rpy[0]) pitch(rpy[1]) yaw(rpy[2])
float velocity[2]; // (unit: m/s), forwardSpeed, sideSpeed in body frame.
float yawSpeed; // (unit: rad/s), rotateSpeed in body frame.
LED led[4];
uint8_t wirelessRemote[40];
uint32_t reserve;
uint32_t crc;
} HighCmd; // high level control uint8_t mode
#pragma pack()
typedef struct
{
unsigned long long TotalCount; // total loop count
unsigned long long SendCount; // total send count
unsigned long long RecvCount; // total receive count
unsigned long long SendError; // total send error
unsigned long long FlagError; // total flag error
unsigned long long RecvCRCError; // total reveive CRC error
unsigned long long RecvLoseError; // total lose package count
} UDPState; // UDP communication state
constexpr int HIGH_CMD_LENGTH = (sizeof(HighCmd));
constexpr int HIGH_STATE_LENGTH = (sizeof(HighState));
}
#endif

View File

@ -20,6 +20,7 @@ enum class ArmFSMState{
TEACH,
TEACHREPEAT,
CALIBRATION,
SETTRAJ,
DANCE00,
DANCE01,
DANCE02,
@ -50,6 +51,13 @@ enum class ArmFSMValue{
UP
};
enum class TrajType{
MoveJ,
MoveL,
MoveC,
Stop
};
// 20 Byte
struct JointCmd{
float T;
@ -61,55 +69,51 @@ struct JointCmd{
// 16 Byte
struct JointState{
float buf[0];
float T;
float W;
float Acc;
float Pos;
};
// 140 Byte
union UDPSendCmd{
uint8_t checkCmd;
JointCmd jointCmd[7];
};
// 16*7=112 Byte
union UDPRecvState{
uint8_t singleState;
uint8_t selfCheck[10];
JointState jointState[7];
uint8_t errorCheck[16];
};
// 24 Byte
struct Posture{
float roll;
float pitch;
float yaw;
float x;
float y;
float z;
double roll;
double pitch;
double yaw;
double x;
double y;
double z;
};
// 48 Byte
struct MoveC{
Posture middlePosture;
Posture endPosture;
struct TrajCmd{
TrajType trajType;
Posture posture[2];
double gripperPos;
double maxSpeed;
double stopTime;
int trajOrder;
};
// 20*7=140 Byte
union ValueUnion{
Posture moveJ;
Posture moveL;
Posture moveC[2];
char teach[10];
char teachRepeat[10];
char saveState[10];
char toState[10];
char name[10];
JointCmd jointCmd[7];
TrajCmd trajCmd;
};
// 2+4+4+140 = 150 Byte
struct SendCmd{
uint8_t head[2];
ArmFSMState state;
@ -117,7 +121,6 @@ struct SendCmd{
ValueUnion valueUnion;
};
// 2+4+112+24 = 142 Byte
struct RecvState{
uint8_t head[2];
ArmFSMState state;

View File

@ -1,5 +1,5 @@
#ifndef _UNITREE_ARM_QUADRUPED_COMMON_H_
#define _UNITREE_ARM_QUADRUPED_COMMON_H_
#ifndef _UNITREE_ARM_B1_COMMON_H_
#define _UNITREE_ARM_B1_COMMON_H_
#include <stdint.h>
#include <array>
@ -206,7 +206,6 @@ namespace UNITREE_LEGGED_SDK
unsigned long long RecvCRCError; // total reveive CRC error
unsigned long long RecvLoseError; // total lose package count
} UDPState; // UDP communication state
}
#endif

View File

@ -4,9 +4,17 @@
#include <vector>
#include "unitree_arm_sdk/udp.h"
#include "unitree_arm_sdk/cmdPanel.h"
#include "unitree_arm_sdk/common/quadruped_common.h"
#include "unitree_arm_sdk/common/joystick_common.h"
#define CTRL_BY_ALIENGO_JOYSTICK
#ifdef CTRL_BY_ALIENGO_JOYSTICK
#include "unitree_arm_sdk/common/aliengo_common.h"
#else
#include "unitree_arm_sdk/common/b1_common.h"
#endif
using namespace UNITREE_LEGGED_SDK;
class UnitreeJoystick : public CmdPanel{

View File

@ -0,0 +1,99 @@
#ifndef MATHTYPES_H
#define MATHTYPES_H
#include <eigen3/Eigen/Dense>
/************************/
/******** Vector ********/
/************************/
// 2x1 Vector
using Vec2 = typename Eigen::Matrix<double, 2, 1>;
// 3x1 Vector
using Vec3 = typename Eigen::Matrix<double, 3, 1>;
// 4x1 Vector
using Vec4 = typename Eigen::Matrix<double, 4, 1>;
// 6x1 Vector
using Vec6 = typename Eigen::Matrix<double, 6, 1>;
// Quaternion
using Quat = typename Eigen::Matrix<double, 4, 1>;
// 4x1 Integer Vector
using VecInt4 = typename Eigen::Matrix<int, 4, 1>;
// 12x1 Vector
using Vec12 = typename Eigen::Matrix<double, 12, 1>;
// 18x1 Vector
using Vec18 = typename Eigen::Matrix<double, 18, 1>;
// Dynamic Length Vector
using VecX = typename Eigen::Matrix<double, Eigen::Dynamic, 1>;
/************************/
/******** Matrix ********/
/************************/
// Rotation Matrix
using RotMat = typename Eigen::Matrix<double, 3, 3>;
// Homogenous Matrix
using HomoMat = typename Eigen::Matrix<double, 4, 4>;
// 2x2 Matrix
using Mat2 = typename Eigen::Matrix<double, 2, 2>;
// 3x3 Matrix
using Mat3 = typename Eigen::Matrix<double, 3, 3>;
// 3x4 Matrix, each column is a 3x1 vector
using Vec34 = typename Eigen::Matrix<double, 3, 4>;
// 6x6 Matrix
using Mat6 = typename Eigen::Matrix<double, 6, 6>;
// 12x12 Matrix
using Mat12 = typename Eigen::Matrix<double, 12, 12>;
// 3x3 Identity Matrix
#define I3 Eigen::MatrixXd::Identity(3, 3)
// 6x6 Identity Matrix
#define I6 Eigen::MatrixXd::Identity(6, 6)
// 12x12 Identity Matrix
#define I12 Eigen::MatrixXd::Identity(12, 12)
// 18x18 Identity Matrix
#define I18 Eigen::MatrixXd::Identity(18, 18)
// Dynamic Size Matrix
using MatX = typename Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic>;
/************************/
/****** Functions *******/
/************************/
inline Vec34 vec12ToVec34(Vec12 vec12){
Vec34 vec34;
for(int i(0); i < 4; ++i){
vec34.col(i) = vec12.segment(3*i, 3);
}
return vec34;
}
inline Vec12 vec34ToVec12(Vec34 vec34){
Vec12 vec12;
for(int i(0); i < 4; ++i){
vec12.segment(3*i, 3) = vec34.col(i);
}
return vec12;
}
template<typename T>
inline VecX stdVecToEigenVec(T stdVec){
VecX eigenVec = Eigen::VectorXd::Map(&stdVec[0], stdVec.size());
return eigenVec;
}
#endif // MATHTYPES_H

View File

@ -10,6 +10,7 @@
#include <iostream>
#include <unistd.h>
#include <termios.h>
#include "unitree_arm_sdk/timer.h"
#include "unitree_arm_sdk/common/arm_motor_common.h"
@ -29,11 +30,13 @@ public:
virtual size_t recv(uint8_t *recvMsg) = 0;
virtual bool sendRecv(std::vector<MOTOR_send> &sendVec, std::vector<MOTOR_recv> &recvVec) = 0;
void resetIO(BlockYN blockYN, size_t recvLength, size_t timeOutUs);
bool isDisConnect;
protected:
BlockYN _blockYN = BlockYN::NO;
size_t _recvLength;
timeval _timeout;
timeval _timeoutSaved;
uint16_t _isDisConnectCnt;
};

View File

@ -4,10 +4,10 @@
#include "unitree_arm_sdk/timer.h"
#include "unitree_arm_sdk/common/arm_motor_common.h"
#include "unitree_arm_sdk/common/arm_common.h"
#include "unitree_arm_sdk/common/quadruped_common.h"
#include "unitree_arm_sdk/udp.h"
#include "unitree_arm_sdk/loop.h"
#include "unitree_arm_sdk/joystick.h"
#include "unitree_arm_sdk/keyboard.h"
#include "mathTypes.h"
#endif

Binary file not shown.

BIN
thirdparty/lcm-1.4.0.zip vendored Normal file

Binary file not shown.

134
unitreeArm/unitreeArm.cpp Normal file
View File

@ -0,0 +1,134 @@
#include "unitreeArm.h"
// constructor
// since the SDK communicates with z1_ctrl, the udp is set to the loopback address by default
unitreeArm::unitreeArm():_udp("127.0.0.1", 8071, 8072, sizeof(RecvState), BlockYN::NO, 500000) {
_sendCmd.head[0] = 0xFE;
_sendCmd.head[1] = 0xFF;
_udpThread = new LoopFunc("udp", 0.004, boost::bind(&unitreeArm::UDPSendRecv, this));
_udpThread->start();
}
unitreeArm::~unitreeArm() {
delete _udpThread;
}
// udp send and receive function
// it has created a thread in the constructor that used to automatically process the arm state and command datas
void unitreeArm::UDPSendRecv() {
_udp.send((uint8_t*)&_sendCmd, sizeof(SendCmd));
_udp.recv((uint8_t*)&_recvState, sizeof(RecvState));
}
// set current FSM to fsm, this is equivalent to key switching when using keyboard control
// input: fsm [the specific format can be viewed in class ArmFSMState ]
void unitreeArm::setFsm(ArmFSMState fsm) {
while (_recvState.state != fsm){
_sendCmd.state = fsm;
usleep(deltaTime);
}
}
void unitreeArm::backToStart() {
setFsm(ArmFSMState::BACKTOSTART);
//for those states that automatically transion to the joint space state, it's recommmanded to wait for it to finish
_sendCmd.state = ArmFSMState::INVALID;
while (_recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
}
// move the arm to the posture indicated by the label
// the specific label name can be viewed in savedArmStates.csv
void unitreeArm::labelRun(std::string label) {
while (_recvState.state != ArmFSMState::TOSTATE){
_sendCmd.state = ArmFSMState::TOSTATE;
strcpy(_sendCmd.valueUnion.name, label.c_str());
usleep(deltaTime);
}
_sendCmd.state = ArmFSMState::INVALID;
while (_recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
}
// save current posture to a label
// the label name should be less than 10 chars
void unitreeArm::labelSave(std::string label) {
_sendCmd.state = ArmFSMState::SAVESTATE;
strcpy(_sendCmd.valueUnion.name, label.c_str());
while (_recvState.state != ArmFSMState::SAVESTATE){
usleep(deltaTime);
}
}
// reach the target posture by directly moving the joint
void unitreeArm::MoveJ(Vec6 moveJCmd) {
_sendCmd.valueUnion.trajCmd.posture[0] = Vec6toPosture(moveJCmd);
_sendCmd.state = ArmFSMState::MOVEJ;
while (_recvState.state != ArmFSMState::MOVEJ){
usleep(deltaTime);
}
_sendCmd.state = ArmFSMState::INVALID;
while (_recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
}
// reach the target posture by directly moving the joint
void unitreeArm::MoveJ(Vec6 moveJCmd, double gripperPos) {
_sendCmd.valueUnion.jointCmd[6].Pos = gripperPos;
MoveJ(moveJCmd);
}
// the end effector reaches the target point in a straight line trajectory
void unitreeArm::MoveL(Vec6 moveLCmd) {
_sendCmd.valueUnion.trajCmd.posture[0] = Vec6toPosture(moveLCmd);
_sendCmd.state = ArmFSMState::MOVEL;
while (_recvState.state != ArmFSMState::MOVEL){
usleep(deltaTime);
}
_sendCmd.state = ArmFSMState::INVALID;
while (_recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
}
// the end effector reaches the target point in a circular arc trajectory
void unitreeArm::MoveC(Vec6 middleP, Vec6 endP){
_sendCmd.valueUnion.trajCmd.posture[0] = Vec6toPosture(middleP);
_sendCmd.valueUnion.trajCmd.posture[1] = Vec6toPosture(endP);
_sendCmd.state = ArmFSMState::MOVEC;
while (_recvState.state != ArmFSMState::MOVEC){
usleep(deltaTime);
}
_sendCmd.state = ArmFSMState::INVALID;
while (_recvState.state != ArmFSMState::JOINTCTRL){
usleep(deltaTime);
}
}
void unitreeArm::getJointState(JointState* jointState) {
for(int i=0;i<7;i++) {
jointState[i] = _recvState.jointState[i];
}
}
void unitreeArm::getGripperState(Posture& gripperState) {
gripperState = _recvState.cartesianState;
}
void unitreeArm::setTraj(TrajCmd trajCmd){
if(_recvState.state != ArmFSMState::SETTRAJ){
_sendCmd.valueUnion.trajCmd.trajOrder = 0;
setFsm(ArmFSMState::SETTRAJ);
}
if(_sendCmd.valueUnion.trajCmd.trajOrder == (trajCmd.trajOrder - 1)){// make sure [order] is sequential
_sendCmd.valueUnion.trajCmd = trajCmd;
}
}

58
unitreeArm/unitreeArm.h Normal file
View File

@ -0,0 +1,58 @@
#ifndef __UNITREEARM_H
#define __UNITREEARM_H
#include <iostream>
#include "unitree_arm_sdk/unitree_arm_sdk.h"
Vec6 PosturetoVec6(const Posture p){
Vec6 posture;
posture(0) = p.roll;
posture(1) = p.pitch;
posture(2) = p.yaw;
posture(3) = p.x;
posture(4) = p.y;
posture(5) = p.z;
return posture;
}
Posture Vec6toPosture(const Vec6 p){
Posture posture;
posture.roll = p(0);
posture.pitch = p(1);
posture.yaw = p(2);
posture.x = p(3);
posture.y = p(4);
posture.z = p(5);
return posture;
}
class unitreeArm{
public:
unitreeArm();
~unitreeArm();
void UDPSendRecv();
void InitCmdData(SendCmd& sendCmd);
void setFsm(ArmFSMState fsm);
void backToStart();
void labelRun(std::string label);
void labelSave(std::string label);
void MoveJ(Vec6 moveJCmd);
void MoveJ(Vec6 moveJCmd, double gripperPos);
void MoveL(Vec6 moveLCmd);
void MoveC(Vec6 middleP, Vec6 endP);
void getJointState(JointState* jointstate);
void getGripperState(Posture& gripperState);
void setTraj(TrajCmd trajCmd);
RecvState _recvState; // the arm state receive from udp
JointState _jointState[7]; // 6 joint angles and one gripper angle
SendCmd _sendCmd; // command to control the arm
TrajCmd _trajCmd;
private:
UDPPort _udp;
float deltaTime = 4000; //us
LoopFunc *_udpThread;
};
#endif