Household chores often feel repetitive and time-consuming, and laundry folding is no exception. While robotic vacuum cleaners have already become part of many households, folding clothes remains a task where dexterity, perception, and human-like motion are required. Our project explores how a wheeled humanoid service robot combined with an exoskeleton controller can bring automation closer to daily life by tackling this very task: folding laundry.
Mercury X1 Humanoid RobotThe design of the Mercury X1 wheeled humanoid robot is driven by the current demands in technology education and research. The Mercury X1 is engineered to address these challenges, delivering a solution that combines adaptability with accuracy and is capable of supporting a wide range of application scenarios.
The Mercury X1 wheeled humanoid robot has a total of 19 degrees of freedom and is composed of and a high-performance mobile base, the whole machine is equipped with Jetson Orin Nano SUPER 8GB as main controller, which make it very practical and high performance.
With force control capability, the myGripper F100 provides an adjustable stroke of 0–100 mm (default fingertip gap) and supports multiple torque levels to meet diverse gripping force needs. Designed for accuracy, it offers a rated payload of 500 g and repeatable positioning within ±0.5 mm. This makes it an ideal choice for a wide range of robotic gripping operations, ensuring both consistency and adaptability in dynamic automation scenarios.
The myController S570 is highly compatible and easily adapting to the widely used collaborative robots in industrial applications. Its lightweight exoskeleton ensures easy portability, while supporting up to 14 degrees of freedom(DOF). Equipped with 2 joysticks and 2 buttons, it is well-suited for remote operation, research on unmanned tasks, and data acquisition, making it an ideal tool for industrial automation and workstation setup.
1. Robot Arm Initialization
Copy this code to the robot via USB or remote control software and name it "init.py". Executing this code will adjust the robot arm's posture to the one suitable for installing the gripper.
from pymycobot import Mercury
ml = Mercury('/dev/left_arm')
mr = Mercury('/dev/right_arm')
# enable first
ml.power_on()
mr.power_on()
print(ml.get_angles())
print(mr.get_angles())
ml.send_angles([-8, 30, 6, -50, 105, 175, 86.74], 40)
mr.send_angles([8,30, 0, -50, -103, 175, 45], 40)
# When install the gripper or start to use remote controlling, please init the robot pose firstly
In order to make the gripper point downwards when the hand is downwards, we need to install the connector perpendicular to the Joint 7.
2. Exoskeleton controller connection
Use a cable longer than 2 meters to connect the exoskeleton and the X1 robot, and install the wearable accessories.
3. Copy the code
Copy this code to /home/Mercury and rename the code file to "remote_control.py"
import threading
from pymycobot import Mercury
import time
from pymycobot import Exoskeleton
import os
os.system("sudo chmod 777 /dev/ttyACM*")
# before using the code check the myController port name by "ls /dev/ttyACM*"
obj = Exoskeleton(port="/dev/ttyACM4")
ml = Mercury("/dev/left_arm")
mr = Mercury("/dev/right_arm")
l_control_mode = 1
r_control_mode = 1
l_last_mode = 0
r_last_mode = 0
# set control type
ml.set_movement_type(3)
mr.set_movement_type(3)
ml.set_vr_mode(1)
mr.set_vr_mode(1)
def jointlimit_left(angles):
max = [15, 70, 40, -20, 175, 220, 200]
min = [-15, 10, -40, -70, -175, 80, 50]
for i in range(7):
if angles[i] > max[i]:
angles[i] = max[i]
if angles[i] < min[i]:
angles[i] = min[i]
def jointlimit_right(angles):
max = [45, 70, 40, -20, 175, 180, 180]
min = [-15, 10, -40, -70, -175, 80, 30]
for i in range(7):
if angles[i] > max[i]:
angles[i] = max[i]
if angles[i] < min[i]:
angles[i] = min[i]
def gripper_control_open(mc):
mc.set_pro_gripper_angle(14, 80)
def gripper_control_close(mc):
mc.set_pro_gripper_angle(14, 0)
# 1 left arm ,2 right arm
def control_arm(arm):
global l_control_mode, l_last_mode, r_control_mode, r_last_mode
st = 0
while True:
try:
if arm == 1:
arm_data = obj.get_arm_data(1)
#print("l: ", arm_data)
mc = ml
elif arm == 2:
arm_data = obj.get_arm_data(2)
#print("r: ", arm_data)
mc = mr
else:
raise ValueError("error arm")
time_err = 1000 * (time.time() - st)
st = time.time()
if arm == 1: #left arm
#align the robot - angle - myController relationship
mercury_list = [
arm_data[0], -arm_data[1], arm_data[2], -arm_data[3], arm_data[4],240 + arm_data[5]*0.5, arm_data[6] + 160]
# limit joint angle
jointlimit_left(mercury_list)
if arm_data[7] == 0 and l_last_mode == 0:
print(6)
l_last_mode = 1
l_control_mode += 1
if l_control_mode > 3:
l_control_mode = 1
if l_control_mode == 1:
obj.set_color(arm, 0, 255, 0)
elif l_control_mode == 2:
obj.set_color(arm, 0, 0, 255)
else:
obj.set_color(arm, 255, 0, 0)
if arm_data[7] == 1:
l_last_mode = 0
if l_control_mode == 1:
TI = 10
elif l_control_mode == 2:
TI = 5
else:
TI = 3
if arm_data[9] == 0:
threading.Thread(target=gripper_control_close, args=(mc,)).start()
print("===== gripper close ============")
elif arm_data[10] == 0:
threading.Thread(target=gripper_control_open, args=(mc,)).start()
print("===== gripper open ============")
else: # right arm
# align the robot pose by testing ( you can modify by yourself again )
mercury_list = [
arm_data[0], -arm_data[1], arm_data[2], -arm_data[3], arm_data[4],200 + arm_data[5]*0.8, arm_data[6] + 80]
# limit the joint angle ( you can modify by yourself again )
jointlimit_right(mercury_list)
if arm_data[7] == 0 and r_last_mode == 0:
print(6)
r_last_mode = 1
r_control_mode += 1
if r_control_mode > 3:
r_control_mode = 1
if r_control_mode == 1:
obj.set_color(arm, 0, 255, 0)
elif r_control_mode == 2:
obj.set_color(arm, 0, 0, 255)
else:
obj.set_color(arm, 255, 0, 0)
if arm_data[7] == 1:
r_last_mode = 0
if r_control_mode == 1:
TI = 10
elif r_control_mode == 2:
TI = 5
else:
TI = 3
if arm_data[9] == 0:
threading.Thread(target=gripper_control_close, args=(mc,)).start()
print("===== gripper close ============")
elif arm_data[10] == 0:
threading.Thread(target=gripper_control_open, args=(mc,)).start()
print("===== gripper open ============")
if arm_data[9] == 0 and arm_data[10] == 0:
time.sleep(0.01)
continue
print(arm)
print(mercury_list)
mc.send_angles(mercury_list, TI, _async=True)
time.sleep(0.01)
except Exception as e:
print(e)
pass
time.sleep(10)
# left arm
threading.Thread(target=control_arm, args=(1,)).start()
# right arm
threading.Thread(target=control_arm, args=(2,)).start()
4. Confirm the serial port
ls /dev/ttyACM*
bash
cd /home/Mercury
python remote_control.py
Looking ahead, several directions are promising:
● Learning from Demonstration: Using the teleoperation data to teach the robot folding autonomously.
● Improved Grippers: Designing soft, adaptive grippers for more reliable cloth handling.
● Shared Autonomy: Blending human teleoperation with AI-based assistance, where the robot helps stabilize and align the garment automatically.
ConclusionFolding laundry may seem mundane, but it represents a deeper challenge in robotics: combining perception, dexterity, and intuitive control to manage complex, flexible objects. By pairing a wheeled humanoid robot with an exoskeleton controller, we took a step toward making service robots more practical in household environments.
Far from being just a showcase for exhibitions, this project illustrates how human-robot synergy can transform routine chores into testbeds for advanced robotics research.
Comments