ΠŸΠ΅Ρ€Π΅ΠΉΡ‚ΠΈ ΠΊ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Π½ΠΈΡŽ

ΠšΡ€Π°Ρ‚ΠΊΠΎΠ΅ руководство ΠΏΠΎ эксплуатации ROS (Robot Operating System)

ROS Introduction (captioned) from Open Robotics on Vimeo.

Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ ROS?

Robot Operating System (ROS) - это Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ с ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ исходным ΠΊΠΎΠ΄ΠΎΠΌ, ΡˆΠΈΡ€ΠΎΠΊΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ Π² исслСдованиях ΠΈ ΠΏΡ€ΠΎΠΌΡ‹ΡˆΠ»Π΅Π½Π½ΠΎΡΡ‚ΠΈ Π² области Ρ€ΠΎΠ±ΠΎΡ‚ΠΎΡ‚Π΅Ρ…Π½ΠΈΠΊΠΈ. ROS прСдставляСт собой Π½Π°Π±ΠΎΡ€ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ ΠΈ инструмСнтов, ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‰ΠΈΡ… Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ прилоТСния для Ρ€ΠΎΠ±ΠΎΡ‚ΠΎΠ². ROS Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Π°Π½Π° для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ Ρ€ΠΎΠ±ΠΎΡ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌΠΈ ΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ°ΠΌΠΈ, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ Π΅Π΅ Π³ΠΈΠ±ΠΊΠΈΠΌ ΠΈ ΠΌΠΎΡ‰Π½Ρ‹ΠΌ инструмСнтом для Ρ€ΠΎΠ±ΠΎΡ‚ΠΎΡ‚Π΅Ρ…Π½ΠΈΠΊΠΎΠ².

ΠšΠ»ΡŽΡ‡Π΅Π²Ρ‹Π΅ особСнности ROS

  1. ΠœΠΎΠ΄ΡƒΠ»ΡŒΠ½Π°Ρ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Π°: ROS ΠΈΠΌΠ΅Π΅Ρ‚ ΠΌΠΎΠ΄ΡƒΠ»ΡŒΠ½ΡƒΡŽ Π°Ρ€Ρ…ΠΈΡ‚Π΅ΠΊΡ‚ΡƒΡ€Ρƒ, ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‰ΡƒΡŽ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ слоТныС систСмы ΠΏΡƒΡ‚Π΅ΠΌ объСдинСния Π½Π΅Π±ΠΎΠ»ΡŒΡˆΠΈΡ… ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹Ρ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΡ‹Ρ… ΡƒΠ·Π»Π°ΠΌΠΈ. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ ΡƒΠ·Π΅Π» ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ выполняСт ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, Π° ΡƒΠ·Π»Ρ‹ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‚ Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ сообщСний Ρ‡Π΅Ρ€Π΅Π· Ρ‚Π΅ΠΌΡ‹ ΠΈΠ»ΠΈ сСрвисы.

  2. ΠšΠΎΠΌΠΌΡƒΠ½ΠΈΠΊΠ°Ρ†ΠΈΠΎΠ½Π½ΠΎΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠ΅ обСспСчСниС: ROS ΠΏΡ€Π΅Π΄Π»Π°Π³Π°Π΅Ρ‚ Π½Π°Π΄Π΅ΠΆΠ½ΡƒΡŽ ΠΊΠΎΠΌΠΌΡƒΠ½ΠΈΠΊΠ°Ρ†ΠΈΠΎΠ½Π½ΡƒΡŽ инфраструктуру, которая ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ мСТпроцСссноС взаимодСйствиС ΠΈ распрСдСлСнныС вычислСния. Π­Ρ‚ΠΎ достигаСтся Π·Π° счСт ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ-подписки для ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² Π΄Π°Π½Π½Ρ‹Ρ… (Ρ‚Π΅ΠΌ) ΠΈ ΠΌΠΎΠ΄Π΅Π»ΠΈ запроса-ΠΎΡ‚Π²Π΅Ρ‚Π° для Π²Ρ‹Π·ΠΎΠ²ΠΎΠ² сСрвисов.

  3. Аппаратная абстракция: ROS обСспСчиваСт ΡƒΡ€ΠΎΠ²Π΅Π½ΡŒ абстракции Π½Π°Π΄ Π°ΠΏΠΏΠ°Ρ€Π°Ρ‚Π½Ρ‹ΠΌ обСспСчСниСм, позволяя Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΊΠΎΠ΄, Π½Π΅ зависящий ΠΎΡ‚ устройства. Π­Ρ‚ΠΎ позволяСт ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΊΠΎΠ΄ с Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ Π°ΠΏΠΏΠ°Ρ€Π°Ρ‚Π½Ρ‹ΠΌΠΈ установками, облСгчая ΠΈΠ½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡŽ ΠΈ экспСримСнты.

  4. Π˜Π½ΡΡ‚Ρ€ΡƒΠΌΠ΅Π½Ρ‚Ρ‹ ΠΈ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚Ρ‹: ROS поставляСтся с Π±ΠΎΠ³Π°Ρ‚Ρ‹ΠΌ Π½Π°Π±ΠΎΡ€ΠΎΠΌ инструмСнтов ΠΈ ΡƒΡ‚ΠΈΠ»ΠΈΡ‚ для Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΈ модСлирования. НапримСр, RViz ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π΄Π°Π½Π½Ρ‹Ρ… Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ² ΠΈ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ состоянии Ρ€ΠΎΠ±ΠΎΡ‚Π°, Π° Gazebo прСдставляСт собой ΠΌΠΎΡ‰Π½ΡƒΡŽ срСду модСлирования для тСстирования Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌΠΎΠ² ΠΈ конструкций Ρ€ΠΎΠ±ΠΎΡ‚ΠΎΠ².

  5. ΠžΠ±ΡˆΠΈΡ€Π½Π°Ρ экосистСма: ЭкосистСма ROS ΠΎΠ±ΡˆΠΈΡ€Π½Π° ΠΈ постоянно развиваСтся, Π² Π½Π΅ΠΉ доступно мноТСство ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ² для Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… робототСхничСских ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ Π½Π°Π²ΠΈΠ³Π°Ρ†ΠΈΡŽ, ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅, восприятиС ΠΈ ΠΌΠ½ΠΎΠ³ΠΎΠ΅ Π΄Ρ€ΡƒΠ³ΠΎΠ΅. БообщСство Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎ участвуСт Π² Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ ΠΈ сопровоТдСнии этих ΠΏΠ°ΠΊΠ΅Ρ‚ΠΎΠ².

Π­Π²ΠΎΠ»ΡŽΡ†ΠΈΡ вСрсий ROS

Π‘ ΠΌΠΎΠΌΠ΅Π½Ρ‚Π° создания Π² 2007 Π³ΠΎΠ΄Ρƒ ROS ΠΏΡ€ΠΎΡˆΠ»Π° Ρ‡Π΅Ρ€Π΅Π· мноТСство вСрсий, Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΠ· ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… появлялись Π½ΠΎΠ²Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΡ для удовлСтворСния растущих потрСбностСй робототСхничСского сообщСства. Π Π°Π·Π²ΠΈΡ‚ΠΈΠ΅ ROS ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚ΡŒ Π½Π° Π΄Π²Π΅ основныС сСрии: ROS 1 ΠΈ ROS 2. Π”Π°Π½Π½ΠΎΠ΅ руководство посвящСно вСрсии ROS 1, извСстной ΠΊΠ°ΠΊ ROS Noetic Ninjemys, которая находится Π½Π° долгосрочной ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ΅ (LTS), ΠΎΠ΄Π½Π°ΠΊΠΎ ΠΊΠΎΠ΄ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΈ с Π±ΠΎΠ»Π΅Π΅ Ρ€Π°Π½Π½ΠΈΠΌΠΈ вСрсиями.

РОБ 1 ΠΏΡ€ΠΎΡ‚ΠΈΠ² РОБ 2

Если ROS 1 обСспСчивала ΠΏΡ€ΠΎΡ‡Π½ΡƒΡŽ основу для Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Ρ€ΠΎΠ±ΠΎΡ‚ΠΎΠ², Ρ‚ΠΎ ROS 2 устраняСт Π΅Π΅ нСдостатки, прСдлагая:

  • ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ: Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π° ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° систСм Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ ΠΈ Π΄Π΅Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ³ΠΎ повСдСния.
  • Π‘Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ: Π£ΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΡΡ‚Π²ΠΎΠ²Π°Π½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π·Π°Ρ‰ΠΈΡ‚Ρ‹ для бСзопасной ΠΈ Π½Π°Π΄Π΅ΠΆΠ½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π² Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… условиях.
  • ΠœΠ°ΡΡˆΡ‚Π°Π±ΠΈΡ€ΡƒΠ΅ΠΌΠΎΡΡ‚ΡŒ: Π£Π»ΡƒΡ‡ΡˆΠ΅Π½Π½Π°Ρ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ° ΠΌΠ½ΠΎΠ³ΠΎΡ€ΠΎΠ±ΠΎΡ‚Π½Ρ‹Ρ… систСм ΠΈ ΠΌΠ°ΡΡˆΡ‚Π°Π±Π½Ρ‹Ρ… Ρ€Π°Π·Π²Π΅Ρ€Ρ‚Ρ‹Π²Π°Π½ΠΈΠΉ.
  • ΠšΡ€ΠΎΡΡΠΏΠ»Π°Ρ‚Ρ„ΠΎΡ€ΠΌΠ΅Π½Π½Π°Ρ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΊΠ°: Π Π°ΡΡˆΠΈΡ€Π΅Π½Π½Π°Ρ ΡΠΎΠ²ΠΌΠ΅ΡΡ‚ΠΈΠΌΠΎΡΡ‚ΡŒ с Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΎΠ½Π½Ρ‹ΠΌΠΈ систСмами, ΠΏΠΎΠΌΠΈΠΌΠΎ Linux, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ Windows ΠΈ macOS.
  • Гибкая коммуникация: ИспользованиС DDS для Π±ΠΎΠ»Π΅Π΅ Π³ΠΈΠ±ΠΊΠΎΠ³ΠΎ ΠΈ эффСктивного мСТпроцСссного взаимодСйствия.

