[ROS] Part 2, Concept of Modularity

iTUTOR - Theppasith N.
iTUTOR
Published in
5 min readMar 10, 2018

--

หลังจากโดนหลอกให้ Cliff hanger ไปใน [ROS] Part 1, Introduction + Installation ! แล้ว

รวมไปถึงคนเขียนซึ่งหางานหาการทำได้แล้ว(มาปีครึ่ง) -*-
เลยมีเวลาเขียนน้อยลง

อันนี้จะเป็นเรื่องของ Concept จริงๆซักทีนะ !!

โปรดระวัง บทความนี้มีรูปภาพเยอะมากๆๆๆๆ

จากตอนที่แล้ว ผมได้ยัดเยียดการ Install ROS ลงไปใน Ubuntu ของทุกคนแล้ว

เราจะมาพูดถึง Terminology(ส่วนประกอบพื้นฐาน) ของ ROS กันหน่อย
ว่า เราจะเขียนโปรแกรมโดยใช้หลักการของอะไร ของต่างๆเรียกยังไง

Controversial image from Willow Garage :)

อยากจะย้ำเรื่อง Concept

ROS นั้นช่วยให้ผู้พัฒนาหุ่นยนต์
สามารถส่ง message ระหว่าง module ต่างๆในระบบได้ง่ายดาย

นั้นคือ concept หลักๆของมัน

โดยวันนี้เราจะมาพูดถึงโครงสร้างของ Software ที่จะเกิดขึ้นกัน

ขอมาตั้งคำศัพท์กันหน่อยก็แล้วกัน

Terminology — Vocabulary

ลองจำๆแบบไม่จำเป็นต้องรู้ความหมายจริงจังก็ได้ ขอแค่พอเข้าใจคร่าวๆ ใช้งานไปแล้วจะเข้าใจเอง 55555

Node — ส่วนของโปรแกรมที่ทำหน้าที่เฉพาะ

เช่น
Node ของการจับหน้าคน
Node ของการขับเคลื่อนมอเตอร์
Node ของการรับค่าจาก Joystick
มองมันเป็น Module หนึ่งใน Software ก็ได้

จริงๆมันจะมีสิ่งที่เรียกว่า Nodelet ด้วยนะเออ แต่อันนั้นมัน Advance มากเลย
เป็นการ Implement Node ในลักษณะที่ทำให้ทำงานไวมากๆ ด้วย Zero copy pointer (ถ้าคนเคยเขียนภาษา C มาจะรู้ว่าแม่งไวจริง)
เอาไว้ทำงานล้ำๆ แต่การเขียนมันจะยากหน่อย ในระดับเริ่มต้น แนะนำว่าให้ข้ามๆไปก่อน ถ้าไม่ได้ยุ่งกับพวก Algorithm เดือดๆมากนัก

Message — ข้อความที่ Node ใช้คุยกัน

เช่น ข้อความทั่วๆไป ก็ string (ข้อความ) , int(จำนวนเต็ม) , double (จำนวนทศนิยม)
หรือ จะเป็นตัวที่ ROS Provide standard ให้
เช่น Vector3 ที่เรากรอกค่า (x,y,z) ได้
Robot Specific หน่อย ก็ — Transformation frame , geometry_msgs::Twist , GoalTarget
หรือจะเป็น Custom ที่ทำเอง เช่น tutormessage ที่ประกอบด้วย int 5 ค่า แบบนี้ก็ได้

Topic — ช่องทางที่ Node ใช้ส่ง Message หรือรอฟัง Message

เป็นเรื่องที่จะส่งคุยกันนั่นแหละ เหมือนเป็น ห้อง Chat , Group ลับๆ 18+ หรืออะไรก็ตาม จะไม่มีใครพ่นเรื่องอื่นในห้องนั้น !!

