Robot Operating System - ROS
Khi một robot còn nằm trên bàn thí nghiệm, ta có thể bắt đầu rất đơn giản: viết một chương trình đọc cảm biến, tính vài giá trị, rồi gửi lệnh xuống động cơ. Cách đó đủ tốt để kiểm tra một thuật toán nhỏ. Nhưng robot thật hiếm khi chỉ có một thuật toán nhỏ.
Một mobile robot trong kho cần đọc LiDAR, camera, encoder bánh xe, IMU. Nó cần biết mình đang ở đâu, bản đồ xung quanh ra sao, vật cản nằm chỗ nào, đường đi tiếp theo là gì, vận tốc nào nên gửi xuống motor. Người phát triển cũng cần nhìn được robot đang nghĩ gì: laser scan có đúng không, odometry có trôi không, planner có tạo đường kỳ lạ không, controller có nhận đúng command không.
Nếu tất cả được nhét vào một chương trình nguyên khối, ban đầu hệ thống có vẻ dễ kiểm soát. Mọi hàm gọi trực tiếp nhau. Dữ liệu nằm chung trong bộ nhớ. Không cần nghĩ nhiều về giao tiếp giữa các thành phần. Nhưng càng thêm sensor, thuật toán và công cụ debug, chương trình đó càng trở thành một khối khó sửa. LiDAR chạy ở nhịp riêng. Camera chạy ở nhịp riêng. Controller cần vòng lặp ổn định hơn planner. Một lỗi nhỏ ở driver sensor có thể làm sập cả hệ thống. Muốn thay thuật toán localization cũng kéo theo hàng loạt thay đổi không liên quan.

ROS xuất hiện từ đúng điểm căng đó. Nó không cố biến robot thành một chương trình lớn hơn. Nó đưa ra một cách tổ chức khác: coi robot là một hệ nhiều thành phần, mỗi thành phần có trách nhiệm rõ, giao tiếp qua interface rõ, và có thể được quan sát bằng các công cụ chung.
Tên đầy đủ của ROS là Robot Operating System, nhưng cách gọi này dễ gây hiểu nhầm. ROS không phải hệ điều hành theo nghĩa Linux hay Windows. Nó không thay kernel, không trực tiếp quản lý CPU, RAM hay driver phần cứng ở tầng thấp. ROS gần hơn với một middleware và một hệ sinh thái phần mềm cho robotics: nó giúp các tiến trình tìm thấy nhau, trao đổi dữ liệu, định nghĩa kiểu message, quản lý transform, ghi lại dữ liệu, visualize trạng thái robot, launch nhiều thành phần, và tái sử dụng package từ cộng đồng.
Vì vậy, học ROS không chỉ là học vài lệnh. Học ROS là học một triết lý tổ chức phần mềm robot: khi hệ thống phức tạp, điều quan trọng không chỉ là thuật toán bên trong từng khối, mà là cách các khối đó sống cùng nhau.
Hệ robot nhiều thành phần
Hãy giữ một ví dụ xuyên suốt: một mobile robot tự di chuyển trong kho. Robot này không thể chỉ “nhìn rồi chạy”. Nó cần một chuỗi năng lực liên tục.
LiDAR tạo ra các lát cắt khoảng cách xung quanh robot. Encoder và IMU giúp ước lượng chuyển động ngắn hạn. Localization dùng cảm biến và bản đồ để ước lượng pose hiện tại. Planner nhận pose, map và goal để tạo đường đi. Controller biến đường đi thành vận tốc. Driver motor nhận vận tốc và điều khiển phần cứng. RViz hoặc một công cụ visualization cần đọc nhiều luồng dữ liệu để người vận hành hiểu robot đang ở trạng thái nào.
Điểm đáng chú ý là các thành phần này không có cùng nhịp thời gian. Controller cần đều và nhanh. Camera có thể nặng và chậm hơn. Planner không nhất thiết chạy ở mọi frame cảm biến. Visualization không nên làm ảnh hưởng tới vòng điều khiển. Một hệ robot tốt phải cho phép các phần này chạy độc lập ở nhịp phù hợp, nhưng vẫn trao đổi dữ liệu đúng cách.
Nếu viết nguyên khối, ta thường phải chọn giữa hai điều khó chịu. Hoặc mọi thứ bị buộc vào một vòng lặp chung, khiến thành phần chậm kéo theo thành phần nhanh. Hoặc chương trình bắt đầu sinh ra nhiều thread, queue và biến chia sẻ tự quản lý, rồi lỗi timing, deadlock và dữ liệu cũ xuất hiện ở những chỗ khó nhìn thấy.
ROS chọn một hướng khác. Thay vì xem robot là một chương trình, ROS xem robot là một graph.
Trong graph đó, mỗi node là một đơn vị logic: node LiDAR đọc scan, node localization ước lượng pose, node planner tạo đường, node controller phát vận tốc, node visualization chỉ quan sát. Các node không cần gọi trực tiếp hàm của nhau. Chúng trao đổi dữ liệu qua các cơ chế giao tiếp chuẩn.
Topic dùng cho dữ liệu chảy liên tục, như /scan, /odom, /joint_states, /cmd_vel. Service dùng cho yêu cầu ngắn kiểu hỏi-đáp, chẳng hạn reset một module hoặc lấy một trạng thái. Action dùng cho tác vụ kéo dài có feedback, như yêu cầu robot đi tới một pose đích và theo dõi tiến trình trên đường đi.
Nhờ cách nhìn này, một thay đổi cục bộ không nhất thiết kéo sập cả hệ thống. Nếu thay LiDAR thật bằng LiDAR trong simulator nhưng vẫn publish cùng topic và cùng message type, các node phía sau có thể tiếp tục chạy. Nếu thay planner A bằng planner B nhưng cả hai cùng nhận map, pose và phát trajectory theo interface tương thích, phần còn lại không cần biết thuật toán bên trong đã đổi.
Đó là lợi ích đầu tiên của ROS: nó biến độ phức tạp của robot thành một kiến trúc có ranh giới.

