add joystick support of low_state.wireless_remote()

This commit is contained in:
yangning wu 2024-06-17 10:38:08 +08:00
parent c8df8aaaf7
commit 030472693c
6 changed files with 127 additions and 21 deletions

View File

@ -29,9 +29,9 @@ input("Press enter to start")
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) <2: if len(sys.argv) <2:
ChannelFactortyInitialize(1, "lo") ChannelFactoryInitialize(1, "lo")
else: else:
ChannelFactortyInitialize(0, sys.argv[1]) ChannelFactoryInitialize(0, sys.argv[1])
# Create a publisher to publish the data defined in UserData class # Create a publisher to publish the data defined in UserData class
pub = ChannelPublisher("rt/lowcmd", LowCmd_) pub = ChannelPublisher("rt/lowcmd", LowCmd_)

View File

@ -60,7 +60,7 @@ sudo apt install libyaml-cpp-dev
``` ```
### 2. Compile unitree_mujoco ### 2. Compile unitree_mujoco
```bash ```bash
cd simulate/ cd unitree_mujoco/simulate
mkdir build && cd build mkdir build && cd build
cmake .. cmake ..
make -j4 make -j4

View File

@ -67,6 +67,34 @@ void UnitreeSdk2Bridge::PublishLowState()
low_state.imu_state().accelerometer()[2] = mj_data_->sensordata[dim_motor_sensor_ + 9]; low_state.imu_state().accelerometer()[2] = mj_data_->sensordata[dim_motor_sensor_ + 9];
} }
if (js_)
{
js_->getState();
wireless_remote_.btn.components.R1 = js_->button_[js_id_.button["RB"]];
wireless_remote_.btn.components.L1 = js_->button_[js_id_.button["LB"]];
wireless_remote_.btn.components.start = js_->button_[js_id_.button["START"]];
wireless_remote_.btn.components.select = js_->button_[js_id_.button["SELECT"]];
wireless_remote_.btn.components.R2 = (js_->axis_[js_id_.axis["RT"]] > 0);
wireless_remote_.btn.components.L2 = (js_->axis_[js_id_.axis["LT"]] > 0);
wireless_remote_.btn.components.F1 = 0;
wireless_remote_.btn.components.F2 = 0;
wireless_remote_.btn.components.A = js_->button_[js_id_.button["A"]];
wireless_remote_.btn.components.B = js_->button_[js_id_.button["B"]];
wireless_remote_.btn.components.X = js_->button_[js_id_.button["X"]];
wireless_remote_.btn.components.Y = js_->button_[js_id_.button["Y"]];
wireless_remote_.btn.components.up = (js_->axis_[js_id_.axis["DY"]] < 0);
wireless_remote_.btn.components.right = (js_->axis_[js_id_.axis["DX"]] > 0);
wireless_remote_.btn.components.down = (js_->axis_[js_id_.axis["DY"]] > 0);
wireless_remote_.btn.components.left = (js_->axis_[js_id_.axis["DX"]] < 0);
wireless_remote_.lx = double(js_->axis_[js_id_.axis["LX"]]) / max_value_;
wireless_remote_.ly = -double(js_->axis_[js_id_.axis["LY"]]) / max_value_;
wireless_remote_.rx = double(js_->axis_[js_id_.axis["RX"]]) / max_value_;
wireless_remote_.ry = -double(js_->axis_[js_id_.axis["RY"]]) / max_value_;
memcpy(&low_state.wireless_remote()[0], &wireless_remote_, 40);
}
low_state_puber_->Write(low_state); low_state_puber_->Write(low_state);
} }
} }

View File

