Atlas Robotics
SLAMNâng cao

Cartographer: SLAM của Google dựa trên Submap và Pose-graph

Atlasbot · 17/8/2026 · 11 phút đọc

Cartographer: SLAM của Google dựa trên Submap và Pose-graph
Submap cục bộ ghép lại thành bản đồ toàn cục qua pose-graph optimization

Bài slam_toolbox đã trình bày một lựa chọn SLAM linh hoạt. Cartographer — do Google phát triển — là lựa chọn còn lại phổ biến nhất trong ROS2, với kiến trúc nội bộ khác biệt rõ rệt: chia nhỏ bản đồ thành nhiều submap, thay vì khớp trực tiếp vào một bản đồ toàn cục duy nhất.

Khái niệm chính

Thay vì: mỗi scan mới khớp trực tiếp vào MỘT bản đồ toàn cục khổng lồ
Cartographer: nhóm một chuỗi scan liên tiếp thành 1 "submap" cục bộ nhỏ
              khi đủ số scan, chốt submap đó lại, bắt đầu submap mới

Khớp scan vào một submap nhỏ, mới cập nhật gần đây chính xác và nhanh hơn nhiều so với khớp vào một bản đồ khổng lồ đã tích luỹ sai số qua thời gian dài — đây là lợi ích chính của kiến trúc chia nhỏ này.

Nguyên lý hoạt động

Mỗi submap là một "đảo" độc lập — cần một bước riêng để ghép chúng thành bản đồ toàn cục nhất quán. Cartographer xây một pose-graph: mỗi submap là một node, các ràng buộc (constraint) giữa chúng — từ cả chuyển động liên tục lẫn loop closure (bài SLAM là gì?) — là các cạnh. Bộ giải tối ưu Ceres Solver (thư viện tối ưu phi tuyến của Google) tìm vị trí đặt từng submap sao cho tổng sai lệch giữa tất cả các ràng buộc là nhỏ nhất.

Front-end: khớp scan vào submap hiện tại (nhanh, cục bộ)
Back-end:  Ceres Solver tối ưu vị trí TẤT CẢ submap cùng lúc (định kỳ, toàn cục)

Đúng khung Front-end/Back-end đã học ở bài SLAM là gì?, chỉ khác đơn vị xử lý là submap thay vì từng scan riêng lẻ.

Tóm lại: Chia nhỏ thành submap giúp front-end luôn khớp vào dữ liệu "tươi", ít sai số tích luỹ — nhưng đổi lại cần thêm bước ghép nối (pose-graph optimization) phức tạp hơn để đảm bảo các submap khớp đúng với nhau ở quy mô toàn cục. Đây chính là sự đánh đổi kiến trúc cốt lõi phân biệt Cartographer với các hệ SLAM khớp trực tiếp vào một bản đồ duy nhất.

Kiến thức kỹ thuật

Công thức

Kích thước submap (số scan gộp mỗi submap) là tham số đánh đổi trực tiếp giữa độ chính xác cục bộ và số lượng ràng buộc back-end cần xử lý:

Submap nhỏ (ít scan/submap):
  + front-end chính xác hơn (dữ liệu rất "tươi")
  − nhiều submap hơn → pose-graph lớn hơn → back-end tốn nhiều tài nguyên hơn

Submap lớn (nhiều scan/submap):
  + ít submap hơn → pose-graph nhỏ hơn, back-end nhẹ hơn
  − front-end kém chính xác hơn (dữ liệu "cũ" hơn trong submap dài)

Thông số

Tiêu chíCartographerslam_toolbox
Kiến trúcSubmap + pose-graph (Ceres Solver)Pose-graph trực tiếp (không chia submap)
Độ phức tạp tham sốCao, cần tinh chỉnh kỹThấp hơn, dễ tiếp cận
Lifelong mappingKhông có sẵnCó
Chế độ Localization riêngKhôngCó
Phù hợpCần độ chính xác cao, đã quen tinh chỉnhCần vòng lặp phát triển nhanh, linh hoạt