Interface
Tách hệ thống thành nhiều node mới chỉ là nửa đầu của câu chuyện. Nếu mỗi node tự phát minh một kiểu dữ liệu riêng, graph vẫn sẽ hỗn loạn. Một node nói “pose” theo kiểu này, node khác hiểu “pose” theo kiểu khác. Một node publish vận tốc nhưng không rõ đơn vị là gì. Một node gửi dữ liệu sensor nhưng không có timestamp hoặc frame. Khi đó, hệ thống tuy có nhiều node nhưng vẫn khó ghép.
Vì vậy, ROS đặt interface ở trung tâm.
Message trong ROS là hợp đồng dữ liệu có type rõ ràng. geometry_msgs/msg/Twist mô tả vận tốc tuyến tính và vận tốc góc. sensor_msgs/msg/LaserScan mô tả một lần quét laser. nav_msgs/msg/Odometry mô tả odometry. Khi một topic có tên, type và quy ước sử dụng rõ, các node có thể giao tiếp mà không cần biết implementation bên trong của nhau.
Điều này có vẻ giống chi tiết kỹ thuật, nhưng trong robotics nó thay đổi cách thiết kế hệ thống. Ta không còn bắt đầu bằng câu hỏi “hàm này gọi hàm nào?”. Ta bắt đầu bằng câu hỏi “node này nhận thông tin gì, phát ra thông tin gì, và hợp đồng dữ liệu của nó là gì?”.
Với mobile robot trong kho, câu hỏi đó giúp hệ thống rõ hơn nhiều. Node localization không cần biết controller viết bằng C++ hay Python. Controller không cần biết pose đến từ AMCL, SLAM hay một hệ motion capture trong phòng lab. Visualization không cần can thiệp vào thuật toán planner. Chỉ cần các interface được giữ ổn định, các phần có thể phát triển độc lập.
Interface cũng là nền của reuse. Một driver camera, một package SLAM, một navigation stack hay một tool visualization chỉ có thể được dùng lại rộng rãi nếu nó nói cùng một “ngôn ngữ” với phần còn lại của hệ sinh thái. ROS không chỉ chia sẻ code. ROS chia sẻ cả message type, quy ước đặt frame, cách publish dữ liệu, cách ghi log, cách launch và cách quan sát hệ thống.
Đây là lý do ROS phổ biến trong nghiên cứu robotics. Một nhóm không phải viết lại mọi thứ từ đầu. Họ có thể dùng driver có sẵn, dùng RViz để nhìn dữ liệu, dùng rosbag để ghi lại một buổi chạy robot, dùng TF để quản lý quan hệ giữa các frame, dùng package navigation hoặc SLAM làm nền, rồi tập trung vào phần thuật toán họ thật sự muốn nghiên cứu.
Nhưng interface và package chỉ có giá trị khi người phát triển quan sát được hệ thống đang làm gì. Robot là hệ vật lý. Khi nó chạy sai, lỗi có thể đến từ sensor, calibration, transform, timing, planner, controller, network hoặc chính thuật toán. Nếu không có tooling, graph đẹp đến đâu cũng khó debug.
Vì vậy, ROS không dừng ở communication. Nó đi cùng một hệ công cụ quanh communication.
Ta có thể xem node nào đang chạy, topic nào đang tồn tại, ai publish, ai subscribe, message type là gì. Ta có thể ghi dữ liệu bằng rosbag rồi replay lại để debug thuật toán mà không cần robot thật đứng trước mặt. Ta có thể dùng RViz để nhìn laser scan, map, robot model, trajectory và transform. Ta có thể dùng launch để khởi động nhiều node với cấu hình nhất quán. Ta có thể dùng URDF để mô tả robot và TF để theo dõi quan hệ giữa các hệ tọa độ.
Nếu chỉ nhìn ROS như một thư viện publish/subscribe, ta sẽ bỏ sót phần quan trọng nhất. ROS mạnh vì nó tạo ra một môi trường phát triển robot: giao tiếp, interface, package, visualization, logging, replay, launch và convention cùng nằm trong một hệ sinh thái.

