سبق 7.2: کنٹرولر بنانا
اب نفاذ کریں (Implement Now)
آپ کے پاس اپنی تفصیلات (specification) موجود ہے۔ یہ واضح، غیر مبہم، اور جانچ کے قابل ہے۔ اب آپ اس پر عمل درآمد (implement) کرتے ہیں۔
یہ اچھی خبر ہے: آپ نے ہر حصہ پہلے ہی بنا لیا ہے۔ یہ نئے تصورات نہیں ہیں۔ یہ ترکیب (composition) ہے—یعنی جو آپ نے ابواب 4 سے 6 میں سیکھا، اسے ایک مکمل نظام میں جوڑنا۔
- باب 4: پبلشر/سبسکرائبر نوڈز ✅
- باب 5: سروس سرورز اور کسٹم پیغامات ✅
- باب 6: پیرامیٹرز اور لانچ فائلز ✅
آپ موجودہ مہارتوں کو ایک نئے نظام میں منظم کر رہے ہیں۔ یہی پیشہ ور روبوٹکس ڈویلپمنٹ ہے۔
نفاذ کے مراحل (Implementation Phases)
مرحلہ 1: پیکیج اور انٹرفیس بنائیں
آپ کا کام: پیکیج کا ڈھانچہ بنائیں اور کسٹم پیغامات کی تعریف کریں۔
باب 5 سے یاد رکھیں:
- کسٹم پیغامات
robot_controller/msg/TurtleStatus.msgمیں جائیں گے - سروسز
robot_controller/srv/NavigateTo.srvمیں جائیں گی
# ورک اسپیس اور پیکیج بنائیں
mkdir -p turtle_ws/src
cd turtle_ws/src
ros2 pkg create robot_controller --build-type ament_cmake
# میسج اور سروس ڈائریکٹریز بنائیں
mkdir -p robot_controller/msg robot_controller/srv
TurtleStatus.msg (سٹیٹس پبلش کرنے کے لیے کسٹم میسج):
float32 x
float32 y
float32 theta
float32 vel_x
float32 vel_y
float32 battery
NavigateTo.srv (نیویگیشن کی درخواستوں کے لیے سروس):
float32 x
float32 y
float32 theta
---
bool success
float32 time_taken
پیغامات کو مرتب (compile) کرنے کے لیے CMakeLists.txt کو اپ ڈیٹ کریں:
find_package(rosidl_default_generators REQUIRED)
rosidl_generate_interfaces(${PROJECT_NAME}
"msg/TurtleStatus.msg"
"srv/NavigateTo.srv"
)
ament_package()
مرحلہ 2: نیویگیٹر نوڈ کا نفاذ کریں
آپ کا کام: ایک پائتھن نوڈ بنائیں جو سروس کے ذریعے اہداف قبول کرے اور ٹرٹل کو کمانڈ دے۔
باب 4 اور 5 سے یاد رکھیں:
- نوڈز
rclpyسےNodeبیس کلاس استعمال کرتے ہیں - سروسز
Serviceآبجیکٹ استعمال کرتی ہیں - پبلشر پیغامات بھیجتے ہیں
robot_controller/navigator_node.py:
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
from your_package.srv import NavigateTo # صحیح پیکیج کا نام استعمال کریں
import math
import time
class NavigatorNode(Node):
def __init__(self):
super().__init__('navigator')
# ٹرٹل کو کنٹرول کرنے کے لیے پبلشر
self.cmd_vel_pub = self.create_publisher(
Twist, '/turtle1/cmd_vel', 10
)
# نیویگیشن کے اہداف کے لیے سروس سرور
self.navigate_srv = self.create_service(
NavigateTo,
'/navigate_to',
self.navigate_callback
)
# موجودہ حالت کو ٹریک کرنا
self.current_x = 0.0
self.current_y = 0.0
self.current_theta = 0.0
self.get_logger().info('Navigator node started')
def navigate_callback(self, request, response):
"""نیویگیشن کے اہداف کی درخواستوں کو ہینڈل کریں"""
self.get_logger().info(
f'هدف موصول ہوا: x={request.x}, y={request.y}, theta={request.theta}'
)
start_time = time.time()
# ہدف تک فاصلہ حساب کریں (سادہ بنایا گیا)
dx = request.x - self.current_x
dy = request.y - self.current_y
distance = math.sqrt(dx**2 + dy**2)
# ہدف کی طرف بڑھیں (سادہ لکیری حرکت)
# حقیقی نفاذ میں، یہ زیادہ نفیس ہوگا
msg = Twist()
msg.linear.x = 0.2 # 0.2 m/s پر آگے بڑھیں
# فاصلہ/رفتار سیکنڈز کے لیے حرکت کریں (تقریباً)
move_time = distance / 0.2 if distance > 0 else 0.0
end_time = time.time() + move_time
while time.time() < end_time:
self.cmd_vel_pub.publish(msg)
time.sleep(0.1)
# روکیں
msg.linear.x = 0.0
self.cmd_vel_pub.publish(msg)
# حالت کو اپ ڈیٹ کریں (حقیقی نظام میں، یہ اوڈومیٹری سے آئے گا)
self.current_x = request.x
self.current_y = request.y
self.current_theta = request.theta
# جواب
elapsed = time.time() - start_time
response.success = distance < 0.5 # 0.5m کے اندر "کامیابی" ہے
response.time_taken = elapsed
self.get_logger().info(f'هدف {elapsed:.2f}s میں مکمل ہوا')
return response
def main(args=None):
rclpy.init(args=args)
navigator = NavigatorNode()
rclpy.spin(navigator)
navigator.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
اہم نکات:
- سروس کال بیک ہدف کی درخواستوں کو ہینڈل کرتا ہے
- پبلشر ویلوسٹی کمانڈز بھیجتا ہے (باب 4 سے)
- جواب کامیابی اور
time_takenواپس کرتا ہے (باب 5 سے) - حقیقی نفاذ اوڈومیٹری پڑھے گا؛ یہ سادہ ورژن حالت کو ٹریک کرتا ہے
مرحلہ 3: سٹیٹس مانیٹر نوڈ کا نفاذ کریں
آپ کا کام: ایک نوڈ بنائیں جو روبوٹ کی حالت کو مسلسل پبلش کرے۔
باب 4 سے پبلشر پیٹرن یاد رکھیں.
robot_controller/status_monitor_node.py:
import rclpy
from rclpy.node import Node
from your_package.msg import TurtleStatus # کسٹم میسج
import random
class StatusMonitorNode(Node):
def __init__(self):
super().__init__('status_monitor')
# سٹیٹس کے لیے پبلشر
self.status_pub = self.create_publisher(
TurtleStatus,
'/robot/status',
10
)
# ہر 100ms (10 Hz) پر پبلش کرنے کے لیے ٹائمر
self.timer = self.create_timer(0.1, self.publish_status)
# نقلی حالت (حقیقی نظام میں، یہ اوڈومیٹری سے آئے گا)
self.x = 0.0
self.y = 0.0
self.theta = 0.0
self.vel_x = 0.0
self.vel_y = 0.0
self.battery = 100.0
self.get_logger().info('Status Monitor started')
def publish_status(self):
"""ہر 100ms پر سٹیٹس میسج پبلش کریں"""
msg = TurtleStatus()
msg.x = self.x
msg.y = self.y
msg.theta = self.theta
msg.vel_x = self.vel_x
msg.vel_y = self.vel_y
msg.battery = self.battery
self.status_pub.publish(msg)
self.get_logger().debug(f'سٹیٹس: ({self.x:.2f}, {self.y:.2f})')
# بیٹری کے ختم ہونے کی نقل کریں
self.battery = max(0.0, self.battery - 0.1)
def main(args=None):
rclpy.init(args=args)
monitor = StatusMonitorNode()
rclpy.spin(monitor)
monitor.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
اہم نکات:
- باب 5 سے کسٹم میسج
TurtleStatus - ٹائمر 10 Hz پبلیکیشن کو یقینی بناتا ہے (باب 6 کے پیٹرن سے ہر 100ms)
- حالت کا انتظام (پوزیشن، ویلوسٹی، بیٹری کو ٹریک کرتا ہے)
مرحلہ 4: رکاوٹ ڈیٹیکٹر نوڈ کا نفاذ کریں
آپ کا کام: ایک نوڈ بنائیں جو رکاوٹ کا پتہ لگانے کی نقل کرے۔
robot_controller/obstacle_detector_node.py:
import rclpy
from rclpy.node import Node
from sensor_msgs.msg import LaserScan
import random
class ObstacleDetectorNode(Node):
def __init__(self):
super().__init__('obstacle_detector')
# رکاوٹ ڈیٹا کے لیے پبلشر (موک سینسر)
self.obstacle_pub = self.create_publisher(
LaserScan,
'/obstacles',
10
)
# ہر 200ms (5 Hz) پر پبلش کرنے کے لیے ٹائمر
self.timer = self.create_timer(0.2, self.publish_obstacles)
self.scan_counter = 0
self.get_logger().info('Obstacle Detector started')
def publish_obstacles(self):
"""موک رکاوٹ اسکین پبلش کریں"""
msg = LaserScan()
msg.header.stamp = self.get_clock().now().to_msg()
msg.header.frame_id = 'base_link'
msg.angle_min = -1.5708 # -90 ڈگری
msg.angle_max = 1.5708 # +90 ڈگری
msg.angle_increment = 0.0174 # ~1 ڈگری
msg.time_increment = 0.0
msg.range_min = 0.0
msg.range_max = 10.0
# کچھ "پتہ لگانے" کی نقل کریں
ranges = []
num_readings = int((msg.angle_max - msg.angle_min) / msg.angle_increment)
for i in range(num_readings):
# رینڈم فاصلے (زیادہ تر کچھ نہ پانے کی نقل کریں،
# کبھی کبھار رکاوٹیں)
if random.random() > 0.95: # رکاوٹ کا 5% موقع
ranges.append(0.5) # 0.5m پر رکاوٹ
else:
ranges.append(10.0) # کوئی رکاوٹ نہیں (زیادہ سے زیادہ رینج)
msg.ranges = ranges
self.obstacle_pub.publish(msg)
self.scan_counter += 1
if self.scan_counter % 5 == 0: # ہر 5 اسکین پر لاگ کریں
self.get_logger().debug(f'اسکین #{self.scan_counter} پبلش ہوا')
def main(args=None):
rclpy.init(args=args)
detector = ObstacleDetectorNode()
rclpy.spin(detector)
detector.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
اہم نکات:
- معیاری ROS 2 میسج
LaserScanاستعمال کرتا ہے (باب 5 کے علم سے) - 5 Hz پر پبلش کرتا ہے (باب 6 سے 200ms وقفے)
- سسٹم ٹیسٹنگ کے لیے کبھی کبھار رکاوٹوں کی نقل کرتا ہے (5% موقع)
مرحلہ 5: لانچ فائل بنائیں
آپ کا کام: پیرامیٹرز کے ساتھ تمام نوڈز شروع کرنے کے لیے ایک لانچ فائل بنائیں۔
باب 6 سے لانچ فائل کا ڈھانچہ یاد رکھیں۔
robot_controller/launch/start_system.launch.py:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
# نیویگیٹر نوڈ
Node(
package='robot_controller',
executable='navigator',
name='navigator',
output='screen',
parameters=[
{'goal_timeout': 5.0},
]
),
# سٹیٹس مانیٹر نوڈ
Node(
package='robot_controller',
executable='status_monitor',
name='status_monitor',
output='screen',
parameters=[
{'publish_rate': 10},
]
),
# رکاوٹ ڈیٹیکٹر نوڈ
Node(
package='robot_controller',
executable='obstacle_detector',
name='obstacle_detector',
output='screen',
parameters=[
{'scan_rate': 5},
]
),
])
setup.py انٹری پوائنٹس (تاکہ ros2 launch ایگزیکیوٹیبلز تلاش کر سکے):
entry_points={
'console_scripts': [
'navigator=robot_controller.navigator_node:main',
'status_monitor=robot_controller.status_monitor_node:main',
'obstacle_detector=robot_controller.obstacle_detector_node:main',
],
},
پیکیج بنانا اور نوڈز کا تجربہ کرنا (Building and Testing Nodes)
پیکیج بنائیں
cd ~/turtle_ws
colcon build --packages-select robot_controller
source install/setup.bash
انفرادی نوڈز کا تجربہ کریں
ٹرمینل 1: turtlesim شروع کریں
ros2 run turtlesim turtlesim_node
ٹرمینل 2: لانچ فائل شروع کریں
cd ~/turtle_ws
ros2 launch robot_controller start_system.launch.py
ٹرمینل 3: نیویگیشن سروس کو کال کریں
ros2 service call /navigate_to robot_controller/srv/NavigateTo "{x: 5.0, y: 5.0, theta: 0.0}"
ٹرمینل 4: سٹیٹس ٹاپک کی نگرانی کریں
ros2 topic echo /robot/status
ٹرمینل 5: رکاوٹوں کی نگرانی کریں
ros2 topic echo /obstacles
عام انضمام کے مسائل اور ڈیبگنگ (Common Integration Issues & Debugging)
مسئلہ 1: "کسٹم میسج نہیں مل رہا"
علامت: امپورٹ کی خرابی robot_controller.srv.NavigateTo not found
حل:
- دوبارہ بنائیں:
colcon build --packages-select robot_controller - سیٹ اپ سورس کریں:
source install/setup.bash - CMakeLists.txt میں
rosidl_generate_interfacesشامل ہے یا نہیں، چیک کریں
مسئلہ 2: "سروس کال کا وقت ختم ہو جاتا ہے" (Service call times out)
علامت: ros2 service call ہینگ ہو جاتا ہے
حل:
- چیک کریں کہ نوڈ چل رہا ہے:
ros2 node list - چیک کریں کہ سروس موجود ہے:
ros2 service list - سروس کال بیک میں لاگنگ شامل کریں تاکہ معلوم ہو کہ اسے کال کیا جا رہا ہے یا نہیں
- ٹائم آؤٹ بڑھائیں:
ros2 service call /navigate_to ... --timeout 10.0
مسئلہ 3: "ٹاپک پبلش نہیں ہو رہا"
علامت: ros2 topic echo /robot/status کوئی آؤٹ پٹ نہیں دکھاتا
حل:
- چیک کریں کہ پبلشر نوڈ چل رہا ہے:
ros2 node list - ٹاپک کا نام چیک کریں:
ros2 topic list - چیک کریں کہ فریکوئنسی بہت سست تو نہیں ہے (شاید پبلشر چل رہا ہے لیکن ڈیٹا پرانا ہے)
- پبلش کال بیک میں لاگنگ شامل کریں
مسئلہ 4: "ٹرٹل حرکت نہیں کرتا"
علامت: سروس کامیابی واپس کرتی ہے لیکن ٹرٹل ساکن رہتا ہے حل:
- تصدیق کریں کہ
turtlesim_nodeچل رہا ہے اور/turtle1/cmd_velپر سن رہا ہے - دستی طور پر ٹیسٹ کریں:
ros2 topic pub /turtle1/cmd_vel geometry_msgs/Twist "{linear: {x: 0.2}}" - ویلوسٹی کی مقدار چیک کریں (ٹیسٹنگ کے لیے 0.2 m/s معیاری ہے)
- ویلوسٹی کمانڈز کے درمیان تاخیر شامل کریں
تخلیق بمقابلہ ترکیب (Composition vs Creation)
نوٹ کریں: آپ نے نئے تصورات تخلیق نہیں کیے۔ آپ نے موجودہ تصورات کو ترکیب کیا:
| باب سے | تصور | استعمال ہوا |
|---|---|---|
| 4 | پبلشر/سبسکرائبر | نیویگیٹر (pub)، سٹیٹس مانیٹر (pub)، رکاوٹ ڈیٹیکٹر (pub) |
| 5 | سروس پیٹرن | نیویگیٹر سروس سرور (/navigate_to) |
| 5 | کسٹم پیغامات | TurtleStatus میسج |
| 6 | لانچ فائلز | start_system.launch.py جس میں تمام 3 نوڈز شامل ہیں |
| 6 | پیرامیٹرز | goal_timeout, publish_rate, scan_rate |
یہ لایه 3 انٹیلی جنس ڈیزائن ہے: آپ دوبارہ استعمال کے قابل اجزاء لے رہے ہیں اور انہیں جوڑ رہے ہیں۔
AI کے ساتھ کوشش کریں
سیٹ اپ: نفاذ کے دوران مسائل کو ڈیبگ کرنے میں مدد کے لیے ایک چیٹ AI استعمال کریں۔
ڈیبگنگ پرامپٹ:
میں ایک ملٹی-نوڈ ROS 2 سسٹم بنا رہا ہوں۔ یہاں میری تفصیلات ہیں:
[Lesson 7.1 سے اپنی تفصیلات پیسٹ کریں]
جب میں نوڈز چلاتا ہوں تو مجھے یہ خرابی ملتی ہے:
[خرابی کا پیغام پیسٹ کریں]
کیا غلط ہے؟ میں اسے کیسے ٹھیک کروں؟
کوڈ جائزہ پرامپٹ:
یہ میرا navigator_node.py ہے:
[کوڈ پیسٹ کریں]
کیا یہ درست طریقے سے نافذ کرتا ہے:
1. میری تفصیلات سے /navigate_to سروس؟
2. ٹرٹل کو ویلوسٹی کمانڈز پبلش کرنا؟
3. جواب میں کامیابی اور time_taken واپس کرنا؟
کوئی کیڑے یا بہتری؟
متوقع نتیجہ:
- تمام 3 نوڈز بغیر کسی خرابی کے مرتب ہوتے ہیں
- لانچ فائل تمام نوڈز کو بیک وقت شروع کرتی ہے
- سروسز اور ٹاپکس
ros2 service listاورros2 topic listکے ساتھ نظر آتے ہیں - آپ نیویگیشن سروس کو کال کر سکتے ہیں اور ٹرٹل کو رد عمل دیتے ہوئے دیکھ سکتے ہیں
حفاظتی نوٹ: آپ کا AI ایسی خصوصیات تجویز کر سکتا ہے جو تفصیلات سے باہر ہوں (حقیقی راستہ منصوبہ بندی، رکاوٹ سے بچنا، کائنےمیٹک حدود)۔ اپنے سبق 7.1 کے غیر اہداف کو یاد رکھیں۔ اسے سادہ رکھیں—باب 4-6 کے بنیادی pub/sub/service پیٹرن پر توجہ دیں۔
اگلا قدم: سبق 7.3: جانچ اور توثیق →