@ -48,6 +48,19 @@ typedef union
uint16_t value; uint16_t value;
} xKeySwitchUnion; } xKeySwitchUnion;
typedef struct
{
uint8_t head[2];
xKeySwitchUnion btn;
float lx;
float rx;
float ry;
float L2;
float ly;
uint8_t idle[16];
} xRockerBtnDataStruct;
// Defaults to xbox gamepad // Defaults to xbox gamepad
struct JoystickId struct JoystickId
{ {
@ -106,7 +119,9 @@ public:
ThreadPtr HighStatePuberThreadPtr; ThreadPtr HighStatePuberThreadPtr;
ThreadPtr WirelessControllerPuberThreadPtr; ThreadPtr WirelessControllerPuberThreadPtr;
xKeySwitchUnion dds_keys_; xKeySwitchUnion dds_keys_ = {};
xRockerBtnDataStruct wireless_remote_ = {};
JoystickId js_id_; JoystickId js_id_;
Joystick *js_; Joystick *js_;
int max_value_ = (1 << 15); // 16 bits joystick int max_value_ = (1 << 15); // 16 bits joystick

View File

@ -21,7 +21,7 @@ def LowStateHandler(msg: LowState_):
if __name__ == "__main__": if __name__ == "__main__":
ChannelFactortyInitialize(1, "lo") ChannelFactoryInitialize(1, "lo")
hight_state_suber = ChannelSubscriber("rt/sportmodestate", SportModeState_) hight_state_suber = ChannelSubscriber("rt/sportmodestate", SportModeState_)
low_state_suber = ChannelSubscriber("rt/lowstate", LowState_) low_state_suber = ChannelSubscriber("rt/lowstate", LowState_)

View File

@ -2,6 +2,7 @@ import mujoco
import numpy as np import numpy as np
import pygame import pygame
import sys import sys
import struct
from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelPublisher from unitree_sdk2py.core.channel import ChannelSubscriber, ChannelPublisher
from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowCmd_ from unitree_sdk2py.idl.unitree_go.msg.dds_ import LowCmd_
@ -34,6 +35,8 @@ class UnitreeSdk2Bridge:
self.have_frame_sensor = False self.have_frame_sensor = False
self.dt = self.mj_model.opt.timestep self.dt = self.mj_model.opt.timestep
self.joystick = None
# Check sensor # Check sensor
for i in range(self.dim_motor_sensor, self.mj_model.nsensor): for i in range(self.dim_motor_sensor, self.mj_model.nsensor):
name = mujoco.mj_id2name( name = mujoco.mj_id2name(
@ -44,7 +47,6 @@ class UnitreeSdk2Bridge:
if name == "frame_pos": if name == "frame_pos":
self.have_frame_sensor_ = True self.have_frame_sensor_ = True
# Unitree sdk2 message # Unitree sdk2 message
self.low_state = unitree_go_msg_dds__LowState_() self.low_state = unitree_go_msg_dds__LowState_()
self.low_state_puber = ChannelPublisher(TOPIC_LOWSTATE, LowState_) self.low_state_puber = ChannelPublisher(TOPIC_LOWSTATE, LowState_)
@ -97,9 +99,6 @@ class UnitreeSdk2Bridge:
"left": 15, "left": 15,
} }
self.joystick = None
def LowCmdHandler(self, msg: LowCmd_): def LowCmdHandler(self, msg: LowCmd_):
if self.mj_data != None: if self.mj_data != None:
for i in range(self.num_motor): for i in range(self.num_motor):
@ -160,6 +159,58 @@ class UnitreeSdk2Bridge:
self.dim_motor_sensor + 9 self.dim_motor_sensor + 9
] ]
if self.joystick != None:
pygame.event.get()
# Buttons
self.low_state.wireless_remote[2] = int(
"".join(
[
f"{key}"
for key in [
0,
0,
int(self.joystick.get_axis(self.axis_id["LT"]) > 0),
int(self.joystick.get_axis(self.axis_id["RT"]) > 0),
int(self.joystick.get_button(self.button_id["SELECT"])),
int(self.joystick.get_button(self.button_id["START"])),
int(self.joystick.get_button(self.button_id["LB"])),
int(self.joystick.get_button(self.button_id["RB"])),
]
]
),
2,
)
self.low_state.wireless_remote[3] = int(
"".join(
[
f"{key}"
for key in [
int(self.joystick.get_hat(0)[0] < 0), # left
int(self.joystick.get_hat(0)[1] < 0), # down
int(self.joystick.get_hat(0)[0] > 0), # right
int(self.joystick.get_hat(0)[1] > 0), # up
int(self.joystick.get_button(self.button_id["Y"])), # Y
int(self.joystick.get_button(self.button_id["X"])), # X
int(self.joystick.get_button(self.button_id["B"])), # B
int(self.joystick.get_button(self.button_id["A"])), # A
]
]
),
2,
)
# Axes
sticks = [
self.joystick.get_axis(self.axis_id["LX"]),
self.joystick.get_axis(self.axis_id["RX"]),
-self.joystick.get_axis(self.axis_id["RY"]),
-self.joystick.get_axis(self.axis_id["LY"]),
]
packs = list(map(lambda x: struct.pack("f", x), sticks))
self.low_state.wireless_remote[4:8] = packs[0]
self.low_state.wireless_remote[8:12] = packs[1]
self.low_state.wireless_remote[12:16] = packs[2]
self.low_state.wireless_remote[20:24] = packs[3]
self.low_state_puber.Write(self.low_state) self.low_state_puber.Write(self.low_state)
def PublishHighState(self): def PublishHighState(self):
@ -190,23 +241,35 @@ class UnitreeSdk2Bridge:
def PublishWirelessController(self): def PublishWirelessController(self):
if self.joystick != None: if self.joystick != None:
pygame.event.get() pygame.event.get()
key_state = [0]*16 key_state = [0] * 16
key_state[self.key_map["R1"]] = self.joystick.get_button(self.button_id["RB"]) key_state[self.key_map["R1"]] = self.joystick.get_button(
key_state[self.key_map["L1"]] = self.joystick.get_button(self.button_id["LB"]) self.button_id["RB"]
key_state[self.key_map["start"]] = self.joystick.get_button(self.button_id["START"]) )
key_state[self.key_map["select"]] = self.joystick.get_button(self.button_id["SELECT"]) key_state[self.key_map["L1"]] = self.joystick.get_button(
key_state[self.key_map["R2"]] = (self.joystick.get_axis(self.axis_id["RT"])>0) self.button_id["LB"]
key_state[self.key_map["L2"]] = (self.joystick.get_axis(self.axis_id["LT"])>0) )
key_state[self.key_map["start"]] = self.joystick.get_button(
self.button_id["START"]
)
key_state[self.key_map["select"]] = self.joystick.get_button(
self.button_id["SELECT"]
)
key_state[self.key_map["R2"]] = (
self.joystick.get_axis(self.axis_id["RT"]) > 0
)
key_state[self.key_map["L2"]] = (
self.joystick.get_axis(self.axis_id["LT"]) > 0
)
key_state[self.key_map["F1"]] = 0 key_state[self.key_map["F1"]] = 0
key_state[self.key_map["F2"]] = 0 key_state[self.key_map["F2"]] = 0
key_state[self.key_map["A"]] = self.joystick.get_button(self.button_id["A"]) key_state[self.key_map["A"]] = self.joystick.get_button(self.button_id["A"])
key_state[self.key_map["B"]] = self.joystick.get_button(self.button_id["B"]) key_state[self.key_map["B"]] = self.joystick.get_button(self.button_id["B"])
key_state[self.key_map["X"]] = self.joystick.get_button(self.button_id["X"]) key_state[self.key_map["X"]] = self.joystick.get_button(self.button_id["X"])
key_state[self.key_map["Y"]] = self.joystick.get_button(self.button_id["Y"]) key_state[self.key_map["Y"]] = self.joystick.get_button(self.button_id["Y"])
key_state[self.key_map["up"]] = (self.joystick.get_hat(0)[1]>0) key_state[self.key_map["up"]] = self.joystick.get_hat(0)[1] > 0
key_state[self.key_map["right"]] = (self.joystick.get_hat(0)[0]>0) key_state[self.key_map["right"]] = self.joystick.get_hat(0)[0] > 0
key_state[self.key_map["down"]] = (self.joystick.get_hat(0)[1]<0) key_state[self.key_map["down"]] = self.joystick.get_hat(0)[1] < 0
key_state[self.key_map["left"]] = (self.joystick.get_hat(0)[0]<0) key_state[self.key_map["left"]] = self.joystick.get_hat(0)[0] < 0
key_value = 0 key_value = 0
for i in range(16): for i in range(16):