ROS 1
ROS 1 ra đời trong bối cảnh robotics cần một nền tảng giúp nghiên cứu nhanh hơn. Khi đó, bài toán lớn nhất không phải là xây một hệ công nghiệp hoàn chỉnh ngay từ đầu. Bài toán là làm sao để các lab có thể ghép sensor, thuật toán và robot nhanh hơn; làm sao để một package hữu ích không bị kẹt trong một dự án riêng; làm sao để người làm SLAM, planning, control và perception có thể chia sẻ kết quả theo một cách dễ dùng.
Với mục tiêu đó, ROS 1 là một thiết kế rất hợp lý. Nó đưa vào các khái niệm mà đến nay vẫn là lõi của ROS: node, topic, service, action, message, package, launch, TF, rosbag, RViz. Nó giúp việc dựng một hệ robot nghiên cứu trở nên nhanh hơn rất nhiều. Ta có thể chạy một driver, xem topic, mở RViz, ghi rosbag, thay package localization, thử planner khác, và quan sát mọi thứ trong cùng một mô hình graph.
Một thành phần quan trọng trong ROS 1 là ROS Master. Master giúp các node tìm thấy nhau. Khi một publisher và subscriber cùng quan tâm tới một topic, Master hỗ trợ quá trình discovery để chúng thiết lập kết nối. Sau khi kết nối được tạo, dữ liệu thường truyền trực tiếp giữa các node.
Cách này đơn giản, dễ hiểu và rất phù hợp với môi trường nghiên cứu. Nó làm cho ROS 1 dễ học, dễ thử, dễ ghép nhanh. Trong nhiều năm, đây là lý do ROS 1 trở thành nền quen thuộc của robotics học thuật và prototyping.
Nhưng chính thành công đó cũng làm lộ ra giới hạn khi robot đi xa hơn phòng lab.
Một robot sản phẩm không chỉ cần chạy được trong demo. Nó cần hoạt động ổn định trong mạng phức tạp hơn, có nhiều máy tính hơn, nhiều process hơn, nhiều loại dữ liệu hơn, yêu cầu bảo mật rõ hơn, và đôi khi có ràng buộc real-time. Trong bối cảnh đó, một số giả định của ROS 1 trở nên chật.
ROS Master là ví dụ dễ thấy. Một điểm trung tâm cho discovery rất tiện khi hệ nhỏ, nhưng không lý tưởng cho hệ phân tán cần khả năng chịu lỗi và cấu hình mạng linh hoạt hơn. Communication trong ROS 1 cũng không cho phép mô tả chính sách truyền dữ liệu đủ phong phú. Camera image, LiDAR scan, command velocity, trạng thái hệ thống và static transform không nên luôn được đối xử như nhau. Có dữ liệu chấp nhận mất frame để giảm độ trễ. Có dữ liệu cần reliable. Có dữ liệu cần được giữ lại để node đến sau vẫn nhận được.
ROS 1 cũng không đặt security, real-time và multi-platform làm mục tiêu thiết kế trung tâm từ đầu. Điều này không có nghĩa ROS 1 “sai”. Nó chỉ phản ánh đúng bài toán mà ROS 1 giải rất tốt: nghiên cứu, thử nghiệm nhanh, chia sẻ package và xây prototype.
Khi bài toán chuyển từ “làm cho robot chạy được trong lab” sang “làm cho nhiều robot, nhiều máy và nhiều luồng dữ liệu chạy đáng tin hơn trong môi trường thật”, ROS cần một nền khác.
ROS 2
ROS 2 không nên được hiểu là ROS 1 đổi cú pháp. Nó là một lần thiết kế lại nền bên dưới, trong khi giữ tinh thần bên trên.
Tinh thần được giữ lại là robot vẫn được tổ chức thành node. Node vẫn trao đổi qua topic, service và action. Message, package, launch, TF, rosbag, RViz và mô hình graph vẫn là những ý tưởng trung tâm. Người học ROS 1 khi nhìn sang ROS 2 vẫn thấy cùng một cách nghĩ: chia hệ thống thành thành phần, định nghĩa interface, quan sát graph, ghép package.
Phần thay đổi nằm ở các giả định hạ tầng.
Thay vì dùng ROS Master, ROS 2 dựa trên DDS làm middleware. DDS được thiết kế cho hệ phân tán, có discovery phân tán, có publish/subscribe, có nhiều chính sách QoS, và có nhiều implementation khác nhau. Nhờ DDS, ROS 2 không cần một master trung tâm kiểu ROS 1. Các node có thể phát hiện nhau thông qua middleware nếu chúng ở cùng ROS domain, mạng được cấu hình phù hợp, và QoS tương thích.
Điều này làm ROS 2 tự nhiên hơn cho các hệ robot hiện đại. Một node camera có thể chạy trên máy A, perception trên máy B, planning trên máy C, controller trên máy D. Hệ thống không còn bị mô hình hóa quanh một master duy nhất. Nhưng đổi lại, người phát triển phải hiểu thêm về mạng, domain id, multicast, firewall, network interface, DDS vendor và QoS khi debug communication.
QoS là một trong những thay đổi quan trọng nhất. Trong ROS 2, một topic không chỉ có tên và message type. Publisher và subscriber còn có Quality of Service policies. Các policy này mô tả dữ liệu nên được truyền như thế nào: reliable hay best effort, giữ bao nhiêu message gần nhất, có lưu dữ liệu cho subscriber đến sau hay không, deadline ra sao, liveliness như thế nào.
Với mobile robot trong kho, QoS không phải lý thuyết xa vời. Camera image hoặc LiDAR scan có thể ưu tiên độ trễ thấp và chấp nhận mất vài frame, nên best effort có thể hợp lý. Một số trạng thái hoặc command quan trọng có thể cần reliable. Static transform có thể cần durability để node mới khởi động vẫn nhận được thông tin cần thiết. ROS 2 cho phép mô tả các khác biệt đó ở tầng communication thay vì giả vờ mọi dữ liệu đều giống nhau.
ROS 2 cũng đưa lifecycle và composition thành các cơ chế rõ hơn. Lifecycle node cho phép một node đi qua các trạng thái như unconfigured, inactive, active, finalized. Với robot thật, điều này rất quan trọng. Một motor driver không nên nhận command trước khi phần cứng được configure xong. Một sensor node có thể cần chuẩn bị tài nguyên trước, rồi chỉ publish khi hệ thống chuyển sang trạng thái active.
Composition cho phép nhiều node được nạp vào cùng một process khi cần giảm overhead, hoặc tách riêng process khi cần cô lập lỗi. Cùng một mô hình node vì thế có thể được triển khai linh hoạt hơn: dễ debug khi tách rời, hiệu quả hơn khi compose chung.
Security và real-time cũng được ROS 2 xem nghiêm túc hơn. Thông qua SROS2 và các cơ chế liên quan tới DDS Security, ROS 2 có nền tốt hơn để nghĩ về xác thực, phân quyền và bảo vệ dữ liệu. Với real-time, ROS 2 không tự động biến một hệ thống thành real-time, vì real-time phụ thuộc vào toàn bộ stack: hệ điều hành, scheduler, middleware, executor, memory allocation, callback, driver và controller. Nhưng ROS 2 được thiết kế để bài toán đó khả thi hơn so với ROS 1.
Vì vậy, khác biệt giữa ROS 1 và ROS 2 không nằm ở chuyện lệnh nào dài hơn hay API nào mới hơn. Khác biệt nằm ở phạm vi bài toán. ROS 1 cực mạnh cho nghiên cứu và prototype. ROS 2 giữ lại mô hình phát triển đó, nhưng đưa communication, lifecycle, deployment, security và real-time tới một nền phù hợp hơn với robot phân tán và triển khai nghiêm túc.

