امروزه ماشینهای خودران در مرکز توجه محققان و دانشمندان قرار گرفته است. شرکت های بزرگی اعم از Tesla, Google, NVIDIA و... سرمایه گذاری های زیادی را در این زمینه انجام دادهاند. اهمیت این زمینه تقریبا بر همگان مبرهن است. در حال حاضر، دنیای تکنولوژی رو به سوی هوشمند کردن تمامی ابعاد زندگی دارد. یکی از این ابعاد، حمل و نقل است. در گذشته خطاهای انسانی، بعضا خسارات جبران ناپذیری بر بشر زده است. هوش مصنوعی سعی بر آن دارد تا خطای انسانی را، در عین افزایش بهرهوری از منابع، کاهش دهد. خطاهای رخداده در مسئله حمل و نقل اغلب جبرانناپذیر اند. به طوری که خسارات ناشی از اشتباهات رانندگی بر هیچکس پوشیده نیست. لذا در صورت کاهش دخالت انسان و افزایش دقت عمل، به وسیله هوش مصنوعی، بسیاری از خسارات مالی و غیرمالی کاهش خواهند یافت.
۱. مقدمه
یکی از رویاها و چالشهای همیشگی بشر، سعی در خودکار کردن امور مختلف است. خودران کردن وسایل نقلیه، بر خلاف تصور عموم مردم، سابقه ای دیرینه دارد. به طوری که لئوناردو داوینچی برای اولین بار،سعی در ساخت یک وسیلهی نقلیه خودران داشت.(در بخش کارهای مرتبط به طور اجمالی بررسی خواهد شد.) این تلاش تاکنون ادامه دارد و سرعت پیشرفت آن بسیار زیاد است. پیشرفت حوزه سختافزار، به وجود آمدن فضاهای محاسبات ابری و پردازشات موازی، تاثیر زیادی بر پیشرفت هوش مصنوعی که ابزاری برای توسعه وسایل خودکار است، داشته است. با پیشرفت الگوریتمهای هوش مصنوعی و افزایش تحقیقات در این زمینه، راهحلهای زیادی برای حل این قبیل مسائل شکل گرفت. تاکنون هیچ راه حل کامل و بدون اشکالی برای توسعه اتومبیل های خودران ارائه نشده است. هر کدام از راهحل ها مزایا و معایب خود را دارند. لذا محققین سعی بر آن دارند که با ترکیب راهحلهای موجود و پیشنهاد راهحلهای جدید به جواب مسئله نزدیک و نزدیکتر شوند.
حل مسئله ماشینهای خودران سطوح مختلفی دارد که هر کدام از سطوح، کاربرد مربوط به خود را دارد و بسته به شرایط، برای حل مسئله استفاده خواهد شد. که در ادامه به این سطوح خواهیم پرداخت.
۲. تعاریف رسمی ماشینهای خودران
شاید تعریف یک ماشین خودران ساده به نظر برسد. ماشینی که خودش میراند! ولی اینگونه نیست. با توجه به شرایط و مشخصات محیط، یک ماشین خودکار تعریف میشود. پس سطوح تعریف یک ماشین خودران متفاوت خواهد بود.
سطح ۱ : ماشینهایی که به راننده با تنظیم کردن زاویه فرمان، تنظیم سرعت و ... به وسیله هشدار (مثل بوق و لرزهی صندلی) کمک میکند.1
سطح ۲ : ماشین هایی تمامی ویژگی های سطح ۱ و قابلیت تغییر زاویه فرمان و تنظیم سرعت ماشین به وسیله ترمز،را دارا میباشند. در این نوع ماشین ها، راننده نیز توانایی کنترل ماشین را خواهد داشت.
سطح ۳ : ماشین هایی که تحت شرایط خاص، تمامی کار های مربوط به کنترل ماشین را میتوانند انجام دهند.(مثل پارک دوبل ماشین) در این سطح راننده باید آماده گرفتن کنترل دوباره ماشین باشد.2
سطح ۴ : تفاوت ماشین های سطح ۴ و سطح ۳ به اینگونه است که ماشین های سطح ۴ به قدری قابلاعتماد هستند که نیازی برای کنترل ماشین توسط راننده در شرایط خاص وجود نداشته باشد.
سطح ۵ : ماشینی که تمام کار های مربوط به رانندگی را در تمام شرایط کنترل کند.
در این پروژه قصد پیادهسازی کامل هیچکدام از سطوح را نداریم. بلکه فقط قسمت تغییر زاویه فرمان ماشین، در شرایط مختلف با توجه به مسیر و جاده است. میتوان گفت که این سیستم میتواند قسمتی از یک ماشین خودران سطح ۵ باشد.
۳. کارهای مرتبط
سابفه این کار به مدت های پیش باز میگردد. اولین طراحی وسیلههای نقلیه خودران توسط لئوناردو داوینچی انجام شده است. طراحی او در زمان خودش قابل اجرا نبود. لذا سال ۲۰۰۶ برای اولین بار، موسسه موزه تاریخ علم در فلورانس ایتالیا3، یک مدل عملیاتی از این طرح را ساخت.