БообщСния ΠΈ Ρ‚Π΅ΠΌΡ‹ ROS

Π’ ROS связь ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ осущСствляСтся с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ сообщСний ΠΈ Ρ‚Π΅ΠΌ. Π‘ΠΎΠΎΠ±Ρ‰Π΅Π½ΠΈΠ΅ - это структура Π΄Π°Π½Π½Ρ‹Ρ…, ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰Π°Ρ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ ΠΎΠ±ΠΌΠ΅Π½ΠΈΠ²Π°ΡŽΡ‚ΡΡ ΡƒΠ·Π»Ρ‹, Π° Ρ‚Π΅ΠΌΠ° - это ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠ°Π½Π°Π», ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΈ ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°ΡŽΡ‚ΡΡ сообщСния. Π£Π·Π»Ρ‹ ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Ρ‚ΡŒ сообщСния Π² Ρ‚Π΅ΠΌΠ΅ ΠΈΠ»ΠΈ ΠΏΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°Ρ‚ΡŒΡΡ Π½Π° сообщСния ΠΈΠ· Ρ‚Π΅ΠΌΡ‹, Ρ‡Ρ‚ΠΎ позволяСт ΠΈΠΌ ΠΎΠ±Ρ‰Π°Ρ‚ΡŒΡΡ Π΄Ρ€ΡƒΠ³ с Π΄Ρ€ΡƒΠ³ΠΎΠΌ. Π­Ρ‚Π° модСль ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ-подписки позволяСт ΠΎΡΡƒΡ‰Π΅ΡΡ‚Π²Π»ΡΡ‚ΡŒ Π°ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½Π½ΡƒΡŽ связь ΠΈ Ρ€Π°Π·Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ. ΠšΠ°ΠΆΠ΄Ρ‹ΠΉ Π΄Π°Ρ‚Ρ‡ΠΈΠΊ ΠΈΠ»ΠΈ ΠΈΡΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ Π² Ρ€ΠΎΠ±ΠΎΡ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ систСмС ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅Ρ‚ Π΄Π°Π½Π½Ρ‹Π΅ Π² Ρ‚Π΅ΠΌΠ΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π·Π°Ρ‚Π΅ΠΌ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Π½Ρ‹ Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ ΡƒΠ·Π»Π°ΠΌΠΈ для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΈΠ»ΠΈ управлСния. Π’ Ρ€Π°ΠΌΠΊΠ°Ρ… Π΄Π°Π½Π½ΠΎΠ³ΠΎ руководства ΠΌΡ‹ рассмотрим сообщСния Image, Depth ΠΈ PointCloud, Π° Ρ‚Π°ΠΊΠΆΠ΅ Ρ‚Π΅ΠΌΡ‹ ΠΊΠ°ΠΌΠ΅Ρ€.

Настройка Ultralytics YOLO с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ROS

Π”Π°Π½Π½ΠΎΠ΅ руководство Π±Ρ‹Π»ΠΎ протСстировано с использованиСм этой срСды ROS, которая являСтся Ρ„ΠΎΡ€ΠΊΠΎΠΌ рСпозитория ROSbot ROS. Π­Ρ‚Π° срСда Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя ΠΏΠ°ΠΊΠ΅Ρ‚ Ultralytics YOLO , ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ Docker для простой настройки, комплСксныС ΠΏΠ°ΠΊΠ΅Ρ‚Ρ‹ ROS ΠΈ ΠΌΠΈΡ€Ρ‹ Gazebo для быстрого тСстирования. Она ΠΏΡ€Π΅Π΄Π½Π°Π·Π½Π°Ρ‡Π΅Π½Π° для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с Husarion ROSbot 2 PRO. ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ ΠΊΠΎΠ΄Π° Π±ΡƒΠ΄ΡƒΡ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² любой срСдС ROS Noetic/Melodic, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ ΠΊΠ°ΠΊ ΡΠΈΠΌΡƒΠ»ΡΡ†ΠΈΡŽ, Ρ‚Π°ΠΊ ΠΈ Ρ€Π΅Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΌΠΈΡ€.

Husarion ROSbot 2 PRO

Установка зависимостСй

Помимо срСды ROS, Π²Π°ΠΌ потрСбуСтся ΡƒΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ зависимости:

  • ΠŸΠ°ΠΊΠ΅Ρ‚ ROS Numpy: Он Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌ для быстрого прСобразования сообщСний ROS Image Π² массивы numpy.

    pip install ros_numpy
    
  • Ultralytics ΠΏΠ°ΠΊΠ΅Ρ‚:

    pip install ultralytics
    

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ultralytics с ROS sensor_msgs/Image

Π‘Π°ΠΉΡ‚ sensor_msgs/Image Ρ‚ΠΈΠΏ сообщСния ΡˆΠΈΡ€ΠΎΠΊΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π² ROS для прСдставлСния Π΄Π°Π½Π½Ρ‹Ρ… изобраТСния. Оно содСрТит поля для ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²ΠΊΠΈ, высоты, ΡˆΠΈΡ€ΠΈΠ½Ρ‹ ΠΈ ΠΏΠΈΠΊΡΠ΅Π»ΡŒΠ½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ Π΅Π³ΠΎ ΠΏΡ€ΠΈΠ³ΠΎΠ΄Π½Ρ‹ΠΌ для ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½Ρ‹Ρ… с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΌΠ΅Ρ€ ΠΈΠ»ΠΈ Π΄Ρ€ΡƒΠ³ΠΈΡ… Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ². БообщСния с изобраТСниями ΡˆΠΈΡ€ΠΎΠΊΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π² робототСхничСских прилоТСниях для Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ Ρ‚Π°ΠΊΠΈΡ… Π·Π°Π΄Π°Ρ‡, ΠΊΠ°ΠΊ Π²ΠΈΠ·ΡƒΠ°Π»ΡŒΠ½ΠΎΠ΅ восприятиС, ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², ΠΈ навигация.

ΠžΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΠΈ сСгмСнтация Π² ROS Gazebo

ПошаговоС использованиС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚ ΠΊΠΎΠ΄Π° дСмонстрируСт, ΠΊΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚ Ultralytics YOLO Π² ROS. Π’ этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ подписываСмся Π½Π° Ρ‚Π΅ΠΌΡƒ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹, ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ входящСС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ YOLO, Π° ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅ΠΌ Π² Π½ΠΎΠ²Ρ‹Π΅ Ρ‚Π΅ΠΌΡ‹ для обнаруТСния ΠΈ сСгмСнтации.

Π‘Π½Π°Ρ‡Π°Π»Π° ΠΈΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠΉΡ‚Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΈ создайтС Π΄Π²Π΅ ΠΌΠΎΠ΄Π΅Π»ΠΈ: ΠΎΠ΄Π½Ρƒ для сСгмСнтация ΠΈ ΠΎΠ΄ΠΈΠ½ для ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅. Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ ΡƒΠ·Π΅Π» ROS (с ΠΈΠΌΠ΅Π½Π΅ΠΌ ultralytics) для обСспСчСния связи с мастСром ROS. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ ΡΡ‚Π°Π±ΠΈΠ»ΡŒΠ½ΠΎΠ΅ соСдинСниС, ΠΌΡ‹ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅ΠΌ ΠΊΠΎΡ€ΠΎΡ‚ΠΊΡƒΡŽ ΠΏΠ°ΡƒΠ·Ρƒ, давая ΡƒΠ·Π»Ρƒ достаточно Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ для установлСния соСдинСния, ΠΏΡ€Π΅ΠΆΠ΄Π΅ Ρ‡Π΅ΠΌ ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠΈΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρƒ.

import time

import rospy

from ultralytics import YOLO