Kiến trúc phần mềm robot
Sau khi đi qua ROS 1 và ROS 2, ta có thể quay lại câu hỏi ban đầu: tại sao robotics lại cần ROS?
Câu trả lời không phải vì ROS có một thuật toán thần kỳ. ROS không tự làm SLAM tốt hơn, không tự làm controller ổn định hơn, không tự làm planner thông minh hơn. Các thuật toán đó vẫn phải được thiết kế, kiểm tra và tinh chỉnh riêng. ROS giải quyết một lớp vấn đề khác: làm sao để các thuật toán, sensor, actuator và tool cùng tồn tại trong một hệ thống có thể phát triển.
Trong robot thật, thuật toán không sống một mình. SLAM cần sensor data đúng timestamp và đúng frame. Planner cần map, pose và goal. Controller cần trajectory hoặc velocity command. Visualization cần đọc gần như mọi thứ nhưng không được làm hỏng vòng điều khiển. Logging cần ghi dữ liệu để debug sau. Simulation cần thay thế phần cứng thật mà không làm các node phía sau đổi quá nhiều.

ROS cung cấp cấu trúc để những phần đó ghép lại. Node tạo ranh giới trách nhiệm. Topic, service và action tạo đường giao tiếp. Message type tạo hợp đồng dữ liệu. TF tạo ngôn ngữ chung cho hệ tọa độ. Launch giúp khởi động hệ thống. Rosbag giúp ghi và replay dữ liệu. RViz giúp nhìn thấy trạng thái mà nếu chỉ đọc log sẽ rất khó hiểu. Package và convention giúp cộng đồng chia sẻ thành phần theo cách người khác có thể dùng lại.
Triết lý sâu hơn của ROS là robotics là bài toán tích hợp. Một robot không chỉ thất bại vì thuật toán sai. Nó có thể thất bại vì dữ liệu đến trễ, frame đặt sai, node publish nhầm type, sensor driver treo, transform thiếu, planner nhận map cũ, controller nhận command không đúng nhịp, hoặc người phát triển không có cách nhìn vào hệ thống đang chạy. ROS không loại bỏ các lỗi đó, nhưng nó cho ta một khung để đặt tên, quan sát và xử lý chúng.
Đó cũng là lý do một ROS graph tốt không nên chỉ là nhiều node. Nó phải là một kiến trúc có ý nghĩa. Mỗi node cần có trách nhiệm rõ. Mỗi interface cần có type và quy ước rõ. Mỗi topic cần phản ánh đúng bản chất dữ liệu. Với ROS 2, QoS cũng phải phù hợp với luồng dữ liệu. Nếu các ranh giới này bị thiết kế cẩu thả, ROS graph có thể trở thành một mạng dây rối không kém chương trình nguyên khối ban đầu.
Nhìn như vậy, ROS không phải đích đến. Nó là nền để xây hệ robot. ROS 1 cho thấy sức mạnh của việc chuẩn hóa cách các thành phần robotics giao tiếp và được tái sử dụng. ROS 2 tiếp tục triết lý đó, nhưng thay nền để đáp ứng tốt hơn các yêu cầu hiện đại: phân tán hơn, có QoS rõ hơn, có lifecycle tốt hơn, có security tốt hơn, nhiều nền tảng hơn, và có đường đi nghiêm túc hơn tới deployment.
Với người mới học robotics, hiểu ROS theo cách này sẽ tự nhiên hơn học thuộc từng khái niệm riêng lẻ. Node, topic, service, action, message, TF, rosbag, RViz, DDS, QoS, lifecycle không phải các mảnh rời. Chúng là các câu trả lời cho cùng một vấn đề: làm sao biến một tập hợp sensor, thuật toán, motor và công cụ debug thành một robot có thể phát triển, quan sát, thay thế và mở rộng.