[ROS2]Part2— แนวคิดเบื้องหลังการพัฒนา
จริงๆบทความนี้ถูกผมแปลและใส่ไข่มาจากบทความ Design Doc ของ ROS2.org นะครับผม
หลังจากที่เล่าเรื่องมาใน Part แรกว่า ทำไมถึงมีการทำ ROS2 เกิดขึ้นมา ก็เพราะว่าของเดิมมันมีคนใช้เยอะ และระบบมันทำมาแน่นเกินกว่าจะรื้อไส้ออกมาแก้แล้ว เลยคิดว่าทำใหม่ดีๆเลยดีกว่า
มันก็ยังมีเรื่องอีกนิดๆหน่อย
(ที่จะสามารถขยายไปเป็นประเด็นใหญ่ๆต่อไปได้เป็น Part3 Part4 เลย 5555)
คือเรื่องเกี่ยวกับ ความพยายามใหม่ๆ ที่ทีมคิดว่าจะใส่เข้ามา และเป็นแนวทางที่ ROS ควรจะเป็น ถ้าจะทำ version ใหม่มาอะนะ
นอกเหนือจาก Core Function พวก messaging ที่กล่าวไปใน Part 1 ก็มีพวกนี้เพิ่มเติมเข้ามาอีก
ความพยายามในการใช้ ROS กับ Hardware ให้ได้โดยตรงเลย
เดิมที ตอนเวลาเราใช้ ROS1 กับพวก Sensor ต่างๆ เราจะต้องควานหา SDK ต่างๆที่คนทำ Hardware ทำมาให้ และต้องเป็น C++ , Python ด้วยนะ จะได้ใช้งานได้ง่ายๆ
สิ่งที่เกิดขึ้นคือ SDK , ROSNode ที่ผู้ผลิต Sensor , Actuator ทำออกมา จะทำการคุยกับ Hardware เราผ่านทาง Serial connection (ส่วนใหญ่) หรือไม่ก็ Network connection แบบ LAN (เช่น Lidar ที่ใช้ RJ45-หัวแลน)
เพื่อสร้างการรับการส่งของพวกเค้าเอง (โดยทั่วไปเราไม่ค่อยได้รู้เท่าไร ว่า Sensor คุยกับคอมด้วยByteหน้าตายังไงเพื่อที่จะทำอะไรบางอย่าง
แต่ตอนเวลาจะเรียกใช้/สั่งส่งข้อมูล ก็ใช้คำสั่งที่มีมาใน SDK เลย
เช่น Lidar.getRanges() , Motor1.move(100) อะไรทำนองนี้ )
คนทำ Hardware จะต้องทำ
- SDK เพื่อให้ใช้ได้กับระบบที่ไม่ใช่ ROS
และก็ต้องทำ - ROS Node เพื่อทำให้ SDK พวกนั้นมาใช้กับ ROS ได้
มันเป็นการทำงานสองรอบใช่ไหมล๊า
โดยข้อ 2. นี้บางทีก็ต้องรอคนใน Community ที่ทนไม่ไหวแล้วว มานั่ง Wrapให้เป็น ROS Node ให้ T_T
ทางทีมพัฒนา ROS2 เลยคิดว่า ถ้าพวก Hardware ต่างๆ สามารถรับส่งของที่พร้อมใช้ใน ROS Software Ecosystem เข้ามาในระบบเลยล่ะ จะทำให้อะไรๆดีขึ้นไหม
อ้ะ ถ้างั้น สมมติว่าเราเอา Rosnode ไป Implement บน Embedded , Sensors , Hardware โดยไม่ใช่ Serialize Library (พวก Rosserial-arduino) ได้แล้ว !
จะพบว่า ~ Sensor , Hardware เล็กๆของเรา มี CPU ที่จำกัดจำเขี่ยมากๆ เวลาที่จะทำตัวเป็น ROSNode จะต้อง Emulate XMLRPC (ไปดูเพิ่มเติมได้ที่ Go Down Deep / Technical Review) บนอุปกรณ์นั้นๆ ก็คงจะใช้ทรัพยากรมากเกินไป ก็อาจทำให้ Mem ของอุปกรณ์นั้นไม่พอ CPU ทำงานไม่ทัน บลาๆ เพราะ Spec มันไม่ดีพอ (อันนี้เดานะ 55)
ทีมพัฒนาเลยจะต้องหาวิธีการทำให้ Hardware , Sensor ของเราเนี่ย สามารถทำตัวเป็น ROSNode ได้ตั้งแต่ต้นทางแบบง่ายๆเลย
จึงเป็นการดีที่จะเริ่ม พยายามทำขึ้นมาใหม่ และพัฒนาส่วนนี้
สิ่งที่เกิดขึ้นคือ ไม่ต้องรอ SDK จากคนที่ผลิตมาเหมือนเดิม
เพื่อที่จะทำ Ros Node ใช้ เพราะคนทำต้องให้มันพร้อมใช้งานมาเลยอยู่แล๊นน !
และมันเป็น Ros based Interface เหมือนกัน เวลาเปลี่ยนเจ้า เป็นยี่ห้อไปใช้ของแบบเดียวกัน แต่ยี่ห้ออื่นเงี่ย ก็ไม่ต้องห่วง เพราะ เวลาเอามาเสียบ ROS2 มันก็ควรจะมองเห็นเหมือนๆกัน !
เช่นเปลี่ยน Motor Driver , Lidar ก็ได้ข้อมูลแบบเดิมหรือใช้คำสั่งลงไปแบบเดิม แม้ว่าจะคนจะยี่ห้อก็ตาม
มันเลยเป็นความพยายามที่ดี และทีมพัฒนาเค้าก็อยากให้มีอะนะ
(แต่ทำได้ละยังนี่เรายังไม่รู้
5555555555ถถT_Tถถถถ55555555 แบบมีน้ำตาซ่อนอยู่)
Launching ที่แสนปวดตับ
ตอนเวลาเราใช้ ROS1 เราจะใช้ Launch File ในการเปิด Node ต่างๆขึ้นมาใช่ไม๊ล๊าา (ถ้ายังไม่ได้ใช้ หรือใช้ไม่เป็น ก็ไปใช้ roslaunch ซะ — ไม่ทำให้ฟันผุนาจา)
ด้วยการเขียน XML ขึ้นมา บอกว่าจะมี Node อะไรบ้าง Param อะไรบ้าง
โดยไม่มี Sequence , Dependency ว่าใครต้องเปิด Node ไหนก่อน Node ไหน
ถ้าเขียนโปรแกรมไม่ดี มักจะเจอปัญหาว่า ต้องเปิด Node นี้ก่อนนะ ไม่งั้น Node นั้นจะบึ้ม จะทำนู้นนั่นนี่ไม่ได้ — ServiceClient ที่เขียนไว้ตอน Init Constructor จะหา ServiceServer ไม่เจอ เพราะ Node Server เปิดทีหลัง … , while loop ที่เรียก TF จะ throw error บลาๆ แล้วก็ล้มตายไป บัยจ้าาา
ทีมงานเค้าเลยกะว่า : รอบนี้ ROS2 ใช้ Python มาทำ Launch File ทีนี้เราจะจัดการการเปิดอย่างเป็นลำดับได้ดีขึ้นแล้ว … (เย้)
และมี State Lifecycle ของ Node ทำให้เราสามารถเล่นกับ Node ตอนเปิดได้ว่า Node พร้อมแล้วหรือยัง ถ้ายังไม่พร้อมให้รอ หรือจะให้ทำอะไรก่อน ก็แล้วแต่
รวมไปถึงเรื่อง Process Layout ด้วย
สืบเนื่องมาจาก เราสามารถเขียน ROS2 Node หลายๆอันใน Process เดียวกันได้ ถ้าให้เปรียบเทียบกับคนที่เคยใช้ ROS1 แบบ Hardcore มา
จะพบเหมือนกับ Nodelet + Nodelet Manager เลย (ในเรื่องของ Component และ Composition)
เช่น ๆ เวลาเราใช้พวก Nodelet ทำงาน มันจะมีกลุ่มของ Node ที่ Run ใน Process เดียวกัน แล้วทีนี้ จะ Debug แค่ตัวเดียวมันก็ต้องมาเจาะดูทีละตัว(จากหลายๆ Nodelet) ซึ่งทำให้ Debugger อึดมากๆ
เสริม Nodelet — เวลาเขียน Nodelet เราจะต้องมองว่า Code เราเป็น Class ของ Pluginlib
(ตัวอย่างของ Pluginlib class — ก็เช่น base_local_planner ใน move_base)
Nodelet จะมี Manager (ของ Nodelet) มา Run Code เรา ทำให้เรามีหลายๆ Node ใน Process เดียว ทำให้เวลาอยู่ Process เดียวกัน จะสามารถทำ Zero Copying (ก็คือเรียกใช้ข้อมูลกันภายในแหละ ไม่ต้องมา Pub/Subข้าม Node ให้เปลือง Network)
ซึ่งทำให้ทำงานกับข้อมูลก้อนใหญ่ๆได้เร็วขึ้นนั่นเอง
ปล(เสริม) — Nodelet เขียนยากอ้ะ syntax ก็ไม่เหมือนปกติ ขี้เกียจใช้(ว้อย)ก็เลยไม่ค่อยได้ใช้ แต่เห็นน้องใช้ทำ Multiplexor อยู่นะ สงสัยมันทำงานได้เร็วกว่า
ทีมที่ทำ ROS2 เลยอยากให้ มันออกมาในรูปแบบที่เลือกได้ว่า Node ไหนจะมา Run เดี่ยวๆ หรือจะรวมกลุ่มกัน (เพื่อ Debug ง่ายๆ) และจัดการกลุ่ม Node ให้อยู่บนเครื่องต่างๆได้ง่าย เช่น งานมีคอมหลายๆเครื่อง ก็อาจแบ่ง Navigation (Kinematics , Moving Parts) เครื่องนึง , Cognition(Image, Sensor + Machine Learning) อีกเครื่องนึง ก็จะจัดการง่ายขึ้น
BUILD SYSTEM ! ระบบ Build ที่(ต้อง)เปลี๊ยนไป๋
ของเดิม เราเก็บ ROS เป็น Package และมี Package.XML เก็บ Catkin Space Package Requirement ไว้ ตอนสั่ง make, build จะใช้ CMakelist จัดการ build พวก Dependency ต่างๆที่ดึงมาจาก XML + ที่ระบุเพิ่มเติมใน CMakelist
และแน่นอน พอมาถึง ROS2 อะไรๆ ก็เปลี่ยนไป
ทีมพัฒนาใช้สิ่งที่เรียกว่า AMENT ซึ่งเป็นระบบ Build ใหม่
(spoil — และก็โดนแทนที่ด้วย Colcon)
Catkin คือ ระบบ Build ของ ROS1 . . . และ AMENT แปลว่า Catkin …. บายยยย
โดยหน้าที่ก็เหมือนๆกัน คือ
- จัดการเรื่องการ Build Software ของเรา แบบเป็น Package
- จัดการ Build หลายๆ Package ที่มี Dependencies โดยเรียงตามลำดับความต้องการดีๆ (Topological Order — เหมือน วิชาที่ต้องลงเรียนก่อน ถึงจะเรียนตัวนี้ได้ อะไรประมาณนั้น)
ซึ่ง Tools นี้ เหมือนกับ Catkin ก็คือต้องใช้ Meta Data (Package Manifest) ประจำ Package ของระบบ Build นั่นก็คือ package.xml
ในการหาข้อมูลต่างๆเพื่อจะมา build
โดยจะมีระบบการ Build ตามที่เรากำหนดไว้แต่ละ package เช่น Build แบบ cmake(Non Ros Package) , หรือ build แบบ Catkin(Ros Packageส่วนใหญ่)
เราแค่พิมพ์ catkin_make , catkin build เท่านี้ ก็build ได้ทั้งหมดในทีเดียว ถ้า setup package , workspace ไว้ดีๆ
(ไปดูเรื่องระบบ Build + Package Layout ได้ที่นี่เน้อ)
โดยภาพรวมระบบจะทำงานคล้ายๆ CATKIN เดิมๆเลย คือสามารถกำหนด Build Environment เองได้(ใน python , C++)
แล้วมันแตกต่างกันยังไงล่ะ ทำไมไม่ใช้ Catkin ต่อ ?
- Catkin ทำงานโดยใช้ CMake เป็นพื้นฐานในการ build
(ขนาด Ros python package ที่ใช้ setuptools ของ python ยังต้องไป enable catkin_python_setup ใน CMake เลย) ซึ่งมันทำให้เกิดข้อจำกัดหลายๆอย่าง และคนเขียนบอกว่าถ้าจะทำให้ Support windows จะทำลำบากมาก - Catkin ใช้ Devel Space ในการ Run ตอนที่เรายังไม่สั่ง build เป็น Executable ทำให้ ตอนเวลา Test เร็วๆ มันดีนะ แต่ … ตอนเวลาที่แปลงเป็นไฟล์พร้อมไปใช้งานเป็น Executable file มันจัดการได้ลำบาก
พูดมาตั้งเยอะใน bullet นี้ — Ament จัดการตอนเวลาเลือกแบบ build install ให้ จบ 555555+
จริงๆมีอีกหลายอย่างแหะ แต่ตอนนี้เหนื่อยแย้วว ไว้ค่อยมาต่อกัน Episode หน้าา
ขอติดเรื่อง QoS , Dev Tools ไว้ก่อนละกัน 55555555+
เดี๋ยวต้องไปลง ros2 ใหม่อีกรอบ เพราะรอบแรกใช้ใน docker แล้วมันไม่ค่อยสะดวกเท่าไร T_T
ติว 23-Oct-2019
กดเข้ามาเหอะ ไม่กัดหรอก https://www.itutor.name