اما جدیترین تلاش ها از ۳۰ سال قبل یعنی ۱۹۸۰ شروع شد. در سال ۱۳۸۰ تیم ALV دست به حل مسئله ماشینهای خودران زد. راه حل این گروه، استفاده از بینایی ماشین سنتی برای تشخیص راه درست به وسیله رنگ عکس های ثبت شده به وسیلهی دوربین بود. عکس زیر نمونه ای از نتایج این تحقیقات بود.

ولی این روش در شرایط جادههای نامناسب، آب و هوای غیر مطلود و ... به جواب نخواهد رسید.

راه حل بعدی ۱۰ سال پس از ALV شروع شد. در این فعالیت اولین اقدام به طراحی شبکهعصبی مرتبط با موضوع بوده اند. این پروژه NavLab
نام گرفت . پس از انجام این پروژه به صورت موفقیت آمیزَ شرکت های زیادی روانهی بازار ماشین های خودران شده اند. شرکت های Tesla
و Google
و ... نیز پا در این زمینه نهاده اند.
۴. راهحل پیشنهادی و پیادهسازی شده
برای حل این مسئله، استفاده از یادگیری تقویتی عمیق 4 پیشنهاد میشود. از دلایل استفاده از این روش می توان به عدم نیاز به فرآیند مهندسی ویژگی 5 است. در راه حل های از نوع یادگیری تقویتی6 این فرآیند یکی از مهمترین بخشهای راهحل مسئله است که درصورت وجود خطا در این بخش، بخشهای زیادی از سیستم به درستی عمل نخواهند کرد.
دقت نسبتا بالای مسائل حل شده توسط یادگیری عمیق نیز یکی دیگر از دلایل انتخاب این روش برای حل مسئله است.

۵. پیادهسازی
پیادهسازی این پروژه شامل سه بخش کلی زیر میشود:
۱. پیادهسازی شبیهساز فضای رانندگی
۲. پیادهسازی مدل یادگیری ماشین
۳. پیادهسازی رابط بین شبیهساز و مدل طراحیشده
کد این پروژه در لینک زیر موجود میباشد :
لینک گیتهاب پروژه
وظایف هر یک از بخشهای بالا به شرح زیر میباشد
۵.۱. شبیهساز
به دلیل عدم امکان توسعه، اشکالیابی و ارزیابی چنین سیستمی در فضای حقیقی، بهتر است از یک شبیهساز شرایط استفاده شود تا در صورت نتایج مطلوب، بتوان آن را در سیستمهای واقعی امتحان و ارزیابی کرد.
در این بخش به علت صرفهجویی در زمان و کارایی بهتر تصمیم به استفاده از شبیهساز طراحیشده توسط شرکت Udacity
شد. این شبیهساز با هدف کمک به تسریع در فرآیند طراحی ماشینهای خودران طراحیشده و از امکانات مناسبی برخوردار است.

