Tài liệu phát triển SDK khung dẫn đường Tbot 3D

Dựa trên giao thức rosbridge WebSocket: không cần môi trường ROS, điều khiển khung xe đa ngôn ngữ. Tài liệu này liệt kê đầy đủ trường request/response của mỗi Topic / Service (kiểu dữ liệu + mô tả).

Kết nối:ws://192.168.1.151:9090
Bao phản hồi chung:Mỗi lần gọi Service, rosbridge trả về một service_response. JSON trong cột "response" dưới đây chính là nội dung values.

1. Tổng quan giao thức

HướngSố lượngTên
Đăng ký Topic (khung → ứng dụng)5/fast_lio_localization、/aft_pgo_path、/map_list_kitty、/ebot_goal_status_local_planner、/ebot_work_state
Gọi Service (ứng dụng → khung)9/start_mapping_kitty、/save_map_kitty、/select_map_and_start_kitty、/delete_map_kitty、/docking_kitty、/navigate_to_pose(điều hướng + hủy)、/add_goal_kitty、/delete_goal_kitty

2. Đăng ký Topic (khung → ứng dụng)

Đăng ký. Tin nhận nằm ở trường msg.

3. Bảng tổng hợp Service

ServiceLoại dịch vụTrường chính
/start_mapping_kittystd_srvs/TriggerYêu cầu rỗng → success,message
/save_map_kittykitty_runtime_manager/SaveMapfilepath → success,message
/select_map_and_start_kittykitty_runtime_manager/SaveMapfilepath → success,message
/delete_map_kittykitty_runtime_manager/DeleteMapmap_name → success,message
/docking_kittystd_srvs/TriggerYêu cầu rỗng → success,message
/navigate_to_posenav_msgs/GetPlangoal.pose.position.x/y/z → plan.poses[]
/add_goal_kittykitty_runtime_manager/AddGoalmap_name,goal_name,x,y,theta → success,message
/delete_goal_kittykitty_runtime_manager/DeleteGoalmap_name,goal_name → success,message

2.1 Định vị robot nav_msgs/Odometry

Khung định kỳ gửi tư thế hiện tại.

msg nhận được:
{
  "pose": { "pose": {
    "position": {"x": 1.23, "y": 4.56, "z": 0.0},
    "orientation": {"x": 0, "y": 0, "z": 0.5, "w": 0.866}
  }}
}
TrườngKiểuMô tả
pose.pose.position.xfloat64Tọa độ x robot (mét)
pose.pose.position.yfloat64Tọa độ y robot (mét)
pose.pose.position.zfloat64Tọa độ z robot (mét, khung cố định 0)
pose.pose.orientation.x/y/z/wfloat64Hướng quaternion; frontend dùng yaw = atan2(2*(w*z+x*y), 1-2*(z*z+y*y)) đổi ra góc radian

2.2 Đường toàn cục nav_msgs/Path

Sau khi bắt đầu dẫn đường gửi mỗi 5 giây, tổng 5 lần (khoảng 30 giây).

msg nhận được:
{ "poses": [
  {"pose":{"position":{"x":0,"y":0,"z":0}}},
  {"pose":{"position":{"x":1,"y":2,"z":0}}}
]}
TrườngKiểuMô tả
posesarray[PoseStamped]Mảng điểm đường đi
poses[].pose.position.xfloat64Tọa độ x điểm đường (mét)
poses[].pose.position.yfloat64Tọa độ y điểm đường (mét)
poses[].pose.position.zfloat64Tọa độ z điểm đường (khung luôn 0)

2.3 Danh sách bản đồ kitty_runtime_manager/MapList

Sau khi đăng ký trả về tất cả bản đồ và điểm mục tiêu đã lưu.

msg nhận được:
{ "maps": [
  {"map_name":"Lobby","map_path":"/maps/floor1",
   "goals":[
     {"name":"Reception","x":1.0,"y":2.0,"theta":0.5},
     {"name":"Elevator","x":3.0,"y":4.0,"theta":1.2}
   ]}
]}
TrườngKiểuMô tả
mapsarray[Map]Mảng bản đồ
maps[].map_namestringTên hiển thị bản đồ
maps[].map_pathstringĐường dẫn file bản đồ (nội bộ)
maps[].goalsarray[Goal]Điểm mục tiêu đã lưu của bản đồ này
maps[].goals[].namestringTên điểm mục tiêu
maps[].goals[].xfloat64x điểm mục tiêu (mét)
maps[].goals[].yfloat64y điểm mục tiêu (mét)
maps[].goals[].thetafloat64Hướng điểm mục tiêu (radian)

2.4 Trạng thái dẫn đường std_msgs/Float64MultiArray

Topic: /ebot_goal_status_local_planner.

msg nhận được:{"data": [1]}
TrườngKiểuMô tả
data[0]float641 = đã tới đích; 0 = chưa tới. Ở chế độ docking chỉ báo 1 khi sạc thật sự.