detection_model = YOLO("yolov8m.pt")
segmentation_model = YOLO("yolov8m-seg.pt")
rospy.init_node("ultralytics")
time.sleep(1)

Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ Π΄Π²Π΅ Ρ‚Π΅ΠΌΡ‹ ROS: ΠΎΠ΄Π½Ρƒ для ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΠΈ ΠΎΠ΄ΠΈΠ½ для сСгмСнтация. Π­Ρ‚ΠΈ Ρ‚Π΅ΠΌΡ‹ Π±ΡƒΠ΄ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ для ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ Π°Π½Π½ΠΎΡ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Ρ… ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, дСлая ΠΈΡ… доступными для дальнСйшСй ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. Бвязь ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ осущСствляСтся с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ sensor_msgs/Image сообщСния.

from sensor_msgs.msg import Image

det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)
seg_image_pub = rospy.Publisher("/ultralytics/segmentation/image", Image, queue_size=5)

НаконСц, создайтС подписчика, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠΈΠ²Π°Ρ‚ΡŒ сообщСния Π½Π° /camera/color/image_raw Ρ‚Π΅ΠΌΡƒ ΠΈ Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Π½ΠΎΠ²ΠΎΠ³ΠΎ сообщСния. Π­Ρ‚Π° функция ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π° ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ сообщСния Ρ‚ΠΈΠΏΠ° sensor_msgs/Image, ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΈΡ… Π² массив numpy с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ros_numpyΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ изобраТСния с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ€Π°Π½Π΅Π΅ созданных ΠΌΠΎΠ΄Π΅Π»Π΅ΠΉ YOLO , Π°Π½Π½ΠΎΡ‚ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈΡ… ΠΈ Π·Π°Ρ‚Π΅ΠΌ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅Ρ‚ Π² ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… Ρ‚Π΅ΠΌΠ°Ρ…: /ultralytics/detection/image для обнаруТСния ΠΈ /ultralytics/segmentation/image для сСгмСнтации.

import ros_numpy


def callback(data):
    """Callback function to process image and publish annotated images."""
    array = ros_numpy.numpify(data)
    if det_image_pub.get_num_connections():
        det_result = detection_model(array)
        det_annotated = det_result[0].plot(show=False)
        det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))

    if seg_image_pub.get_num_connections():
        seg_result = segmentation_model(array)
        seg_annotated = seg_result[0].plot(show=False)
        seg_image_pub.publish(ros_numpy.msgify(Image, seg_annotated, encoding="rgb8"))


rospy.Subscriber("/camera/color/image_raw", Image, callback)

while True:
    rospy.spin()
ΠŸΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄
import time

import ros_numpy
import rospy
from sensor_msgs.msg import Image

from ultralytics import YOLO

detection_model = YOLO("yolov8m.pt")
segmentation_model = YOLO("yolov8m-seg.pt")
rospy.init_node("ultralytics")
time.sleep(1)

det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)
seg_image_pub = rospy.Publisher("/ultralytics/segmentation/image", Image, queue_size=5)


def callback(data):
    """Callback function to process image and publish annotated images."""
    array = ros_numpy.numpify(data)
    if det_image_pub.get_num_connections():
        det_result = detection_model(array)
        det_annotated = det_result[0].plot(show=False)
        det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))

    if seg_image_pub.get_num_connections():
        seg_result = segmentation_model(array)
        seg_annotated = seg_result[0].plot(show=False)
        seg_image_pub.publish(ros_numpy.msgify(Image, seg_annotated, encoding="rgb8"))


rospy.Subscriber("/camera/color/image_raw", Image, callback)

while True:
    rospy.spin()
ΠžΡ‚Π»Π°Π΄ΠΊΠ°

ΠžΡ‚Π»Π°Π΄ΠΊΠ° ΡƒΠ·Π»ΠΎΠ² ROS (Robot Operating System) ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ слоТной ΠΈΠ·-Π·Π° распрСдСлСнной ΠΏΡ€ΠΈΡ€ΠΎΠ΄Ρ‹ систСмы. НСсколько инструмСнтов ΠΌΠΎΠ³ΡƒΡ‚ ΠΏΠΎΠΌΠΎΡ‡ΡŒ Π² этом процСссС:

  1. rostopic echo <TOPIC-NAME> : Π­Ρ‚Π° ΠΊΠΎΠΌΠ°Π½Π΄Π° позволяСт ΠΏΡ€ΠΎΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ сообщСния, ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½Π½Ρ‹Π΅ Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΉ Ρ‚Π΅ΠΌΠ΅, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠΌΠΎΠ³Π°Π΅Ρ‚ ΠΈΠ·ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠΎΡ‚ΠΎΠΊ Π΄Π°Π½Π½Ρ‹Ρ….
  2. rostopic list: Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ этой ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ список всСх доступных Ρ‚Π΅ΠΌ Π² систСмС ROS, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ Π²Π°ΠΌ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ прСдставлСниС ΠΎΠ± Π°ΠΊΡ‚ΠΈΠ²Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠ°Ρ… Π΄Π°Π½Π½Ρ‹Ρ….
  3. rqt_graph: Π­Ρ‚ΠΎΡ‚ инструмСнт Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΎΡ‚ΠΎΠ±Ρ€Π°ΠΆΠ°Π΅Ρ‚ Π³Ρ€Π°Ρ„ связи ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ, позволяя ΠΏΠΎΠ½ΡΡ‚ΡŒ, ΠΊΠ°ΠΊ ΡƒΠ·Π»Ρ‹ связаны ΠΌΠ΅ΠΆΠ΄Ρƒ собой ΠΈ ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‚.
  4. Для Π±ΠΎΠ»Π΅Π΅ слоТных Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΉ, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ 3D-прСдставлСния, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ RViz. RViz (ROS Visualization) - это ΠΌΠΎΡ‰Π½Ρ‹ΠΉ инструмСнт 3D-Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ для ROS. Он позволяСт Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ состояниС вашСго Ρ€ΠΎΠ±ΠΎΡ‚Π° ΠΈ Π΅Π³ΠΎ окруТСния Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ. Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ RViz ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€ΠΎΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ Π΄Π°Π½Π½Ρ‹Π΅ Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ² (Π½Π°ΠΏΡ€. sensors_msgs/Image), состояния ΠΌΠΎΠ΄Π΅Π»ΠΈ Ρ€ΠΎΠ±ΠΎΡ‚Π° ΠΈ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Π΅ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Π²ΠΈΠ΄Ρ‹ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ, Ρ‡Ρ‚ΠΎ ΠΎΠ±Π»Π΅Π³Ρ‡Π°Π΅Ρ‚ ΠΎΡ‚Π»Π°Π΄ΠΊΡƒ ΠΈ ΠΏΠΎΠ½ΠΈΠΌΠ°Π½ΠΈΠ΅ повСдСния Ρ€ΠΎΠ±ΠΎΡ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠΉ систСмы.

ΠŸΡƒΠ±Π»ΠΈΠΊΡƒΠΉΡ‚Π΅ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Π΅ классы с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ std_msgs/String

Π‘Ρ‚Π°Π½Π΄Π°Ρ€Ρ‚Π½Ρ‹Π΅ сообщСния ROS Ρ‚Π°ΠΊΠΆΠ΅ Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‚ std_msgs/String сообщСния. Π’ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΡ… прилоТСниях Π½Π΅Ρ‚ нСобходимости ΠΏΠ΅Ρ€Π΅ΠΈΠ·Π΄Π°Π²Π°Ρ‚ΡŒ всС Π°Π½Π½ΠΎΡ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅; вмСсто этого Π½ΡƒΠΆΠ½Ρ‹ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ классы, ΠΏΡ€ΠΈΡΡƒΡ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠ΅ Π² прСдставлСнии Ρ€ΠΎΠ±ΠΎΡ‚Π°. Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ дСмонстрируСт, ΠΊΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ std_msgs/String сообщСния Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΏΠΎΠ²Ρ‚ΠΎΡ€Π½ΠΎ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Π΅ классы Π½Π° /ultralytics/detection/classes Ρ‚Π΅ΠΌΠ°. Π­Ρ‚ΠΈ сообщСния Π±ΠΎΠ»Π΅Π΅ Π»Π΅Π³ΠΊΠΈΠ΅ ΠΈ содСрТат Π²Π°ΠΆΠ½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ, Ρ‡Ρ‚ΠΎ Π΄Π΅Π»Π°Π΅Ρ‚ ΠΈΡ… Ρ†Π΅Π½Π½Ρ‹ΠΌΠΈ для Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ использования