เราสามารถตั้งชื่อ Topic ได้ตามใจเรา แต่ส่วนใหญ่จะตามหัวข้อเรื่อง
เช่น /detected_faces , /command_velocity , /transformation_frame , . ..
โดยจะเสมือนเป็นท่อที่ทิ่มออกจาก Node
มีความสามารถแบบ IN-OUT (ทั้งรับและส่ง) ผ่านท่อนี้เลย

โดย Node นึงจะมีได้หลาย Topic อยู่ที่จะเป็นการรับ หรือเป็นการส่งข้อมูล

การรับและการส่งข้อมูลใน ROS จะเป็น Message broadcasting based

คนส่ง คนรับ ?

คนส่งข้อความจะเรียกว่า

  • Publisher — ตัวส่งสาส์น
    ทำหน้าที่ ขับ MSG ออกทางท่อ TOPIC ที่กำหนดไว้ (ออกทางท่อฝั่งส่ง)
    ซึ่ง Publisher จะอยู่ใน Node และจะมีกี่อันก็ได้

คนรับจะเรียกว่า

  • Subscriber — คนรับสาส์น
    ทำหน้าที่ รับ MSG ตามท่อ TOPIC ที่วางไว้ (ท่อฝั่งรับ)

จากการปู้ยี้ปู้ยำ จะได้รูปหน้าตาประมาณนี้

ถ้าดูแล้วตาลาย แล้วก็งงๆ อันนี้เป็นปกติ เพราะจงใจให้ดูงงๆ 55555555555555555555

สังเกตดีๆจะพบว่า ของมันถูกแบ่งเป็นเรื่องๆ และคนอื่นจะมาจิ้มเข้าตรงไหนเพิ่มเติมก็ได้

เห็นได้ชัดเจนว่าการใช้ Message Passing (การส่งข้อความ) แบบนี้เนี่ย

มันช่วยลดความเบลอ ตอนเวลา Code มากๆเลย

ถึงเวลาจะใช้ก็เรียกใช้ ถึงเวลาจะส่งก็ส่ง มันทำให้อะไรๆง่ายขึ้นเยอะ

ที่พูดๆมานี้เรียก ระบบ MESSAGING

ซึ่งจริงๆมี 3 แบบ

  • แบบส่งๆรับๆ ไม่สนใจเงื่อนไขอะไร ส่งก็ส่งไป รับก็รับไป “ส่งแบบต่อเนื่อง”
  • แบบส่ง แล้วรอคำตอบ (รอได้ไม่นานนะ หงุดหงิด เชอะ !)
  • แบบส่งทิ้งไว้ ไม่รอคำตอบ(เพราะต้องรอนาน)
    แต่ถ้ามีคำตอบมาเมื่อไหร่ ค่อยมาบอก

1. ROS MESSAGE (STREAM)

คือการส่ง Message ระหว่าง Node ต่างๆใน ROS

การส่งจะเป็นแบบ Stream ข้อมูลแบบต่อเนื่อง ส่งไป มีคนรับไม่รับไม่รู้ คนส่งมีหน้าที่ส่ง อยากจะส่งเมื่อไร ก็ส่ง

คนรับ ก็รอฟังอย่างเดียว ส่งมาถึงที่ หรือล่มกลางทางก็ไม่รู้ แต่ถ้าได้รับข้อความเมื่อไร ก็ใช้งานผ่าน Receive callback function

ตัวอย่างของจริงๆ ! — ขับหุ่นยนต์ !

สมมติว่าเรามี ฐานหุ่นยนต์อยู่ สามารถสั่งการเป็น

ความเร็วลงไปที่ฐานหุ่นยนต์ได้ ผ่าน Serial Port

เรามี Joystick อยู่ ติดต่อผ่าน Driver ของ Joystick