2.5 Pin và trạng thái sạc std_msgs/Float64MultiArray

Topic: /ebot_work_state.

msg nhận được:{"data": [2, 75.5]}
TrườngKiểuMô tả
data[0]float64Trạng thái sạc: 1=sạc 2=không sạc
data[1]float64Phần trăm pin (0~100)

3.1 Bắt đầu dựng bản đồ std_srvs/Trigger

Service:/start_mapping_kitty

Yêu cầu:
{}
(Yêu cầu rỗng)
Giá trị phản hồi:
{ "success": true, "message": "Mapping started" }
TrườngKiểuHướngMô tả
successboolPhản hồiThao tác thành công hay không
messagestringPhản hồiThông tin kết quả (lý do khi thất bại)

3.2 Lưu bản đồ kitty_runtime_manager/SaveMap

Service:/save_map_kitty

Yêu cầu:
{ "filepath": "map_name" }
Giá trị phản hồi:
{ "success": true, "message": "Map saved" }
TrườngKiểuHướngMô tả
filepathstringYêu cầumap_name (không kèm đường dẫn)
successboolPhản hồiThao tác thành công hay không
messagestringPhản hồiThông tin kết quả

3.3 Chọn bản đồ và bắt đầu dẫn đường kitty_runtime_manager/SaveMap

Service:/select_map_and_start_kitty

Yêu cầu:
{ "filepath": "map_name" }
Giá trị phản hồi:
{ "success": true, "message": "Map selected and navigation started" }
TrườngKiểuHướngMô tả
filepathstringYêu cầumap_name (không kèm đường dẫn)
successboolPhản hồiThao tác thành công hay không
messagestringPhản hồiThông tin kết quả

3.4 Xóa bản đồ kitty_runtime_manager/DeleteMap

Service:/delete_map_kitty

Yêu cầu:
{ "map_name": "map_name" }
Giá trị phản hồi:
{ "success": true, "message": "Deleted successfully" }
TrườngKiểuHướngMô tả
map_namestringYêu cầumap_name cần xóa
successboolPhản hồiThao tác thành công hay không
messagestringPhản hồiThông tin kết quả

3.5 Về trạm sạc std_srvs/Trigger

Service:/docking_kitty

Yêu cầu:
{}
Giá trị phản hồi:
{ "success": true, "message": "Docking started" }
TrườngKiểuHướngMô tả
successboolPhản hồiThao tác thành công hay không (chỉ nghĩa là quá trình Docking đã khởi động, chưa chắc đã sạc)
messagestringPhản hồiThông tin kết quả

3.6 Dẫn đường đến điểm mục tiêu nav_msgs/GetPlan

Service:/navigate_to_pose

Yêu cầu:
{
  "goal": { "pose": { "position": { "x": 1.0, "y": 2.0, "z": 0.0 } } }
}
Giá trị phản hồi:
{ "plan": { "poses": [
  {"pose":{"position":{"x":0,"y":0,"z":0}}},
  {"pose":{"position":{"x":1,"y":2,"z":0}}}
]}}
TrườngKiểuHướngMô tả
goal.pose.position.xfloat64Yêu cầux điểm mục tiêu (mét)
goal.pose.position.yfloat64Yêu cầuy điểm mục tiêu (mét)
goal.pose.position.zfloat64Yêu cầuz điểm mục tiêu (khung luôn 0)
plan.posesarray[PoseStamped]Phản hồiMảng điểm đường đã quy hoạch (frontend có thể vẽ đường)
Lưu ý:Để biết có thực sự đến, đừng nhìn phản hồi này — hãy đăng ký ebot_goal_status và nhận data[0]==1.

3.7 Hủy dẫn đường nav_msgs/GetPlan

Service:/navigate_to_pose((Cùng dịch vụ với dẫn đường, phân biệt bằng tọa độ đặc biệt))

Yêu cầu:
{
  "goal": { "pose": { "position": { "x": 999999, "y": 888888, "z": 0 } } }
}
Giá trị phản hồi:
{ "plan": { "poses": [] } }
TrườngKiểuHướngMô tả
goal.pose.position.xfloat64Yêu cầuCố định 999999 (cờ hủy)
goal.pose.position.yfloat64Yêu cầuCố định 888888 (cờ hủy)
goal.pose.position.zfloat64Yêu cầuCố định 0
plan.posesarrayPhản hồiĐường trống hoặc bị cắt

3.8 Thêm điểm mục tiêu kitty_runtime_manager/AddGoal

Service:/add_goal_kitty

Yêu cầu:
{
  "map_name": "Lobby",
  "goal_name": "Reception",
  "x": 1.0, "y": 2.0, "theta": 0.5
}
Giá trị phản hồi:
{ "success": true, "message": "Added successfully" }
TrườngKiểuHướngMô tả
map_namestringYêu cầumap_name
goal_namestringYêu cầuTên điểm mục tiêu
xfloat64Yêu cầux điểm mục tiêu (mét)
yfloat64Yêu cầuy điểm mục tiêu (mét)
thetafloat64Yêu cầuGóc hướng (radian)
successboolPhản hồiThao tác thành công hay không
messagestringPhản hồiThông tin kết quả