Рассмотрим складского Ρ€ΠΎΠ±ΠΎΡ‚Π°, оснащСнного ΠΊΠ°ΠΌΠ΅Ρ€ΠΎΠΉ ΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ модСль обнаруТСния. ВмСсто Ρ‚ΠΎΠ³ΠΎ Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΡ‚ΠΏΡ€Π°Π²Π»ΡΡ‚ΡŒ ΠΏΠΎ сСти большиС Π°Π½Π½ΠΎΡ‚ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹Π΅ изобраТСния, Ρ€ΠΎΠ±ΠΎΡ‚ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Ρ‚ΡŒ список ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Ρ… классов Π² Π²ΠΈΠ΄Π΅ std_msgs/String сообщСния. НапримСр, ΠΊΠΎΠ³Π΄Π° Ρ€ΠΎΠ±ΠΎΡ‚ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Π΅Ρ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Ρ‚ΠΈΠΏΠ° "ΠΊΠΎΡ€ΠΎΠ±ΠΊΠ°", "ΠΏΠ°Π»Π»Π΅Ρ‚Π°" ΠΈ "Π²ΠΈΠ»ΠΎΡ‡Π½Ρ‹ΠΉ ΠΏΠΎΠ³Ρ€ΡƒΠ·Ρ‡ΠΈΠΊ", ΠΎΠ½ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅Ρ‚ эти классы Π² /ultralytics/detection/classes Ρ‚Π΅ΠΌΠ°. Π­Ρ‚Π° информация ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использована Ρ†Π΅Π½Ρ‚Ρ€Π°Π»ΡŒΠ½ΠΎΠΉ систСмой ΠΌΠΎΠ½ΠΈΡ‚ΠΎΡ€ΠΈΠ½Π³Π° для отслСТивания инвСнтаря Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ, ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ планирования Ρ‚Ρ€Π°Π΅ΠΊΡ‚ΠΎΡ€ΠΈΠΈ двиТСния Ρ€ΠΎΠ±ΠΎΡ‚Π°, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ прСпятствий, ΠΈΠ»ΠΈ для запуска ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… дСйствий, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ Π·Π°Ρ…Π²Π°Ρ‚ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½ΠΎΠΉ ΠΊΠΎΡ€ΠΎΠ±ΠΊΠΈ. Π’Π°ΠΊΠΎΠΉ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ позволяСт ΡΠ½ΠΈΠ·ΠΈΡ‚ΡŒ ΠΏΡ€ΠΎΠΏΡƒΡΠΊΠ½ΡƒΡŽ ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ‚ΡŒ ΠΊΠ°Π½Π°Π»Π° связи ΠΈ ΡΠΎΡΡ€Π΅Π΄ΠΎΡ‚ΠΎΡ‡ΠΈΡ‚ΡŒΡΡ Π½Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ критичСски Π²Π°ΠΆΠ½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ….

ПошаговоС использованиС строк

Π­Ρ‚ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ дСмонстрируСт, ΠΊΠ°ΠΊ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠ°ΠΊΠ΅Ρ‚ Ultralytics YOLO Π² ROS. Π’ этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ подписываСмся Π½Π° Ρ‚Π΅ΠΌΡƒ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹, ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌ входящСС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ YOLO, Π° ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅ΠΌ Π² Π½ΠΎΠ²ΠΎΠΉ Ρ‚Π΅ΠΌΠ΅ /ultralytics/detection/classes ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ std_msgs/String сообщСния. Π‘Π°ΠΉΡ‚ ros_numpy ΠŸΠ°ΠΊΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для прСобразования сообщСния ROS Image Π² массив numpy для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ YOLO.

import time

import ros_numpy
import rospy
from sensor_msgs.msg import Image
from std_msgs.msg import String

from ultralytics import YOLO

detection_model = YOLO("yolov8m.pt")
rospy.init_node("ultralytics")
time.sleep(1)
classes_pub = rospy.Publisher("/ultralytics/detection/classes", String, queue_size=5)


def callback(data):
    """Callback function to process image and publish detected classes."""
    array = ros_numpy.numpify(data)
    if classes_pub.get_num_connections():
        det_result = detection_model(array)
        classes = det_result[0].boxes.cls.cpu().numpy().astype(int)
        names = [det_result[0].names[i] for i in classes]
        classes_pub.publish(String(data=str(names)))


rospy.Subscriber("/camera/color/image_raw", Image, callback)
while True:
    rospy.spin()

ИспользованиС Ultralytics с изобраТСниями Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ ROS

Помимо RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, ROS ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ изобраТСния Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ± удалСнности ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² ΠΎΡ‚ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹. Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ ΠΊΡ€Π°ΠΉΠ½Π΅ Π²Π°ΠΆΠ½Ρ‹ для Ρ‚Π°ΠΊΠΈΡ… робототСхничСских ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, ΠΊΠ°ΠΊ ΠΎΠ±Ρ…ΠΎΠ΄ прСпятствий, 3D-картография ΠΈ локализация.

Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ - это ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ пиксСль ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ прСдставляСт собой расстояниС ΠΎΡ‚ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ Π΄ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Π’ ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‰ΠΈΡ… Ρ†Π²Π΅Ρ‚, изобраТСния Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ ΠΏΡ€ΠΎΡΡ‚Ρ€Π°Π½ΡΡ‚Π²Π΅Π½Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ, позволяя Ρ€ΠΎΠ±ΠΎΡ‚Π°ΠΌ Π²ΠΎΡΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Ρ‚ΡŒ Ρ‚Ρ€Π΅Ρ…ΠΌΠ΅Ρ€Π½ΡƒΡŽ структуру ΠΎΠΊΡ€ΡƒΠΆΠ°ΡŽΡ‰Π΅ΠΉ срСды.

ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹

Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ²:

  1. Π‘Ρ‚Π΅Ρ€Π΅ΠΎΠΊΠ°ΠΌΠ΅Ρ€Ρ‹: ИспользованиС Π΄Π²ΡƒΡ… ΠΊΠ°ΠΌΠ΅Ρ€ для расчСта Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ Π½Π° основС расхоТдСния ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ.
  2. ΠšΠ°ΠΌΠ΅Ρ€Ρ‹ с Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌ ΠΏΡ€ΠΎΠ»Π΅Ρ‚ΠΎΠΌ (ToF): Π˜Π·ΠΌΠ΅Ρ€ΡΡŽΡ‚ врСмя, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ свСт возвращаСтся ΠΎΡ‚ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.
  3. Π”Π°Ρ‚Ρ‡ΠΈΠΊΠΈ структурированного свСта: ΠŸΡ€ΠΎΠ΅Ρ†ΠΈΡ€ΡƒΠΉΡ‚Π΅ рисунок ΠΈ измСряйтС Π΅Π³ΠΎ Π΄Π΅Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ Π½Π° повСрхности.

ИспользованиС YOLO с изобраТСниями Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹

Π’ ROS изобраТСния Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ прСдставлСны с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ sensor_msgs/Image Ρ‚ΠΈΠΏ сообщСния, Π²ΠΊΠ»ΡŽΡ‡Π°ΡŽΡ‰ΠΈΠΉ поля для ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²ΠΊΠΈ, высоты, ΡˆΠΈΡ€ΠΈΠ½Ρ‹ ΠΈ ΠΏΠΈΠΊΡΠ΅Π»ΡŒΠ½Ρ‹Ρ… Π΄Π°Π½Π½Ρ‹Ρ…. ПолС ΠΊΠΎΠ΄ΠΈΡ€ΠΎΠ²ΠΊΠΈ для ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ часто ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ Ρ‚ΠΈΠΏΠ° "16UC1", ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ Π½Π° 16-Π±ΠΈΡ‚Π½ΠΎΠ΅ Ρ†Π΅Π»ΠΎΠ΅ число Π±Π΅Π· Π·Π½Π°ΠΊΠ° Π½Π° пиксСль, Π³Π΄Π΅ ΠΊΠ°ΠΆΠ΄ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ прСдставляСт собой расстояниС Π΄ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Π˜Π·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π² сочСтании с RGB-изобраТСниями для получСния Π±ΠΎΠ»Π΅Π΅ ΠΏΠΎΠ»Π½ΠΎΠ³ΠΎ прСдставлСния ΠΎΠ± ΠΎΠΊΡ€ΡƒΠΆΠ°ΡŽΡ‰Π΅ΠΉ срСдС.

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ YOLO ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Ρ‚ΡŒ ΠΈ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΡΡ‚ΡŒ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΊΠ°ΠΊ ΠΈΠ· RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, Ρ‚Π°ΠΊ ΠΈ ΠΈΠ· ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹. НапримСр, YOLO ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ²Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Π½Π° RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ, ΠΈ это ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ использовано для опрСдСлСния ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… областСй Π½Π° ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹. Π­Ρ‚ΠΎ позволяСт ΠΈΠ·Π²Π»Π΅ΠΊΠ°Ρ‚ΡŒ Ρ‚ΠΎΡ‡Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Π³Π»ΡƒΠ±ΠΈΠ½Π΅ для ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², Ρ€Π°ΡΡˆΠΈΡ€ΡΡ возмоТности Ρ€ΠΎΠ±ΠΎΡ‚Π° ΠΏΠΎ Π²ΠΎΡΠΏΡ€ΠΈΡΡ‚ΠΈΡŽ ΠΎΠΊΡ€ΡƒΠΆΠ°ΡŽΡ‰Π΅ΠΉ срСды Π² Ρ‚Ρ€Π΅Ρ… измСрСниях.

ΠšΠ°ΠΌΠ΅Ρ€Ρ‹ RGB-D

ΠŸΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с изобраТСниями Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠ΅ совмСщСниС RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ ΠΈ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹. ΠšΠ°ΠΌΠ΅Ρ€Ρ‹ RGB-D, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ сСрия Intel RealSense, ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‚ ΡΠΈΠ½Ρ…Ρ€ΠΎΠ½ΠΈΠ·Π°Ρ†ΠΈΡŽ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ RGB ΠΈ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹, Ρ‡Ρ‚ΠΎ ΠΎΠ±Π»Π΅Π³Ρ‡Π°Π΅Ρ‚ объСдинСниС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΈΠ· ΠΎΠ±ΠΎΠΈΡ… источников. Если ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ RGB ΠΈ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹, ΠΎΡ‡Π΅Π½ΡŒ Π²Π°ΠΆΠ½ΠΎ ΠΎΡ‚ΠΊΠ°Π»ΠΈΠ±Ρ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΡ…, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΡ‚ΡŒ Ρ‚ΠΎΡ‡Π½ΠΎΠ΅ Π²Ρ‹Ρ€Π°Π²Π½ΠΈΠ²Π°Π½ΠΈΠ΅.

Π“Π»ΡƒΠ±ΠΈΠ½Π° ПошаговоС использованиС

Π’ этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ ΠΌΡ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ YOLO для сСгмСнтации изобраТСния ΠΈ примСняСм ΠΈΠ·Π²Π»Π΅Ρ‡Π΅Π½Π½ΡƒΡŽ маску для сСгмСнтации ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° Π½Π° ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹. Π­Ρ‚ΠΎ позволяСт Π½Π°ΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ расстояниС ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ пиксСля ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‰Π΅Π³ΠΎ нас ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΎΡ‚ фокусного Ρ†Π΅Π½Ρ‚Ρ€Π° ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹. ΠŸΠΎΠ»ΡƒΡ‡ΠΈΠ² эту ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ расстоянии, ΠΌΡ‹ смоТСм Ρ€Π°ΡΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ расстояниС ΠΌΠ΅ΠΆΠ΄Ρƒ ΠΊΠ°ΠΌΠ΅Ρ€ΠΎΠΉ ΠΈ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ Π² сцСнС. НачнитС с ΠΈΠΌΠΏΠΎΡ€Ρ‚Π° Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Ρ… Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ, создания ΡƒΠ·Π»Π° ROS, инстанцирования ΠΌΠΎΠ΄Π΅Π»ΠΈ сСгмСнтации ΠΈ Ρ‚Π΅ΠΌΡ‹ ROS.

import time

import rospy
from std_msgs.msg import String

from ultralytics import YOLO

rospy.init_node("ultralytics")
time.sleep(1)

segmentation_model = YOLO("yolov8m-seg.pt")

classes_pub = rospy.Publisher("/ultralytics/detection/distance", String, queue_size=5)

Π—Π°Ρ‚Π΅ΠΌ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΎΠ±Ρ€Π°Ρ‚Π½ΠΎΠ³ΠΎ Π²Ρ‹Π·ΠΎΠ²Π°, которая ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ входящСС сообщСниС с ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹. Ѐункция ΠΎΠΆΠΈΠ΄Π°Π΅Ρ‚ сообщСний с ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ ΠΈ RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ, ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ ΠΈΡ… Π² массивы numpy ΠΈ примСняСт модСль сСгмСнтации ΠΊ RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡŽ. Π—Π°Ρ‚Π΅ΠΌ ΠΎΠ½Π° ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅Ρ‚ маску сСгмСнтации для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΈ вычисляСт срСднСС расстояниС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΎΡ‚ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ ΠΏΠΎ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡŽ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹. Π‘ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ² ΠΈΠΌΠ΅ΡŽΡ‚ максимальноС расстояниС, извСстноС ΠΊΠ°ΠΊ расстояниС ΠΊΠ»ΠΈΠΏΠ°, Π·Π° ΠΏΡ€Π΅Π΄Π΅Π»Π°ΠΌΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ значСния ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ inf (np.inf). ΠŸΠ΅Ρ€Π΅Π΄ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ Π²Π°ΠΆΠ½ΠΎ ΠΎΡ‚Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Ρ‚ΡŒ эти Π½ΡƒΠ»Π΅Π²Ρ‹Π΅ значСния ΠΈ ΠΏΡ€ΠΈΡΠ²ΠΎΠΈΡ‚ΡŒ ΠΈΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ 0. НаконСц, ΠΎΠ½ ΠΏΡƒΠ±Π»ΠΈΠΊΡƒΠ΅Ρ‚ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½Ρ‹Π΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ вмСстС с ΠΈΡ… срСдним расстояниСм Π΄ΠΎ /ultralytics/detection/distance Ρ‚Π΅ΠΌΠ°.

import numpy as np
import ros_numpy
from sensor_msgs.msg import Image


def callback(data):
    """Callback function to process depth image and RGB image."""
    image = rospy.wait_for_message("/camera/color/image_raw", Image)
    image = ros_numpy.numpify(image)
    depth = ros_numpy.numpify(data)
    result = segmentation_model(image)

    for index, cls in enumerate(result[0].boxes.cls):
        class_index = int(cls.cpu().numpy())
        name = result[0].names[class_index]
        mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
        obj = depth[mask == 1]
        obj = obj[~np.isnan(obj)]
        avg_distance = np.mean(obj) if len(obj) else np.inf

    classes_pub.publish(String(data=str(all_objects)))


rospy.Subscriber("/camera/depth/image_raw", Image, callback)

while True:
    rospy.spin()
ΠŸΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄
import time

import numpy as np
import ros_numpy
import rospy
from sensor_msgs.msg import Image
from std_msgs.msg import String

from ultralytics import YOLO

rospy.init_node("ultralytics")
time.sleep(1)

segmentation_model = YOLO("yolov8m-seg.pt")

classes_pub = rospy.Publisher("/ultralytics/detection/distance", String, queue_size=5)


def callback(data):
    """Callback function to process depth image and RGB image."""
    image = rospy.wait_for_message("/camera/color/image_raw", Image)
    image = ros_numpy.numpify(image)
    depth = ros_numpy.numpify(data)
    result = segmentation_model(image)

    for index, cls in enumerate(result[0].boxes.cls):
        class_index = int(cls.cpu().numpy())
        name = result[0].names[class_index]
        mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
        obj = depth[mask == 1]
        obj = obj[~np.isnan(obj)]
        avg_distance = np.mean(obj) if len(obj) else np.inf

    classes_pub.publish(String(data=str(all_objects)))


rospy.Subscriber("/camera/depth/image_raw", Image, callback)

while True:
    rospy.spin()

Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ Ultralytics с ROS sensor_msgs/PointCloud2

ΠžΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΠΈ сСгмСнтация Π² ROS Gazebo

Π‘Π°ΠΉΡ‚ sensor_msgs/PointCloud2 Ρ‚ΠΈΠΏ сообщСния это структура Π΄Π°Π½Π½Ρ‹Ρ…, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΠ°Ρ Π² ROS для прСдставлСния Π΄Π°Π½Π½Ρ‹Ρ… 3D ΠΎΠ±Π»Π°ΠΊΠ° Ρ‚ΠΎΡ‡Π΅ΠΊ. Π­Ρ‚ΠΎΡ‚ Ρ‚ΠΈΠΏ сообщСний являСтся Π½Π΅ΠΎΡ‚ΡŠΠ΅ΠΌΠ»Π΅ΠΌΠΎΠΉ Ρ‡Π°ΡΡ‚ΡŒΡŽ робототСхничСских ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ, позволяя Ρ€Π΅ΡˆΠ°Ρ‚ΡŒ Ρ‚Π°ΠΊΠΈΠ΅ Π·Π°Π΄Π°Ρ‡ΠΈ, ΠΊΠ°ΠΊ 3D-ΠΊΠ°Ρ€Ρ‚ΠΎΠ³Ρ€Π°Ρ„ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅, распознаваниС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² ΠΈ локализация.

Облако Ρ‚ΠΎΡ‡Π΅ΠΊ - это Π½Π°Π±ΠΎΡ€ Ρ‚ΠΎΡ‡Π΅ΠΊ Π΄Π°Π½Π½Ρ‹Ρ…, ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½Ρ‹Ρ… Π² Ρ‚Ρ€Π΅Ρ…ΠΌΠ΅Ρ€Π½ΠΎΠΉ систСмС ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚. Π­Ρ‚ΠΈ Ρ‚ΠΎΡ‡ΠΊΠΈ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ собой внСшнюю ΠΏΠΎΠ²Π΅Ρ€Ρ…Π½ΠΎΡΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΈΠ»ΠΈ сцСны, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΡƒΡŽ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ‚Π΅Ρ…Π½ΠΎΠ»ΠΎΠ³ΠΈΠΉ 3D-сканирования. КаТдая Ρ‚ΠΎΡ‡ΠΊΠ° Π² ΠΎΠ±Π»Π°ΠΊΠ΅ ΠΈΠΌΠ΅Π΅Ρ‚ X, Y, ΠΈ Z ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‚ Π΅Π³ΠΎ полоТСнию Π² пространствС, Π° Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΊΠ»ΡŽΡ‡Π°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ, Ρ‚Π°ΠΊΡƒΡŽ ΠΊΠ°ΠΊ Ρ†Π²Π΅Ρ‚ ΠΈ ΠΈΠ½Ρ‚Π΅Π½ΡΠΈΠ²Π½ΠΎΡΡ‚ΡŒ.