สิ่งที่เราต้องใช้คือ

  • MOTOR DRIVER NODE
    Node ที่ทำหน้าที่ เขียนคำสั่งความเร็วหุ่นยนต์
    ส่ง แบบ Serial ลงไปตามสาย USB ที่ต่อกับฐานหุ่นยนต์
    เรียกได้ว่าเป็น Low level Communication Node
  • JOYSTICK ACTION MAPPING NODE
    Node ที่ติดต่อกับ Driver Joystick (ดึงค่าปุ่ม ค่าคันโยก)
  • JOYSTICK (DRIVER ของจอย) NODE
    Node ที่ทำหน้าที่แปลงค่าจาก Joystick ให้เป็นความเร็วของหุ่นยนต์

ซึ่งพบว่าพวกนี้ แม่งมักจะมีคนเขียนทิ้งไว้ให้โหลดมาใช้กันฟรีๆ และเป็นของดีที่ test มาแล้ว ( สบายตัวละกู ไม่ต้องเขียนเอง 555555+ )

ตอนนี้เราก็เรียนรู้ concept ของการส่งข้อมูลใน ROS แล้ว

จริงๆแล้วมันยังไม่จบ !

หลังจากที่เราเข้าใจ สิ่งที่เรียกว่า ROS — Message แล้ว
มันเลยเอา Message ไปทำ Operation แบบอื่นๆได้ อีกสองแบบ

คือ
ROS Services
และ
ROS ActionLib (Action Library)

(ซึ่งจริงๆมันก็คือการส่ง ROS Message แหละ แต่เค้าสร้างตัวช่วยขึ้นมาเพิ่ม)

2. ROS Services

เนื่องจาก ROS Message จะเป็นการส่งข้อมูลกันแบบ Stream ต่อเนื่อง

อยากจะส่งก็ส่ง อยากจะหยุดก็หยุด

คนที่ส่งได้ตลอด ก็ส่งตลอด
ไม่สนใจคนรับว่าจะเอาไปใช้งานอะไรไหม

แล้วถ้าอยากทำอะไรแค่ครั้งเดียวล่ะ ขอแค่ทีเดียว

ก็เลยต้องมี Paradigm แบบ Request Response ขึ้นมาบ้าง สำหรับการกระทำบางอย่างที่เราต้องการรอผลลัพธ์ของการ Request เพื่อทำอะไรบางอย่าง

ROS Service เลยทำหน้าที่นี้ คือ การส่ง Message แบบ ไม่เน้นความต่อเนื่อง มี Request มี Response

ตัวอย่างจริงๆก็คือ

ส่ง Request ไปขอ แผนที่จาก Node ที่ถือไฟล์รูปหน่อย

เราสามารถตอบ Request ของ service นี้ว่า สำเร็จหรือไม่สำเร็จก็ได้
เช่น
Request ให้ไปหารูป SORA.jpg แต่ดันไม่มีไฟล์ ก็ตอบ Failed กลับมา
หรือถ้าสำเร็จ ก็ส่ง Array ของรูป คืนกลับไปให้คนขอใช้งาน

หรืออีกตัวอย่าง คือ Request ขอเปิดไฟ
(คงไม่ขอเปิดไฟรัวๆ แบบ Message Stream ใน ROS Message แบบที่ 1)
ก็คือการ request เปิดไฟไป ถ้าเปิดติดแล้ว ก็ return succeed กลับมาให้ ประมาณนี้
แล้วถ้า เปิดอยู่แล้ว ดันสั่งเปิดด้วยเนี่ย ก็ Return failed มา พร้อมข้อความบอกว่า มันเปิดอยู่แล้วเฟร้ยย แบบนี้ก็ได้

คนที่ Request ต้องรอ response เสมอ เหมือนสัญญาใจ ! ห้ามไปคุยกับใครเลย รอเท่านั้น ~!

(จริงๆก็มี Timeout ของการรอนะ แต่ขอเล่า Theme ประมาณนี้ก่อน)

อ้าว แล้วถ้าไม่อยากรอล่ะ

ก็คนรักกันมันไว้ใจได้ เดี๋ยวเค้าก็กลับมาเอง !
ไปใช้ Action Library ไป๊

3. ROS Action Library

สำหรับใช้งานกับ Task ที่ กินเวลาน๊านนาน แล้วไม่อยากรอคำตอบ(นานไป๊) เช่น สั่งให้หุ่นยนต์เดินรอบโลก รอบนึง

ถ้าเป็น Service ก็จะต้องรอคำตอบไปจนกว่าจะมีคน Response (หรือ timeout หมดไป) ได้แห้งตายกันพอดี

Action-lib จะใช้หลักการคือ ส่ง Goal เข้าไป (ส่งเป้าหมาย)
แล้ว คนที่รับเป้าหมายไปทำ สามารถ Report progress มา (เรียก feedback)
และ สามารถ Report เมื่อเป้าหมายถึงจุดที่ต้องสิ้นสุด
( Succeed หรือ Aborted(failed) )

ถ้าเข้าใจ Service มา ในส่วนนี้ก็ไม่ยากเลย ก็คือ Service ที่เราสามารถ ดู Progress ได้ ว่ามันทำถึงไหนแล้ว และ รอคำตอบแบบ Asynchronous (ไม่ได้หยุดทั้งโปรแกรมเพื่อรอ คำตอบนั้นๆ — โปรแกรมทำอย่างอื่นต่อได้ ไว้คำตอบมาเมื่อไร ค่อยมาดูกันว่าจะทำยังไงต่อไป)

ตอนนี้เรามีอาวุธ 3 ชิ้นในมือแล้ว ในการใช้ ROS Framework ของเรา

ทั้งหมดนี้คือความพยายามย่อยในหัวข้อที่ชี้ๆ ให้เป็นภาษาที่คนทั่วไปมาอ่านแล้วพอจะเข้าใจแบบนัวๆ ไม่ลึกมาก ถ้าอยากจะเจาะไปที่ประเด็นเลย
ลองไปอ่านตามลิงค์นี้เน้อ

RECAP : Episode

นี้เราได้รู้ว่า ROS ทำให้เราแบ่งโปรแกรมในตัวหุ่นยนต์ออกเป็นก้อนๆเป็นเรื่องๆได ้
มันสามารถคุยกันด้วย Message ได้ ผ่านทาง Topic
โดยการส่ง Message นั้น
- จะส่งเป็น Stream ก็ได้ (ROS Message)
- จะเป็น Single Operation แบบ Blocking การทำงานตัวเอง เพื่อรอ(ROS Service)
- หรืออาจเป็นการ Dispatch Long term action แบบไม่ Blocking (ROS Action-lib)

โดยทั้ง 3 แบบนี้ จะเป็นรูปแบบสากลในการส่งข้อความแหละ !

เราจะเอาไปทำอะไรดี

มาทำหุ่นยนต์บังคับกันเถอะ !!! [ROS] Part 3 Workspaces (Catkin)

แล้วก็หลอกให้รอ Episode ถัดไปอีกปีนึง 5555555555555555555555555

จะรีบเขียนให้ไวที่สุดเน้ออออ :)

ปุกาศๆๆๆ : ช่วงขายของและ Tie-in

เอ้อ ตอนนี้ ติวทำงานประจำอยู่ที่ Obodroid Corporation นะ
ทำหุ่นยนต์เพื่อใช้งานในที่พักอาศัย
ไม่ว่าจะเป็น Assistant robot , Security robot , Cart Robot

ที่สำคัญสุดคือ !! WE’RE HIRING (ประกาศ ณ. 10–3–2018)

ถ้าอยากทำงานด้านหุ่นยนต์ ไม่ว่าจะเป็น Mechanical engineer , Robotics Software engineer , Perception&ML,Deep,AI Engineer ก็ ลองสมัครเข้ามาได้ :)

ส่ง Resume มาที่ jobs@hiveground.com ได้เลยจย้าา

เอ้อ เพิ่งเขียน About me ด้วยแหละ

--

--

iTUTOR - Theppasith N.
iTUTOR

A Robotics Software Engineer - Not a quick learner , but eager to learn. — http://www.itutor.me