مباحث جلسه
stepSimulation()- Time Step
- Real Time
- سرعت شبیهسازی
- مفهوم Simulation Loop
1. اول مشکل کد جلسه قبل
در جلسه ۷ داشتیم:
time.sleep(5)
این فقط به Python میگوید:
۵ ثانیه صبر کن.
اما Simulation را جلو نمیبرد.
یعنی:
time.sleep(5)
↓
فقط منتظر بمان
در مقابل:
p.stepSimulation()
به موتور فیزیک میگوید:
یک گام از Simulation را محاسبه کن.
این تفاوت، هسته اصلی جلسه ۸ است.
2. stepSimulation() چیست؟
فرض کن Simulation را به فریمهای زمانی کوچک تقسیم کنیم:
زمان:
0.000
↓
0.004
↓
0.008
↓
0.012
↓
0.016
↓
...
هر بار که مینویسیم:
p.stepSimulation()
PyBullet یک گام فیزیکی جلو میرود.
پس:
stepSimulation()
↓
محاسبه نیروها
↓
محاسبه حرکت
↓
محاسبه برخوردها
↓
بهروزرسانی وضعیت اجسام
↓
گام بعدی
3. اولین Simulation Loop
حالا main.py را تغییر بده.
import pybullet as p
import pybullet_data
import time
print("Connecting to PyBullet...")
client = p.connect(p.GUI)
print("Connected!")
print("Connection ID:", client)
p.setAdditionalSearchPath(pybullet_data.getDataPath())
# Gravity
p.setGravity(0, 0, -9.81)
# Ground
p.loadURDF("plane.urdf")
# Collision Shape
collision_shape = p.createCollisionShape(
p.GEOM_BOX,
halfExtents=[0.5, 0.5, 0.5]
)
# Visual Shape
visual_shape = p.createVisualShape(
p.GEOM_BOX,
halfExtents=[0.5, 0.5, 0.5]
)
# Object
box_id = p.createMultiBody(
baseMass=1,
baseCollisionShapeIndex=collision_shape,
baseVisualShapeIndex=visual_shape,
basePosition=[0, 0, 2]
)
print("Box created!")
# Simulation Loop
for i in range(1000):
p.stepSimulation()
time.sleep(1 / 240)
p.disconnect(client)
print("Disconnected!")
4. حالا چه اتفاقی افتاد؟
این قسمت:
for i in range(1000):
یعنی:
این کار را ۱۰۰۰ بار انجام بده.
و داخل آن:
p.stepSimulation()
یعنی:
هر بار Simulation را یک گام جلو ببر.
و:
time.sleep(1 / 240)
فعلاً برای این است که اجرای حلقه را با حدود ۲۴۰ گام در ثانیه هماهنگ کنیم.
در نتیجه:
for loop
│
├── stepSimulation()
├── sleep
│
├── stepSimulation()
├── sleep
│
├── stepSimulation()
├── sleep
│
└── ...
حالا باید ببینی مکعب از ارتفاع ۲ متر سقوط میکند و روی زمین قرار میگیرد.
نگران نباش در پایین قراره بیشتر توضیح بدیم تا مطلب جا بیاته
5. Time Step چیست؟
اینجا یک مفهوم بسیار مهم داریم.
فرض کن Time Step برابر باشد با:
1 / 240
یعنی:
0.004166... ثانیه
تقریباً ۴.۱۷ میلیثانیه.
پس اگر:
p.stepSimulation()
را ۲۴۰ بار اجرا کنیم، تقریباً یک ثانیه Simulation را جلو بردهایم.
240 steps
↓
1 second simulation
این را فعلاً به شکل ساده در ذهن داشته باش:
Time Step = مقدار زمانی که Simulation با هر گام جلو میرود.
چرا عدد 240؟
این عدد سرعت حرکت مکعب نیست.
و حتی به این معنی نیست که مکعب باید در یک ثانیه ۲۴۰ بار حرکت کند.
وقتی مینویسیم:
p.stepSimulation()
یعنی:
موتور فیزیک PyBullet یک گام محاسباتی جلو برود.
ما برای شبیهسازی معمولاً از یک Time Step کوچک استفاده میکنیم.
مثلاً:
1/240 second
یعنی:
0.0041667 second
پس اگر Time Step را 1/240 بگیریم:
Simulation:
0 sec
↓
0.00417 sec
↓
0.00833 sec
↓
0.01250 sec
↓
...
240 عددی است که برای Time Step شبیهسازی استفاده میکنیم، نه سرعت مکعب.
پس چرا مکعب یکدفعه یک ثانیه جلو نمیرود؟
فرض کن بگوییم:
مکعب در یک ثانیه از ارتفاع ۲ متر سقوط کند.
اگر موتور فیزیک فقط یک بار در ثانیه وضعیت را محاسبه کند:
t=0
↓
1 ثانیه
↓
t=1
موتور اصلاً نمیداند بین این دو نقطه چه اتفاقی افتاده.
اما فیزیک واقعی پیوسته است.
مکعب:
ارتفاع 2m
↓
1.9m
↓
1.8m
↓
1.7m
↓
...
↓
0m
بنابراین Simulation زمان را به گامهای کوچک تقسیم میکند.
مثلاً:
1 second
───────────────
240 گام
1/240
1/240
1/240
...
این باعث میشود موتور فیزیک بتواند نیرو، سرعت، برخورد و غیره را بهصورت عددی محاسبه کند.
ایا میشه گفت تایم استپ مثل دور کند فلم (Slow Motion) هست تا بفهمیم تو هر مرحله چه اتفاقی میافته؟!
نه . این دو مفهوم را باید جدا کنیم.
240 Hz یا Time Step کوچک برای دقت محاسبات فیزیک است، نه برای آهسته نشان دادن فیلم.
این خیلی مهم است.
مثلاً:
Physics Time Step
≠
Display Speed
یک مثال خیلی ساده
فرض کن یک ماشین واقعی:
سرعت = 1 m/s
یعنی در یک ثانیه:
1 متر
حرکت میکند.
اگر Simulation با:
dt = 1/240
کار کند، در هر گام زمانی، اگر سرعت ثابت باشد:
distance = velocity × dt
پس:
1 × 1/240
=
0.00417 m
یعنی حدود:
4.17 میلیمتر
در هر گام.
نه در هر ثانیه!
در ۲۴۰ گام:
240 × 0.00417 ≈ 1 meter
بنابراین:
هر گام ≈ 4.17 mm
۲۴۰ گام ≈ 1 m
پس آن جمله قبلی من که گفتم «در یک ثانیه 0.00417 متر حرکت میکند» اشتباه بود. مقدار 0.00417 m مربوط به یک گام زمانی بود، نه یک ثانیه.
6. چرا Time Step برای AGV مهم است؟
فرض کن AGV ما با سرعت:
1 m/s
حرکت میکند.
اگر Simulation هر:
1/240 s
محاسبه شود، در هر گام تقریباً:
1 × 1/240
متر حرکت میکند.
یعنی حدود:
0.00417 m
یا:
4.17 mm
پس Simulation میتواند حرکت AGV را به صورت گامهای بسیار کوچک محاسبه کند.
7. Simulation Time با Real Time فرق دارد
این قسمت خیلی مهم است.
دو مفهوم داریم:
Real Time
زمانی که واقعاً روی کامپیوتر میگذرد.
مثلاً:
10:00:00
10:00:01
10:00:02
Simulation Time
زمانی که موتور شبیهسازی جلو میرود.
مثلاً:
0.000
0.004
0.008
0.012
...
این دو الزاماً یکی نیستند.
7.1 سرعت Simulation
فرض کن Simulation ما این باشد:
Simulation Time = 10 seconds
ممکن است کامپیوتر این ۱۰ ثانیه را در:
5 seconds
محاسبه کند.
یعنی:
Real Time = 5 sec
Simulation Time = 10 sec
پس Simulation با سرعت:
2× Real Time
اجرا شده است.
یا برعکس ممکن است کامپیوتر ضعیف باشد و:
Real Time = 20 sec
Simulation Time = 10 sec
در این حالت Simulation کندتر از Real Time است.
8. time.sleep() این وسط چه کار میکند؟
این خط:
time.sleep(1 / 240)
جزء موتور فیزیک PyBullet نیست.
این دستور متعلق به Python است.
یعنی:
Python کمی صبر کن.
ما از آن استفاده میکنیم تا Simulation را به زمان واقعی نزدیک کنیم.
پس این دو را با هم قاطی نکن:
p.stepSimulation()
⬅️ گام فیزیکی Simulation
time.sleep(...)
⬅️ مکث واقعی CPU/برنامه
9. یک آزمایش خیلی خوب
حالا یک بار این را:
time.sleep(1 / 240)
به:
time.sleep(1 / 60)
تغییر بده.
اجرا کن.
بعد:
time.sleep(1 / 1000)
را امتحان کن.
قرار نیست فعلاً از این آزمایش نتیجه دقیق مهندسی بگیریم؛ هدف این است که رابطه سرعت اجرای حلقه با Real Time را ببینی.
11. Product-Oriented Robotics — چرا این موضوع برای محصول مهم است؟
در AGV واقعی ما یک حلقه دائمی داریم:
┌─────────────────────┐
│ Read Sensors │
└──────────┬──────────┘
↓
┌─────────────────────┐
│ Decision / AI │
└──────────┬──────────┘
↓
┌─────────────────────┐
│ Motor Control │
└──────────┬──────────┘
↓
┌─────────────────────┐
│ Update Environment │
└──────────┬──────────┘
↓
Next Cycle
│
└──────────→
در Simulation هم یک حلقه داریم:
stepSimulation()
↓
Physics
↓
Object Position
↓
Collision
↓
Next Step
بعداً این دو حلقه را به هم نزدیک میکنیم.
مثلاً:
PyBullet Simulation
│
▼
Sensor
│
▼
Perception
│
▼
Decision / AI
│
▼
Control
│
▼
AGV Movement
│
└──────────→ Simulation
این دقیقاً همان چیزی است که بعداً برای Digital Twin و Sim-to-Real اهمیت پیدا میکند.
12. یک نکته بسیار مهم برای آینده
فعلاً ما از:
for i in range(1000):
استفاده میکنیم.
اما در پروژه واقعی AGV، نمیخواهیم برنامه بگوییم:
«۱۰۰۰ بار اجرا شو و تمام.»
بلکه یک Simulation Loop دائمی خواهیم داشت:
while True:
# read sensors
# decision
# control
# simulation step
البته بعداً روش حرفهایتر و معماری درستتری برای این کار میسازیم.
جمعبندی جلسه ۸
تا اینجا:
stepSimulation()
یک گام فیزیکی Simulation
Time Step
مقدار زمانی که هر گام Simulation جلو میرود
time.sleep()
مکث واقعی Python
Real Time
زمان واقعی کامپیوتر
Simulation Time
زمان داخل دنیای شبیهسازی
Simulation Loop
Step
↓
Step
↓
Step
↓
Step
↓
...
و در محصول AGV:
Sensors
↓
Perception
↓
Decision
↓
Control
↓
Physics
↓
New State
↓
Sensors
↓
...
این حلقه، یکی از پایهایترین مفاهیم کل پروژه AGV ماست.
فعلاً همین کد را اجرا کن و مهمتر از همه ببین که مکعب واقعاً از ارتفاع ۲ متر سقوط میکند و روی زمین میایستد. بعد از اینکه این را دیدی، میتوانیم بخش بعدی جلسه ۸ را انجام دهیم: چگونه Time Step را خودمان کنترل کنیم و تفاوت Simulation سریع، کند و Real-Time را عملاً آزمایش کنیم.