3.9 Xóa điểm mục tiêu kitty_runtime_manager/DeleteGoal

Service:/delete_goal_kitty

Yêu cầu:
{ "map_name": "Lobby", "goal_name": "Reception" }
Giá trị phản hồi:
{ "success": true, "message": "Deleted successfully" }
TrườngKiểuHướngMô tả
map_namestringYêu cầumap_name
goal_namestringYêu cầuTên điểm mục tiêu
successboolPhản hồiThao tác thành công hay không
messagestringPhản hồiThông tin kết quả

4. Ví dụ phát triển đa ngôn ngữ

Mỗi ngôn ngữ mặc định hiển thị ví dụ nhanh (kết nối + đăng ký đọc pin + docking về sạc), bấm "Xem toàn bộ mã" để mở demo đầy đủ 5 Topic + 9 Service.

4.1 Python(roslibpy)

Phụ thuộc:pip install roslibpy

import roslibpy, time
client = roslibpy.Ros(host='192.168.1.151', port=9090)
client.run()

# Subscribe to battery state
roslibpy.Topic(client,'/ebot_work_state','std_msgs/Float64MultiArray').subscribe(
    lambda m: print(f"Battery {m['data'][1]}% charging={m['data'][0]==1}"))
# Dock to charger
roslibpy.Service(client,'/docking_kitty','std_srvs/Trigger').call(roslibpy.ServiceRequest(),
    callback=lambda r: print("Docking:", r['message']))
try:
    while True: time.sleep(1)
except KeyboardInterrupt: client.terminate()
import roslibpy, time, math
client = roslibpy.Ros(host='192.168.1.151', port=9090)
client.run()

# ===== Subscribe to all 5 Topics =====
# 1) Localization
def on_odom(m):
    p = m['pose']['pose']['position']; o = m['pose']['pose']['orientation']
    yaw = math.atan2(2*(o['w']*o['z']+o['x']*o['y']), 1-2*(o['z']**2+o['y']**2))
    print(f"[Pose] x={p['x']:.2f} y={p['y']:.2f} yaw={math.degrees(yaw):.1f}°")
roslibpy.Topic(client,'/fast_lio_localization','nav_msgs/Odometry').subscribe(on_odom)
# 2) Global path
roslibpy.Topic(client,'/aft_pgo_path','nav_msgs/Path').subscribe(
    lambda m: print(f"[Path] {len(m['poses'])}  points"))
# 3) Map list
roslibpy.Topic(client,'/map_list_kitty','kitty_runtime_manager/MapList').subscribe(
    lambda m: [print(f"[Map] {mp['map_name']}  goals:{[g['name'] for g in mp['goals']]}") for mp in m['maps']])
# 4) Navigation status
roslibpy.Topic(client,'/ebot_goal_status_local_planner','std_msgs/Float64MultiArray').subscribe(
    lambda m: m['data'][0]==1 and print("✅ Arrived"))
# 5) Battery
roslibpy.Topic(client,'/ebot_work_state','std_msgs/Float64MultiArray').subscribe(
    lambda m: print(f"[Battery] {m['data'][1]:.0f}% {'Charging' if m['data'][0]==1 else 'Not charging'}"))

# ===== Call all 9 Services =====
def call(svc, args, srv):
    r = roslibpy.Service(client, svc, srv).call(roslibpy.ServiceRequest(args))
    print(f"[SVC] {svc} → {dict(r)}")
time.sleep(1)
call('/start_mapping_kitty', {}, 'std_srvs/Trigger')
call('/save_map_kitty', {'filepath':'test_map'}, 'kitty_runtime_manager/SaveMap')
call('/select_map_and_start_kitty', {'filepath':'test_map'}, 'kitty_runtime_manager/SaveMap')
call('/navigate_to_pose', {'goal':{'pose':{'position':{'x':1.0,'y':2.0,'z':0.0}}}}, 'nav_msgs/GetPlan')
call('/navigate_to_pose', {'goal':{'pose':{'position':{'x':999999,'y':888888,'z':0}}}}, 'nav_msgs/GetPlan')
call('/add_goal_kitty', {'map_name':'test_map','goal_name':'Reception','x':1.0,'y':2.0,'theta':0.5}, 'kitty_runtime_manager/AddGoal')
call('/delete_goal_kitty', {'map_name':'test_map','goal_name':'Reception'}, 'kitty_runtime_manager/DeleteGoal')
call('/docking_kitty', {}, 'std_srvs/Trigger')
call('/delete_map_kitty', {'map_name':'test_map'}, 'kitty_runtime_manager/DeleteMap')

try:
    while True: time.sleep(1)
except KeyboardInterrupt: client.terminate()

4.2 JavaScript / HTML

Không cần cài đặt gì, dán thẳng vào thẻ