БистСма отсчСта

ΠŸΡ€ΠΈ Ρ€Π°Π±ΠΎΡ‚Π΅ с sensor_msgs/PointCloud2ΠŸΡ€ΠΈ этом Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ систСму отсчСта Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠ°, с ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ Π±Ρ‹Π»ΠΈ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Ρ‹ Π΄Π°Π½Π½Ρ‹Π΅ ΠΎΠ±Π»Π°ΠΊΠ° Ρ‚ΠΎΡ‡Π΅ΠΊ. Π˜Π·Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎ ΠΎΠ±Π»Π°ΠΊΠΎ Ρ‚ΠΎΡ‡Π΅ΠΊ снимаСтся Π² систСмС отсчСта Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠ°. Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ эту систСму отсчСта, ΠΏΡ€ΠΎΡΠ»ΡƒΡˆΠ°Π² /tf_static Ρ‚Π΅ΠΌΠ°. Однако Π² зависимости ΠΎΡ‚ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹Ρ… Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Π½ΠΈΠΉ прилоТСния Π²Π°ΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠ½Π°Π΄ΠΎΠ±ΠΈΡ‚ΡŒΡΡ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΠ±Π»Π°ΠΊΠΎ Ρ‚ΠΎΡ‡Π΅ΠΊ Π² Π΄Ρ€ΡƒΠ³ΡƒΡŽ систСму отсчСта. Π­Ρ‚ΠΎ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ tf2_ros ΠΏΠ°ΠΊΠ΅Ρ‚, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ прСдоставляСт инструмСнты для управлСния ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π½Ρ‹ΠΌΠΈ Ρ€Π°ΠΌΠΊΠ°ΠΌΠΈ ΠΈ прСобразования Π΄Π°Π½Π½Ρ‹Ρ… ΠΌΠ΅ΠΆΠ΄Ρƒ Π½ΠΈΠΌΠΈ.

ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ ΠΎΠ±Π»Π°ΠΊΠΎΠ² Ρ‚ΠΎΡ‡Π΅ΠΊ

Облака Ρ‚ΠΎΡ‡Π΅ΠΊ ΠΌΠΎΠ³ΡƒΡ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Ρ‹ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹Ρ… Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ²:

  1. LIDAR (Light Detection and Ranging): Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π»Π°Π·Π΅Ρ€Π½Ρ‹Π΅ ΠΈΠΌΠΏΡƒΠ»ΡŒΡΡ‹ для измСрСния расстояния Π΄ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² ΠΈ создания высокоточных 3D-ΠΊΠ°Ρ€Ρ‚.
  2. ΠšΠ°ΠΌΠ΅Ρ€Ρ‹ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹: Π—Π°Ρ…Π²Π°Ρ‚Ρ‹Π²Π°ΡŽΡ‚ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Π³Π»ΡƒΠ±ΠΈΠ½Π΅ для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ пиксСля, Ρ‡Ρ‚ΠΎ позволяСт Π²ΠΎΡΡΠΎΠ·Π΄Π°Ρ‚ΡŒ 3D-сцСну.
  3. Π‘Ρ‚Π΅Ρ€Π΅ΠΎΠΊΠ°ΠΌΠ΅Ρ€Ρ‹: ИспользованиС Π΄Π²ΡƒΡ… ΠΈΠ»ΠΈ Π±ΠΎΠ»Π΅Π΅ ΠΊΠ°ΠΌΠ΅Ρ€ для получСния ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ Π³Π»ΡƒΠ±ΠΈΠ½Π΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ триангуляции.
  4. Π‘ΠΊΠ°Π½Π΅Ρ€Ρ‹ структурированного свСта: ΠŸΡ€ΠΎΠ΅Ρ†ΠΈΡ€ΡƒΡŽΡ‚ извСстный рисунок Π½Π° ΠΏΠΎΠ²Π΅Ρ€Ρ…Π½ΠΎΡΡ‚ΡŒ ΠΈ ΠΈΠ·ΠΌΠ΅Ρ€ΡΡŽΡ‚ Π΄Π΅Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ для расчСта Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹.

ИспользованиС YOLO с Ρ‚ΠΎΡ‡Π΅Ρ‡Π½Ρ‹ΠΌΠΈ ΠΎΠ±Π»Π°ΠΊΠ°ΠΌΠΈ

Π§Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ YOLO с sensor_msgs/PointCloud2 Для получСния сообщСний Ρ‚Π°ΠΊΠΎΠ³ΠΎ Ρ‚ΠΈΠΏΠ° ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΌΠ΅Ρ‚ΠΎΠ΄, Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½Ρ‹ΠΉ Ρ‚ΠΎΠΌΡƒ, Ρ‡Ρ‚ΠΎ примСняСтся для ΠΊΠ°Ρ€Ρ‚ Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Ρ†Π²Π΅Ρ‚Π΅, Π·Π°Π»ΠΎΠΆΠ΅Π½Π½ΡƒΡŽ Π² ΠΎΠ±Π»Π°ΠΊΠ΅ Ρ‚ΠΎΡ‡Π΅ΠΊ, ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ ΠΈΠ·Π²Π»Π΅Ρ‡ΡŒ Π΄Π²ΡƒΠΌΠ΅Ρ€Π½ΠΎΠ΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ ΡΠ΅Π³ΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ этого изобраТСния с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ YOLO, Π° Π·Π°Ρ‚Π΅ΠΌ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΡƒΡŽ маску ΠΊ Ρ‚Ρ€Π΅Ρ…ΠΌΠ΅Ρ€Π½Ρ‹ΠΌ Ρ‚ΠΎΡ‡ΠΊΠ°ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‰ΠΈΠΉ нас 3D-ΠΎΠ±ΡŠΠ΅ΠΊΡ‚.

Для Ρ€Π°Π±ΠΎΡ‚Ρ‹ с ΠΎΠ±Π»Π°ΠΊΠ°ΠΌΠΈ Ρ‚ΠΎΡ‡Π΅ΠΊ ΠΌΡ‹ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄ΡƒΠ΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Open3D (pip install open3d), удобная Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° Python . Open3D прСдоставляСт Π½Π°Π΄Π΅ΠΆΠ½Ρ‹Π΅ инструмСнты для управлСния структурами Π΄Π°Π½Π½Ρ‹Ρ… ΠΎΠ±Π»Π°ΠΊΠ° Ρ‚ΠΎΡ‡Π΅ΠΊ, ΠΈΡ… Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΈ бСспрСпятствСнного выполнСния слоТных ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΉ. Π­Ρ‚Π° Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠ° ΠΌΠΎΠΆΠ΅Ρ‚ Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΡƒΠΏΡ€ΠΎΡΡ‚ΠΈΡ‚ΡŒ процСсс ΠΈ Ρ€Π°ΡΡˆΠΈΡ€ΠΈΡ‚ΡŒ наши возмоТности ΠΏΠΎ ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΡŽ ΠΈ Π°Π½Π°Π»ΠΈΠ·Ρƒ ΠΎΠ±Π»Π°ΠΊΠΎΠ² Ρ‚ΠΎΡ‡Π΅ΠΊ Π² сочСтании с сСгмСнтациСй Π½Π° основС YOLO.

ПошаговоС использованиС ΠΎΠ±Π»Π°ΠΊΠΎΠ² Ρ‚ΠΎΡ‡Π΅ΠΊ

Π˜ΠΌΠΏΠΎΡ€Ρ‚ΠΈΡ€ΡƒΠΉΡ‚Π΅ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Π΅ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ ΠΈ создайтС модСль YOLO для сСгмСнтации.

import time

import rospy

from ultralytics import YOLO

rospy.init_node("ultralytics")
time.sleep(1)
segmentation_model = YOLO("yolov8m-seg.pt")

Π‘ΠΎΠ·Π΄Π°ΠΉΡ‚Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ pointcloud2_to_array, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΡƒΠ΅Ρ‚ sensor_msgs/PointCloud2 сообщСниС Π² Π΄Π²Π° массива numpy. Массив sensor_msgs/PointCloud2 сообщСния содСрТат n Π±Π°Π»Π»Ρ‹, основанныС Π½Π° width ΠΈ height ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ³ΠΎ изобраТСния. НапримСр. 480 x 640 ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠΌΠ΅Ρ‚ΡŒ 307,200 Ρ‚ΠΎΡ‡ΠΊΠΈ. КаТдая Ρ‚ΠΎΡ‡ΠΊΠ° Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя Ρ‚Ρ€ΠΈ пространствСнныС ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ (xyz) ΠΈ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΉ Ρ†Π²Π΅Ρ‚ Π² RGB Ρ„ΠΎΡ€ΠΌΠ°Ρ‚. Π˜Ρ… ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΡΠΌΠ°Ρ‚Ρ€ΠΈΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ Π΄Π²Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Ρ… ΠΊΠ°Π½Π°Π»Π° ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡ΠΈ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ.