۵.۲. مدل شبکه عصبی
شاکله اصلی این پروژه شبکه عصبی آن است. وظیفهی این قسمت، یادگیری سیستم و تصمیم گیری بر اساس حالت کنونی است. در این مسئله از ترکیب شبکه های عصبی Dense
و Convolutional
استفادهشده است. طرح زیر نشاندهندهی معماری شبکه عصبی مورد استفاده در برنامه است.

بخشی از کد مربوط به شبکه عصبی که با استفاده از Keras
پیاده سازی شده است به شرح زیر است:
model = Sequential()
model.add(Lambda(lambda x: x/127.5-0.1, input_shape=INPUT_SHAPE))
model.add(Conv2D(24, 5, 5, activation='elu', subsample=(2, 2)))
model.add(Conv2D(36, 5, 5, activation='elu', subsample=(2, 2)))
model.add(Conv2D(48, 5, 5, activation='elu', subsample=(2, 2)))
model.add(Conv2D(64, 3, 3, activation='elu'))
model.add(Conv2D(64, 3, 3, activation='elu'))
model.add(Dropout(args.keep_prob))
model.add(Flatten())
model.add(Dense(100, activation='elu'))
model.add(Dense(50, activation='elu'))
model.add(Dense(10, activation='elu'))
model.add(Dense(1))
چرخه یادگیری و نحوه استفاده از شبکه عصبی در شکل زیر موجود میباشد.

در این چرخه ابتدا یکی از عکسهای از زاویه راست، چپ و وسط انتخاب شده، و سپس یکی از تکنیک های ساخت اطلاعات روی آن اعمال میشود. سپس آن عکس به عنوان ورودی به شبکه عصبی داده میشود. خروجی شبکه عصبی با خروجی مورد انتظار مقایسه شده و مقدار خطا برای بههنگامسازی7 شبکه عصبی با الگوریتم Back Propagation
استفاده خواهد شد.
۵.۳. رابط بین شبیهساز و مدل
یکی از چالشهای پروژه (که در قسمت چالشها نیز بررسی شده است) طراحی رابطی برای ارسال دستورات و اطلاعات بین شبیهساز و مدل بوده است.
عملکرد این رابط به این صورت است که اطلاعات مورد نیاز برای هدایت ماشین را از طریق Socket
از شبیهساز برای شبکه عصبی ارسال کرده و شبکه پس از انجام محاسبات دستور پیش بینی شده برای این اطلعات را به شبیهساز ارسال میکند.