Ứng dụng thực tế

So với slam_toolbox, Cartographer expose nhiều tham số cấu hình hơn (kích thước submap, ngưỡng chấp nhận constraint, trọng số trong hàm tối ưu Ceres...) — mạnh mẽ khi tinh chỉnh đúng cho một loại cảm biến/môi trường cụ thể, nhưng đòi hỏi hiểu sâu hơn để đạt kết quả tốt so với việc dùng slam_toolbox gần như "cắm là chạy" với tham số mặc định. Với dự án nghiên cứu cần độ chính xác bản đồ cao nhất có thể và có đủ thời gian tinh chỉnh tham số, Cartographer thường là lựa chọn tốt hơn; với dự án cần vòng lặp phát triển nhanh hoặc môi trường thay đổi thường xuyên (cần lifelong mapping), slam_toolbox phù hợp hơn.

Ví dụ thực tế

# Trích cấu hình Cartographer điển hình (.lua config)
TRAJECTORY_BUILDER_2D.submaps.num_range_data = 90  # số scan mỗi submap
POSE_GRAPH.optimize_every_n_nodes = 90              # tần suất chạy back-end
POSE_GRAPH.constraint_builder.min_score = 0.65       # ngưỡng chấp nhận loop closure
Tăng num_range_data từ 90 lên 180:
  → submap "dày" hơn, ít submap hơn cho cùng quãng đường
  → back-end nhẹ hơn (ít node trong pose-graph)
  → nhưng front-end trong mỗi submap kém "tươi" hơn ở phần cuối submap

Giảm min_score (VD: 0.65 → 0.55):
  → chấp nhận loop closure dễ dàng hơn (ngưỡng khớp thấp hơn)
  → nguy cơ chấp nhận loop closure SAI cao hơn (khớp nhầm 2 vị trí giống nhau)

Đây là ví dụ cụ thể cho việc "nhiều tham số hơn = mạnh hơn nhưng cần hiểu sâu hơn" đã nêu ở phần Ứng dụng thực tế — mỗi tham số đều có đánh đổi hai chiều, không có giá trị "luôn tốt nhất".

Lỗi thường gặp

  • Giảm ngưỡng min_score quá thấp để "dễ có loop closure hơn" — như ví dụ trên, tăng nguy cơ chấp nhận loop closure sai, gây méo bản đồ nghiêm trọng hơn nhiều so với không có loop closure.
  • Dùng tham số mặc định của Cartographer cho môi trường/cảm biến khác biệt lớn so với cấu hình gốc được thiết kế — Cartographer đòi hỏi tinh chỉnh kỹ hơn slam_toolbox, tham số mặc định không đảm bảo phù hợp mọi trường hợp.
  • Chọn Cartographer khi thực sự cần lifelong mapping — như bảng so sánh, Cartographer không hỗ trợ sẵn tính năng này, cần cân nhắc slam_toolbox nếu đây là yêu cầu quan trọng.
  • Đặt kích thước submap quá lớn cho môi trường có nhiều đặc trưng thay đổi nhanh — submap "cũ" hơn khiến front-end kém chính xác hơn đúng ở những khu vực cần độ chính xác cao nhất.

Kết luận

Cartographer đánh đổi độ phức tạp cấu hình lấy khả năng tinh chỉnh sâu và độ chính xác cao khi cấu hình đúng — kiến trúc submap + pose-graph optimization qua Ceres Solver là điểm khác biệt cốt lõi so với slam_toolbox. Chọn giữa hai không phải "cái nào tốt hơn tuyệt đối" mà là "cái nào phù hợp với thời gian tinh chỉnh sẵn có và yêu cầu tính năng cụ thể (lifelong mapping, độ chính xác tối đa)". Bài tiếp theo trong chuyên mục mở cơ chế scan matching ở tầng thuật toán cụ thể hơn — LiDAR SLAM.

Cartographer: SLAM của Google dựa trên Submap và Pose-graph — Atlasbot