Ѐункция Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ xyz ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ ΠΈ RGB значСния Π² Ρ„ΠΎΡ€ΠΌΠ°Ρ‚Π΅ исходного Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ (width x height). Π‘ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ² ΠΈΠΌΠ΅ΡŽΡ‚ максимальноС расстояниС, извСстноС ΠΊΠ°ΠΊ расстояниС ΠΊΠ»ΠΈΠΏΠ°, Π·Π° ΠΏΡ€Π΅Π΄Π΅Π»Π°ΠΌΠΈ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ³ΠΎ значСния ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΊΠ°ΠΊ inf (np.inf). ΠŸΠ΅Ρ€Π΅Π΄ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΎΠΉ Π²Π°ΠΆΠ½ΠΎ ΠΎΡ‚Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Ρ‚ΡŒ эти Π½ΡƒΠ»Π΅Π²Ρ‹Π΅ значСния ΠΈ ΠΏΡ€ΠΈΡΠ²ΠΎΠΈΡ‚ΡŒ ΠΈΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ 0.

import numpy as np
import ros_numpy


def pointcloud2_to_array(pointcloud2: PointCloud2) -> tuple:
    """
    Convert a ROS PointCloud2 message to a numpy array.

    Args:
        pointcloud2 (PointCloud2): the PointCloud2 message

    Returns:
        (tuple): tuple containing (xyz, rgb)
    """
    pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2)
    split = ros_numpy.point_cloud2.split_rgb_field(pc_array)
    rgb = np.stack([split["b"], split["g"], split["r"]], axis=2)
    xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False)
    xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3))
    nan_rows = np.isnan(xyz).all(axis=2)
    xyz[nan_rows] = [0, 0, 0]
    rgb[nan_rows] = [0, 0, 0]
    return xyz, rgb

Π—Π°Ρ‚Π΅ΠΌ ΠΏΠΎΠ΄ΠΏΠΈΡˆΠΈΡ‚Π΅ΡΡŒ Π½Π° /camera/depth/points Ρ‚Π΅ΠΌΠ° для получСния сообщСния ΠΎΠ± ΠΎΠ±Π»Π°ΠΊΠ΅ Ρ‚ΠΎΡ‡Π΅ΠΊ ΠΈ прСобразования sensor_msgs/PointCloud2 сообщСниС Π² массивы numpy, содСрТащиС ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Ρ‹ XYZ ΠΈ значСния RGB (с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ pointcloud2_to_array функция). ΠžΠ±Ρ€Π°Π±ΠΎΡ‚Π°ΠΉΡ‚Π΅ RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠΎΠ΄Π΅Π»ΠΈ YOLO , Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ΡŒ сСгмСнтированныС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹. Для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΈΠ·Π²Π»Π΅ΠΊΠ°Π΅ΠΌ маску сСгмСнтации ΠΈ примСняСм Π΅Π΅ ΠΊΠ°ΠΊ ΠΊ RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΡŽ, Ρ‚Π°ΠΊ ΠΈ ΠΊ ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚Π°ΠΌ XYZ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² 3D-пространствС.

ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° маски проста, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΎΠ½Π° состоит ΠΈΠ· Π΄Π²ΠΎΠΈΡ‡Π½Ρ‹Ρ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ 1 ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ Π½Π° Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° ΠΈ 0 ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ Π½Π° отсутствиС. Π§Ρ‚ΠΎΠ±Ρ‹ ΠΏΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚ΡŒ маску, просто ΡƒΠΌΠ½ΠΎΠΆΡŒΡ‚Π΅ исходныС ΠΊΠ°Π½Π°Π»Ρ‹ Π½Π° маску. Π­Ρ‚Π° опСрация позволяСт эффСктивно ΠΈΠ·ΠΎΠ»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ½Ρ‚Π΅Ρ€Π΅ΡΡƒΡŽΡ‰ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π½Π° ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΈ. НаконСц, создайтС ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΎΠ±Π»Π°ΠΊΠ° Ρ‚ΠΎΡ‡Π΅ΠΊ Open3D ΠΈ Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€ΡƒΠΉΡ‚Π΅ сСгмСнтированный ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² 3D-пространствС с ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΠΌΠΈ Ρ†Π²Π΅Ρ‚Π°ΠΌΠΈ.

import sys

import open3d as o3d

ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2)
xyz, rgb = pointcloud2_to_array(ros_cloud)
result = segmentation_model(rgb)

if not len(result[0].boxes.cls):
    print("No objects detected")
    sys.exit()

classes = result[0].boxes.cls.cpu().numpy().astype(int)
for index, class_id in enumerate(classes):
    mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
    mask_expanded = np.stack([mask, mask, mask], axis=2)

    obj_rgb = rgb * mask_expanded
    obj_xyz = xyz * mask_expanded

    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((ros_cloud.height * ros_cloud.width, 3)))
    pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((ros_cloud.height * ros_cloud.width, 3)) / 255)
    o3d.visualization.draw_geometries([pcd])
ΠŸΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄
import sys
import time

import numpy as np
import open3d as o3d
import ros_numpy
import rospy

from ultralytics import YOLO

rospy.init_node("ultralytics")
time.sleep(1)
segmentation_model = YOLO("yolov8m-seg.pt")


def pointcloud2_to_array(pointcloud2: PointCloud2) -> tuple:
    """
    Convert a ROS PointCloud2 message to a numpy array.

    Args:
        pointcloud2 (PointCloud2): the PointCloud2 message

    Returns:
        (tuple): tuple containing (xyz, rgb)
    """
    pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2)
    split = ros_numpy.point_cloud2.split_rgb_field(pc_array)
    rgb = np.stack([split["b"], split["g"], split["r"]], axis=2)
    xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False)
    xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3))
    nan_rows = np.isnan(xyz).all(axis=2)
    xyz[nan_rows] = [0, 0, 0]
    rgb[nan_rows] = [0, 0, 0]
    return xyz, rgb


ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2)
xyz, rgb = pointcloud2_to_array(ros_cloud)
result = segmentation_model(rgb)

if not len(result[0].boxes.cls):
    print("No objects detected")
    sys.exit()

classes = result[0].boxes.cls.cpu().numpy().astype(int)
for index, class_id in enumerate(classes):
    mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
    mask_expanded = np.stack([mask, mask, mask], axis=2)

    obj_rgb = rgb * mask_expanded
    obj_xyz = xyz * mask_expanded

    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((ros_cloud.height * ros_cloud.width, 3)))
    pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((ros_cloud.height * ros_cloud.width, 3)) / 255)
    o3d.visualization.draw_geometries([pcd])

БСгмСнтация ΠΎΠ±Π»Π°ΠΊΠΎΠ² Ρ‚ΠΎΡ‡Π΅ΠΊ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ Ultralytics

ЧАБВО Π—ΠΠ”ΠΠ’ΠΠ•ΠœΠ«Π• Π’ΠžΠŸΠ ΠžΠ‘Π«

Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ опСрационная систСма Ρ€ΠΎΠ±ΠΎΡ‚Π° (ROS)?

Robot Operating System (ROS) - это Ρ„Ρ€Π΅ΠΉΠΌΠ²ΠΎΡ€ΠΊ с ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌ исходным ΠΊΠΎΠ΄ΠΎΠΌ, ΡˆΠΈΡ€ΠΎΠΊΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΉ Π² Ρ€ΠΎΠ±ΠΎΡ‚ΠΎΡ‚Π΅Ρ…Π½ΠΈΠΊΠ΅ ΠΈ ΠΏΠΎΠΌΠΎΠ³Π°ΡŽΡ‰ΠΈΠΉ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠ°ΠΌ ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ Π½Π°Π΄Π΅ΠΆΠ½Ρ‹Π΅ прилоТСния для Ρ€ΠΎΠ±ΠΎΡ‚ΠΎΠ². Она прСдоставляСт Π½Π°Π±ΠΎΡ€ Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊ ΠΈ инструмСнтов для создания ΠΈ взаимодСйствия с Ρ€ΠΎΠ±ΠΎΡ‚ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΌΠΈ систСмами, облСгчая Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΡƒ слоТных ΠΏΡ€ΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ. ROS ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ связь ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ сообщСний Ρ‡Π΅Ρ€Π΅Π· Ρ‚Π΅ΠΌΡ‹ ΠΈΠ»ΠΈ сСрвисы.

Как ΠΈΠ½Ρ‚Π΅Π³Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ultralytics YOLO с ROS для обнаруТСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π² Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΌ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ?

Π˜Π½Ρ‚Π΅Π³Ρ€Π°Ρ†ΠΈΡ Ultralytics YOLO с ROS Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π² сСбя настройку срСды ROS ΠΈ использованиС YOLO для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ Π΄Π°Π½Π½Ρ‹Ρ… Π΄Π°Ρ‚Ρ‡ΠΈΠΊΠΎΠ². НачнитС с установки Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹Ρ… зависимостСй, Ρ‚Π°ΠΊΠΈΡ… ΠΊΠ°ΠΊ ros_numpy ΠΈ Ultralytics YOLO :

pip install ros_numpy ultralytics