برای طراحی این رابط از کتابخانه Flask
استفاده شده است. قسمتی از کد این رابط به صورت زیر است:
socket = socketio.Server()
app = Flask(__name__)
class Sender:
def __init__(self):
self.image_save = False
def send(self, angle, throttle):
socket.emit("steer", data={'steering_angle': str(angle), 'throttle': str(throttle)}, skip_sid=True)
۶. چالشها
در هر پروژه چالش هایی برای حل مسئله وجود دارد. چالشهای اجرا و پیاده سازی این پروژه عبارتند از:
یادگیری مفاهیم مربوط به ماشینهای خودران
عدم وجود DataSet مناسب و معتبر
پیادهسازی رابط بین شبیه ساز و کد
عدم وجود سختافزار مناسب برای عملیات یادگیری سیستم
برخی از چالشهای بالا با روش های خاصی حل شده اند که در ادامه به طور مختصر به توضیح آنها میپردازیم
۶.۱. یادگیری مفاهیم مربوط به ماشینهای خودران
برای پیادهسازی هر چه بهتر پروژه، لازم بود که با مفاهیم و تاریخچهی ماشین های خودران آشنا شویم. با مطالعه مقالات قدیمی و جدید شناخت نسبی بر مفاهیم کسب شد. ولی مفاهیم به تنهایی برای پیاده سازی کافی نبود. لذا با توجه به نیاز برنامه، به یادگیری Convolutional Neural Network
ها پرداختیم. سپس نحوه استفاده از آنها در بستر Keras
آموخته شد.
۶.۲. عدم وجود DataSet مناسب و معتبر
برای یادگیری مناسب سیستم، نیاز به اطلاعات مناسب از رانندگیهای خوب داریم. ولی این اطلاعات مانند اطلاعات مسئله های دیگر به راحتی در دسترس نیست. لذا برای یادگیری خوب، مجبور بودیم که اطلاعات رانندگی انجام شده توسط اعضای گروه را استخراج کرده و با استفاده از آن سیستم را آموزش داد. ولی مشکل به اینجا ختم نمیشود. اولا ممکن است که رانندگی افراد گروه در شبیه ساز، برای یادگیری شبکه عصبی موجود در برنامه مفید نباشد. دوما علاوه بر امکان اشکال اطلاعات، باز هم حجم اطلاعات مورد نظر کم است. برای مشکلی اول چارهای جز دقت در رانندگی و رعایت برخی اصول اعم از خارج نشدن از مسیر، حفظ سرعت مناسب، چرخش به موقع و ... نیست . ولی برای مشکل دوم در پیاده سازی چاره ای اندیشیده شده است که در ادامه به طور مختصر توضیح داده شده است.
۶.۲.۱. ایجاد اطلاعات جدید با استفاده از اطلاعات استخراج شده
با استفاده از چند تکنیک، اطلاعات جدید و مفیدی را می توان برای یادگیری سیستم ساخت. یکی از روش ها Flip
کردن تصاویر است. همانطور که توضیح داده شده است، ورودی سیستم عکس محیط روبهروی ماشین و خروجی سیستم زاویه فرمان خواهد بود. پس برای یادگیری باید یک چندین عکس از محیط و زاویه فرمان مورد انتظار داشته باشیم. حال بر فرض درست بودن اطلاعات ورودی، در صورت Flip
کردن تصویر میتوان گفت که زاویه فرمان قابل محاسبه خواهد بود. در شبیه ساز استفاده شده برای این پروژه، زوایه های مثبت به معنای چرخانده شدن فرمان به سمت راست و زاویه های منفی به معنای چرخاندهشدن فرمان به سمت چپ است. حال با در اختیار داشتن یک عکس و زاویه فرمان مورد انتظار، با Flip
کردن عکس و قرینه کردن زاویه فرمان،می توانیم اطلاعات جدیدی را ایجاد کنیم. به عنوان مثال اگر زاویه فرمان مناسب برای عکس زیر مقدار ۹.۵ باشد،در آن صورت زاویه فرمان مناسب برای دو عکس بعد مقدار ۹.۵- خواهد بود.


یکی دیگر از روش های ساخت اطلاعات جدید در این پروژه، Shift
تصاویر است. با توجه به اینکه تصاویر و اطلاعات تهیه شده توسط شبیه ساز از سه زاویهی روبهرو، آینهی سمت راست و آینهی سمت چپ است. برای مثال اگر از بخواهیم از عکس زاویه آینهی سمت راست برای یادگیری استفاده کنیم باید کمی عکس را به سمت چپ شیفت داده و مقدار زاویه فرمان را کمی کمتر از زاویه فرمان مورد انتظار کنیم. با این کار در واقع اطلاعات جدیدی برای یادگیری تولید خواهد شد.
۶.۲.۲. اجرای چندباره عملیات یادگیری با استفاده از ترکیب اطلاعات موجود و اطلاعات ساخته شده
درصورت یادگیری سیستم تنها با یک DataSet، در صورت مشاهدهی فضاهای جدید عملکرد مناسبی نخواهد داشت. لذا بهتر است از ترکیب اطلاعات موجود و اطلاعات ساخته شده برای یادگیری استفاده کنیم. در این صورت سیستم در صورت مشاهده حالت های جدید از فضا عملکرد بهتری خواهد داشت.
همچنین اگر عملیات یادگیری چندبار و با ترکیبات مختلف از اطلاعات موجود و اطلاعات ساخته شده انجام شود، یادگیری کاملتر و دقت سیستم بهتر خواهد بود.
۶.۳. پیادهسازی رابط بین شبیهساز و کد
برای فرمان دادن به ماشین که در شبیهساز در حال رانندگی است، باید یک رابط طراحی شود تا بتواند از شبیه ساز اطلاعات فضا و حالت کنونی را دریافت کرده و با توجه به پیادهسازی و راهبرد8 یادگرفته شده، فرامین لازم را به ماشین برای کنترل آن بفرستد. پیاده سازی این رابط با استفاده از SocketIO
پیاده سازی شده است. معماری این رابط به نوعی `رخداد گرا9 است. در رخدادهای مختلف اعم از اتصال، ارسال اطلاعات از شبیهساز و ... تابع های متناسب با آن اتفاق پیادهسازی شده است. برای مثال هنگام رخداد ارسال اطلاعات از سمت شبیهساز، تابع زیر فراخوانی میشود:
@socket.on('telemetry')
def telemetry(sid, data):
if data:
speed = float(data["speed"])
image = Image.open(BytesIO(base64.b64decode(data["image"])))
if sender.image_save:
timestamp = datetime.utcnow().strftime('%Y_%m_%d_%H_%M_%S_%f')[:-3]
image_filename = os.path.join(args.image_folder, timestamp)
image.save('{}.jpg'.format(image_filename))
try:
image = numpy.asarray(image)
image = utils.preprocess(image)
image = numpy.array([image])
steering_angle = float(model.predict(image, batch_size=1))
global speed_limit
if speed > speed_limit:
speed_limit = MIN_SPEED
else:
speed_limit = MAX_SPEED
throttle = 1.0 - steering_angle ** 2 - (speed / speed_limit) ** 2
sender.send(steering_angle, throttle)
except Exception as e:
print(e)
else:
socket.emit('manual', data={}, skip_sid=True)
۶.۴. عدم وجود سختافزار مناسب برای عملیات یادگیری سیستم
در ابتدا قصد اجرای این فرآیند بر بستر Google Colab
را داشتیم. ولی با توجه به اطلاعات تولید شده توسط شبیهساز و وابسته بودن اطلاعات تولید شده به دستگاهی که شبیهساز روی آن اجرا شده است(مثل آدرس عکس های ذخیره شده)،این امکان فراهم نشد. و این چالش حل نشده باقی ماند!
۷. آزمایشها
پس از یادگیریهای متعدد و آزمون و خطا های پیدرپی و یافتن پارامتر های مناسب برای یادگیری شبکه عصبی،اعم از تعداد Epoch
ها، تعداد نمونههای هر Epoch
، مقدار تعیینکننده Dropout
، اندازه Batch Size
و ... به نتیجه زیر برای یادگیری بهتر رسیدیم.
Learning Rate = 1e-4
Test Size = 0.2
Epoch Number = 10
Batch Size = 40
Samples Per Epoch = 30000
Dropout = 0.8
این مقادیر برای پارامتر های شبکه عصبی، لزوما بهترین نتیجه ممکن را به ارمغان نخواهند آورد و ممکن از یک لیست پارامتر بهتر از این لیست وجود داشته باشد.
پس از یادگیری سیستم، حال زمان اجرا و ارزشیابی است. شبیه ساز دارای دو جاده است که یکی از آنها برای رانندگی آسان و دیگری سخت است. ابتدا نتایج اطلاعات ورودی در هر جاده،محاسبه شد. نمودار زیر نشان دهنده درصد فراوانی بازههای زاویه فرمان در طول کل رانندگی است.


پس از اجرای مدل یادگیری شده در دو جاده به نتایج زیر رسیدیم:


همانطور که قابل مشاهده است، در جاده آسان درصد مشابهت ۹۱.۹ ٪ کسب شده است که در نوع خود شگفت انگیز است . در این جاده سیستم توانسته به خوبی از رانندگی فردا استخراج کننده اطلاعات تقلید کند. در این حالت کنترل ماشین در هیچ حالتی با شکست روبهرو نمیشود.
ولی در جاده سخت، درصد تشابه عملکرد انسان و هوش مصنوعی پیادهسازی شده ۵۴.۴ ٪ است. گرچه این درصد بسیار پایین به نظر میرسد، ولی با توجه به مشاهدات، سیستم در این حالت نیز با شکست روبهرو نمیشود و ماشین با موفقیت مسیر خود را ادامه میدهد.
از دیگر نتایج مشهود و قابل ملاحظه، با توجه به نمودارهای بالا، کاهی چرخش های با زاویه بالا در سیستم یادگیری شده است. این موضوع میتواند نشاندهنده امکان افزایش امنیت اتومبیلهای خودران باشد.
۸. نتیجهگیری
با توجه به مشاهدات، میتوان گفت که روشهای یادگیری عمیق برای سیستمهای خودران مناسب نیست. علاوه بر اینکه به اطلاعات بسیار زیادی برای یادگیری برای تمام حالت های ممکن نیاز است، نمیتوان یک ویژگی را به سیستم تحمیل کرد. از آنجا که امنیت خودروهای خودران بسیار هستندَ نیاز است برخی ویژگیهای مهم و بحرانی به آن ها تحمیل شود. ولی در این روش این امکان موجود نیست.
ولی از یادگیری عمیق میتوان در بخشهای کوچک، که از حساسیت کمی برخوردار هستند، در یک ماشین خودران کامل استفاده نمود.
۹. کارهای آینده
۹.۱. کنترل سرعت توسط شبکه عصبی
در حال حاضر، تنها پارامتر رانندگی که از سمت برنامه کنترل میشود، میزان زاویه فرمان است. در برنامه حاضر سرعت ماشین با یک فرمول ثابت که میزان نیروی وارده بر موتور را تعیین میکند مشخص میشود. اگر میزان زاویه فرمان SteeringAngle باشد،میزان نیروی وارده بر موتور (Throttle) با فرمول زیر محاسبه میشود.
که در این Speed سرعت کنونی ماشین، و SpeedLimit بیشترین سرعت ممکن برای ماشین است.
یکی از کارهای آینده میتواند تعیین میزان نیروی وارده بر موتور توسط شبکه عصبی است.
۹.۲. پیادهسازی در محیطها و شبیهسازهای واقعگرایانهتر
پیادهسازی الگوریتم کنونی بر روی شبیهساز Udacity
انجام شدهاست. محیط این شبیهساز نسبتا غیرواقعی و فانتزی به نظر میرسد. برای آزمایش الگوریتم میتوان آن را در محیط های واقع گرایانه امتحان کرد. یکی از دیگر شبیهسازهای این زمینه، شبیهساز AirSim
محصول شرکت مایکروسافت 10 است. محیط این شبیه ساز بسیار واقعگرایانهتر از شبیهساز کنونی است و شرایط بسیار بیشتری را شبیهسازی کرده است. لذا نتایج به دست آمده میتواند به خوبی آزمایش شوند.

۱۰. ابزارهای مورد استفاده
Python
Keras
Udacity Simulator
Github
۱۱. منابع
Project Github Link
End-to-End Deep Learning for Self-Driving Cars
Udacity Self Driving Car Simulator
Udacity Socket Interface Documentation
The First Self Driving Car is 500 Years Old
Levels of autonomy in self-driving cars
AirSim Simulator
Leonardo da vinci's Self-Propelled Cart
ADAS : Advanced Driver Assistance System
ADS : Automated Driving System
Italy’s Institute and Museum of the History of Science in Florence
Deep Reinforcement Learning
Feature Engineering
Reinforcement Learning
Update
Policy
Event-Based
Microsoft