Π—Π°Ρ‚Π΅ΠΌ создайтС ΡƒΠ·Π΅Π» ROS ΠΈ ΠΏΠΎΠ΄ΠΏΠΈΡˆΠΈΡ‚Π΅ΡΡŒ Π½Π° Ρ‚Π΅ΠΌΡƒ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΠΎΡΡ‚ΡƒΠΏΠ°ΡŽΡ‰ΠΈΠ΅ Π΄Π°Π½Π½Ρ‹Π΅. Π’ΠΎΡ‚ ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€:

import ros_numpy
import rospy
from sensor_msgs.msg import Image

from ultralytics import YOLO

detection_model = YOLO("yolov8m.pt")
rospy.init_node("ultralytics")
det_image_pub = rospy.Publisher("/ultralytics/detection/image", Image, queue_size=5)


def callback(data):
    array = ros_numpy.numpify(data)
    det_result = detection_model(array)
    det_annotated = det_result[0].plot(show=False)
    det_image_pub.publish(ros_numpy.msgify(Image, det_annotated, encoding="rgb8"))


rospy.Subscriber("/camera/color/image_raw", Image, callback)
rospy.spin()

Π§Ρ‚ΠΎ Ρ‚Π°ΠΊΠΎΠ΅ Ρ‚Π΅ΠΌΡ‹ ROS ΠΈ ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ΡΡ Π² Ultralytics YOLO ?

Π’Π΅ΠΌΡ‹ ROS ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‚ связь ΠΌΠ΅ΠΆΠ΄Ρƒ ΡƒΠ·Π»Π°ΠΌΠΈ Π² сСти ROS с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΌΠΎΠ΄Π΅Π»ΠΈ ΠΏΡƒΠ±Π»ΠΈΠΊΠ°Ρ†ΠΈΠΈ-подписки. Π’Π΅ΠΌΠ° - это ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ ΠΊΠ°Π½Π°Π», ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΡƒΠ·Π»Ρ‹ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‚ для асинхронной ΠΎΡ‚ΠΏΡ€Π°Π²ΠΊΠΈ ΠΈ получСния сообщСний. Π’ контСкстС Ultralytics YOLO ΠΌΠΎΠΆΠ½ΠΎ Π·Π°ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΡƒΠ·Π΅Π» ΠΏΠΎΠ΄ΠΏΠΈΡΠ°Ρ‚ΡŒΡΡ Π½Π° Ρ‚Π΅ΠΌΡƒ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ, ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ изобраТСния с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ YOLO для Ρ‚Π°ΠΊΠΈΡ… Π·Π°Π΄Π°Ρ‡, ΠΊΠ°ΠΊ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠ΅ ΠΈΠ»ΠΈ сСгмСнтация, ΠΈ ΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Ρ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹ Π² Π½ΠΎΠ²Ρ‹Ρ… Ρ‚Π΅ΠΌΠ°Ρ….

НапримСр, ΠΏΠΎΠ΄ΠΏΠΈΡˆΠΈΡ‚Π΅ΡΡŒ Π½Π° Ρ‚Π΅ΠΌΡƒ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹ ΠΈ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°ΠΉΡ‚Π΅ входящСС ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ для обнаруТСния:

rospy.Subscriber("/camera/color/image_raw", Image, callback)

Π—Π°Ρ‡Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ изобраТСния Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ с Ultralytics YOLO Π² ROS?

Π“Π»ΡƒΠ±ΠΈΠ½Π½Ρ‹Π΅ изобраТСния Π² ROS, прСдставлСнныС sensor_msgs/ImageОни ΠΏΠΎΠ·Π²ΠΎΠ»ΡΡŽΡ‚ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ расстояниС Π΄ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², находящихся Π½Π° расстоянии ΠΎΡ‚ ΠΊΠ°ΠΌΠ΅Ρ€Ρ‹, Ρ‡Ρ‚ΠΎ ΠΎΡ‡Π΅Π½ΡŒ Π²Π°ΠΆΠ½ΠΎ для Ρ‚Π°ΠΊΠΈΡ… Π·Π°Π΄Π°Ρ‡, ΠΊΠ°ΠΊ ΠΏΡ€Π΅Π΄ΠΎΡ‚Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ столкновСний с прСпятствиями, 3D-ΠΊΠ°Ρ€Ρ‚ΠΎΠ³Ρ€Π°Ρ„ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ ΠΈ локализация. По ссылкС использованиС ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ Π³Π»ΡƒΠ±ΠΈΠ½Π΅ ВмСстС с RGB-изобраТСниями Ρ€ΠΎΠ±ΠΎΡ‚Ρ‹ ΠΌΠΎΠ³ΡƒΡ‚ Π»ΡƒΡ‡ΡˆΠ΅ ΠΏΠΎΠ½ΠΈΠΌΠ°Ρ‚ΡŒ ΠΎΠΊΡ€ΡƒΠΆΠ°ΡŽΡ‰ΡƒΡŽ ΠΈΡ… 3D-срСду.

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ сайта YOLO ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·Π²Π»Π΅ΠΊΠ°Ρ‚ΡŒ маски сСгмСнтации ΠΈΠ· RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ ΠΈ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΈΡ… ΠΊ изобраТСниям Π³Π»ΡƒΠ±ΠΈΠ½Ρ‹ для получСния Ρ‚ΠΎΡ‡Π½ΠΎΠΉ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ 3D-ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°Ρ…, Ρ‡Ρ‚ΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠ°Π΅Ρ‚ ΡΠΏΠΎΡΠΎΠ±Π½ΠΎΡΡ‚ΡŒ Ρ€ΠΎΠ±ΠΎΡ‚Π° ΠΎΡ€ΠΈΠ΅Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ ΠΈ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ с ΠΎΠΊΡ€ΡƒΠΆΠ°ΡŽΡ‰Π΅ΠΉ срСдой.

Как Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ 3D-ΠΎΠ±Π»Π°ΠΊΠ° Ρ‚ΠΎΡ‡Π΅ΠΊ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ YOLO Π² ROS?

Визуализация 3D-ΠΎΠ±Π»Π°ΠΊΠΎΠ² Ρ‚ΠΎΡ‡Π΅ΠΊ Π² ROS с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ YOLO:

  1. ΠšΠΎΠ½Π²Π΅Ρ€Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ sensor_msgs/PointCloud2 сообщСния Π² массивы numpy.
  2. Π˜ΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠΉΡ‚Π΅ YOLO для сСгмСнтации RGB-ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ.
  3. ΠŸΡ€ΠΈΠΌΠ΅Π½ΠΈΡ‚Π΅ маску сСгмСнтации ΠΊ ΠΎΠ±Π»Π°ΠΊΡƒ Ρ‚ΠΎΡ‡Π΅ΠΊ.

Π’ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ использования Open3D для Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ:

import sys

import open3d as o3d
import ros_numpy
import rospy
from sensor_msgs.msg import PointCloud2

from ultralytics import YOLO

rospy.init_node("ultralytics")
segmentation_model = YOLO("yolov8m-seg.pt")


def pointcloud2_to_array(pointcloud2):
    pc_array = ros_numpy.point_cloud2.pointcloud2_to_array(pointcloud2)
    split = ros_numpy.point_cloud2.split_rgb_field(pc_array)
    rgb = np.stack([split["b"], split["g"], split["r"]], axis=2)
    xyz = ros_numpy.point_cloud2.get_xyz_points(pc_array, remove_nans=False)
    xyz = np.array(xyz).reshape((pointcloud2.height, pointcloud2.width, 3))
    return xyz, rgb


ros_cloud = rospy.wait_for_message("/camera/depth/points", PointCloud2)
xyz, rgb = pointcloud2_to_array(ros_cloud)
result = segmentation_model(rgb)

if not len(result[0].boxes.cls):
    print("No objects detected")
    sys.exit()

classes = result[0].boxes.cls.cpu().numpy().astype(int)
for index, class_id in enumerate(classes):
    mask = result[0].masks.data.cpu().numpy()[index, :, :].astype(int)
    mask_expanded = np.stack([mask, mask, mask], axis=2)

    obj_rgb = rgb * mask_expanded
    obj_xyz = xyz * mask_expanded

    pcd = o3d.geometry.PointCloud()
    pcd.points = o3d.utility.Vector3dVector(obj_xyz.reshape((-1, 3)))
    pcd.colors = o3d.utility.Vector3dVector(obj_rgb.reshape((-1, 3)) / 255)
    o3d.visualization.draw_geometries([pcd])

Π­Ρ‚ΠΎΡ‚ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ обСспСчиваСт 3D-Π²ΠΈΠ·ΡƒΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡŽ сСгмСнтированных ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ², Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ»Π΅Π·Π½ΠΎ для Ρ‚Π°ΠΊΠΈΡ… Π·Π°Π΄Π°Ρ‡, ΠΊΠ°ΠΊ навигация ΠΈ ΠΌΠ°Π½ΠΈΠΏΡƒΠ»ΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅.

πŸ“… Π‘ΠΎΠ·Π΄Π°Π½ΠΎ 5 мСсяцСв Π½Π°Π·Π°Π΄ ✏️ ОбновлСно 2 мСсяца Π½Π°Π·Π°Π΄

ΠšΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΈ