Программирование приложений на android
Создана: 31 Октября 2011 Пон 13:25:33.
Раздел: "Компьютерный раздел"
Сообщений в теме: 223, просмотров: 34838
-
Пусть мы хотим сделать легкий, ажурный каркас для игры.
Игра имеет два субъекта - квадрокоптер (вертолет с четырьмя винтами по углам крестовины) и игровое поле с границами, которое в общем случае меняется во времени
Как это сделать?
Линейный случай.
Постановка
Перемещение в одном измерении, по оси x. У DRONE есть ультразвуковой сонар который позволяет видеть препятствие на расстоянии 10 метров. Пусть длина площадки 50 метров.
Движение начинается от центра , DRONE набирает скорость до 10 м/сек, на расстоянии 10 метров от препятствия он его видит и начинает торможение. Затормозив, он начинает движение в противоположную сторону.
Алгоритм
Программа запускается периодически с помощью таймера, считывает данные с сонара, определяет состояние, выполняет действия в соответствии с текущим состоянием.
DRONE имеет инерциальную систему отсчета, своей позиции на карте местности. Начальная точка движения DRONE привязана к точке на карте игрового поля. В любой момент времени мы знаем величину вектора из начальной точки в текущую точку.
Субъект DRONE рассчитывает значение вектора положения на линии. -
Drone двигается по линии. Задача - затормозить перед препятствием и начать движение в другую сторону.
Торможение начинается на расстоянии 5 метров от препятствия и продолжается до тех пор пока скорость движения становится маленькой, то есть неопасной для столкновения с препятствием. После этого начинается движение в противоположную сторону
Вместо того чтобы решать дифференциальное уравнение, описывающее процесс торможения можно описать этот процесс в терминах нечеткой логики.
По моему так
Шкала скоростей
1. От бесконечности до 3 метров в секунду - Высокая скорость
2. От 3 м/сек до 0,25 м/сек - Средняя скорость
3. От 0,25 м/сек до нуля - Низкая скорость
Шкала расстояний до препятствия
1. От 5 метров до 2 - Большое расстояние
2. От 2 до 0,5 - Среднее расстояние
3. От 0,5 до 0 - Маленькое расстояние
Шкала ускорений
1. От 10 м/сек^2 до 2 - Высокое
2. От 2 до 0,25 - Среднее
3. От 0,25 до 0 - Низкое
Для управление торможением используется перечень правил , примерно так
-
Для построения модели управления Drone, вместо нечеткой логики я решил использовать другую эвристику - абстракции средней скорости и среднего ускорения.
Способ взаимодействия с Drone : мы можем периодически , через определенный интервал времени считывать данные с датчиков на борту Drone и выдавать ему управляющие команды
В случае торможения суть действий будет состоять в увеличении оборотов одного двигателя и уменьшении оборотов другого
За короткий промежуток времени нельзя увеличить или уменьшить обороты на большую величину, потому что реальные реальные механические системы обладают инерцией. Поэтому надо плавно изменять обороты двигателей
То есть график тормозного ускорения будет иметь вид пика
Время торможения - путь торможения деленный на среднюю скорость движения - t0.
Среднее ускорение торможения - средняя скорость движения деленная на время торможения - a0
Ускорение меняется линейно с временем от нуля до величины 2*a0 и обратно до нуля
Пусть начальная скорость Drone - 10 м/сек, расстояние до препятствия - 1 метр.
Чтобы снизить вероятность столкновения надо добиться нулевой скорости не доходя скажем 20 см до препятствия. Тогда расстояние будем считать равным 0,8 метра.
Время движения до препятствия равно расстояние деленное на скорость. Скорость во время торможения будет падать скажем линейно от времени (хотя на самом деле график скорости будет иметь форму тангенсоиды, потому что ускорение торможения будет нарастать постепенно к середине пути , а затем также постепенно уменьшаться) . Поэтому используя среднюю скорость движения можно вычислить время в пути.
Предположим, что средняя скорость равна половине начальной, т.е. 5 м/сек. Тогда время в пути 0,8/5 = 0,16 сек
Среднее ускорение необходимое для торможения равно начальной скорости деленной на время движения
a = v/t = 10 м/сек / 0,16 = 62,5 м/сек^2
Пусть мы имеем возможность через каждые 0,005 секунды изменять тормозящее ускорение. Тогда нам надо 16 раз увеличить ускорение от от нуля до 125 м/сек^2 , а потом 16 раз уменьшить ускорение от 125 до нуля.
Получается что каждый раз через интервал времени 0,005 секунды нам надо сначала увеличивать ускорение на 7,8125 м/сек^2, а затем уменьшать на эту же величину тоже 16 раз
Предполагается, что время в течении которого изменяется ускорение пренебрежимо мало по сравнению с величиной интервалом дискретизации. Допустим наше устройство может менять ускорение на нужную величину за время равное сотой части от величины интервала дискретизации , то есть за время 0,0005 секунды
Код:
package kz.drone;
import java.util.Timer;
import java.util.TimerTask;
public class Tormoz {
/**
* @param args
*/
public static void main(String args[]) throws java.io.IOException {
TimerTask task = new TimerTask() {
float x=0.8f;
float v=10;
float a=0; // начальная скорость
float dt = 0.005f;
float vs=v/2;
float t=x/vs;
float as=v/t;
float n = t / dt;
float da=4*as/n;
float vt=v;
public void run() {
if (vt>v/2) a = a + da; else a = a - da;
vt = vt - a*dt;
x = x - vt*dt;
if (a<0){
cancel();
}
else
{
System.out.println("Ускорение: "+a);
System.out.println("Скорость: "+vt);
System.out.println("Расстояние: "+ x);
}
}
};
Timer timer = new Timer();
timer.schedule(task, 0, 5);
// System.out.println("Press ENTER to stop");
// System.in.read(new byte[10]);
// timer.cancel();
}
}
-
-
Android NDK — дополнение к Android SDK предназначенное для написания участков кода требующих высокой производительности на языках C и C++. Хочется обратить внимание что, к сожалению, полностью написать приложение на C/C++ нам не позволят, всё равно написанные нами библиотеки будут вызываться из Java кода.
Java Native Interface (JNI) — стандартный механизм для запуска кода, под управлением виртуальной машины Java (JVM), который написан на языках С/С++ или Ассемблера, и скомпонован в виде динамических библиотек, позволяет не использовать статическое связывание. ©Wikipedia
Cygwin — UNIX-подобная среда и интерфейс командной строки для Microsoft Windows. Cygwin обеспечивает тесную интеграцию Windows приложений, данных и ресурсов с приложениями, данными и ресурсами UNIX-подобной среды.©Wikipedia
[внешняя ссылка] -
karaganda писал : Приложения для Android теперь можно писать на C/C++
Уже сто лет в обед как можно.
karaganda писал : Хочется обратить внимание что, к сожалению, полностью написать приложение на C/C++ нам не позволят, всё равно написанные нами библиотеки будут вызываться из Java кода.
Кто это не позволит? Начиная с 2.3 можно писать полностью нативные приложения без единой строчки на яве. -
rock88,
Значит наврал, извиняюсь. Раньше не сталкивался с такой задачей
Хорошая статья про JNI
[внешняя ссылка] -
Понимание пути к классу и имен пакета
Классы Java организуются в пакеты, которые отображаются на каталоги в файловой системе. Но, в отличие от файловой системы, всякий раз, когда Вы определяете имя пакета, Вы определяете целое имя пакета - никогда часть его. Например, имя пакета для java.awt.Button всегда определяется как java.awt.
Например, предположите, что Вы хотите, чтобы Среда выполнения Java сочла класс названным Cool.class в пакете utility.myapp. Если путь к тому каталогу /java/MyClasses/utility/myapp, Вы установили бы путь к классу так, чтобы он содержал /java/MyClasses.
Чтобы выполнить то приложение, Вы могли использовать следующую команду JVM:
% java -classpath /java/MyClasses utility.myapp.Cool
[внешняя ссылка]
Комментарии
Задача : Создать файл заголовка при том, что уже скомпилирован файл .class из файла .java
Вот текст исходной программы на java
Код: package m.pack;
public class C
{
static
{
System.loadLibrary("megalib");
}
native public static void printOne();
}
Действия : Используем команду javah.
Если записать команду так : "javah -jni m.pack.C", то получим сообщение :
Error : Could not find class file for 'm.pac.C'
Допустим класс над которым выполняется процедура является частью пакета my.pack. Тогда для корректной работы нужно создать структуру папок classes\my\pack, туда положить файл C.class и для переменной среды classpath задать значение пути до каталога classes от корня логического диска.
set classpath=d:\dev\android\workspaces\classes
В общем случае надо еще указать пути к библиотекам базовых классов, они у меня находятся в папке d:\android-16\
тогда имеем для переменной такое значение
set classpath=d:\dev\android\workspaces\test\bin\classes;d:\android-16\* -
-
Вот она, Америка - заморская страна,
По наклонной плоскости все катится она
И Статую Свободы - ненужный атрибут
На аукционе скоро продадут
Получил квадрокоптер на почте. Посылка пришла из US
Полетал сейчас на квадрокоптере в квартире. Подъем-посадка.
Управляемость отличная.
Для детей старше 14 лет (в инструкции так написано) - рекомендую -
Пишем приложение на java с использованием библиотеки на С, для android
Есть существенная разница между компиляторами языков java и С. Компилятор java делает код понятный для виртуальной java машины, которая преобразует его в код конкретной платформы, то есть в машинный код. Компилятор языка С сразу делает машинный код, то есть для каждой платформы у языка должен быть свой компилятор.
Систематического руководства по этой задаче не нашел. Английский мой - нулевой. Погрузился в "поток сознания" русского сегмента. Как говорится - аллах акбар.
Эту проблему для приложений на android решает пакет NDK.
В общем надо его скачать, он существует в виде архива и распаковать в любое удобное место.
Кроме NDK все советуют использовать пакет Sequoyah
Чтобы его установить делаем в eclipse : Help - Install New Software, далее в поле Work with определяем адрес сетевой сервера откуда скачиваем пакет - Indigo repository - [внешняя ссылка]
Внизу появляется список, раскрываем пакет - Mobile and Device Development, и в нем выбираем "Sequoyah Android Native Code Support". Я не стал разбираться и отметил все позиции со словом Sequoyah
Говорят, что eclipse использует для компиляции и сборки команду make и типа под windows можно сделать эмулятор linux c помощью cygwin. Сходил на сайт [внешняя ссылка] и установил его. Потренировался в создании библиотек и написании make-файлов
Надо задать NDK location. Для этого в главном меню eclipse выбираем команду window - Preferences. Потом в диалоге Android - Native Development и NDK
Собственно из приготовительных работ все.
В качестве шаблона проекта использовал "hello-jni" из папки samples в NDK
Сборка проекта. Создал проект hello-jni, скопировал туда файлы из шаблона. Выполнил операцию Add Native Support. Чтобы ее выполнить выделяем корневую папку проекта в окне "Project Explorer" eclipse, затем вызываем контекстное меню, правой кнопкой мыши, далее в списке команд ищем "Add Native Support", у меня их там две , выбираем ту которая со зеленным значком слева от текста.
Теперь смотрим за изменениями в составе проекта. Оказывается появилась новая папка - "jni". В ней два файла - текст библиотеки на С и make-файл Amdroid.mk
Кроме того если повезет появится еще папка include и в ней список путей к папкам.c заголовочными файлами Я говорю так потому что у меня eclipse на двух машинах. На одной после операции создается папка include и в нее помещаются каталоги с заголовочными файлами, а на другой нет. Почему так происходит - не знаю.
Если не повезло придется самому писать пути. Делается это так. Выделяем корневую папку проекта, потом вызываем контекстное меню и там команду Properties. Выбираем C/C++ General - Paths and Symbols
У меня к этому проекты определенны такие пути к include :
D:/dev/android/android-ndk-r8b/platforms/android-14/arch-mips/usr/include
D:/dev/android/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/lib/gcc/arm-linux-androideabi/4.6.x-google/include
D:/dev/android/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/windows/lib/gcc/arm-linux-androideabi/4.6.x-google/include-fixed
D:/dev/android/android-ndk-r8b/sources/cxx-stl/system/include
Теперь берем из шаблона NDK содержимое для файла библиотеки hello-jni.
Далее надо создать заголовочный файл для HelloJni.class. Для этого определяем значение classpath и выполняем создание заголовка с помощью javah. Я делаю это в командной строке Far. Получается две команды
>set classpath=d:\dev\android\workspaces\hello-jni\bin\classes;d:\android-16\*
>javah -jni com.example.hellojni.HelloJni
После чего имеем в текущей папке файл com_example_hellojni_HelloJni.h. Копируем его в папку jni проекта. Для вставки выделяю папку jni в "Project Explorer" eclipse
Собственно все. Осталось создать динамическую библиотеку. Тут тоже несколько путей. Как вариант - в среде Far делаю текущим каталог проекта и выполняю команду ndk-build.cmd
После этого запускаю проект - Run. Все -
Технические применения Ar Drone
Из-за низкой стоимости, большого количества установленных сенсоров и приборов, а так же открытому API, AR Drone стал популярной платформой для научных и образовательных целей.
Он применяется в экспериментах по автоматическому управлению, обучению ИИ, автономномному видеонаблюдению, взаимодействию человек-машина, и т.д.
[внешняя ссылка] -
Вот, для примера , как можно AR.Dron`ом управлять из командной строки в Windows
—————————————————
[внешняя ссылка]
AT commands, UDP ports and Video format - Добавил(а) MAPGPS
I just wrote a simple Java app to control AR.Drone directly via AT commands. It can run on Windows XP (DOS prompt) or any other platforms with Java installed.
Код: /*
UI_BIT:
00010001010101000000000000000000
| | | | | || | ||||+—0: Button turn to left
| | | | | || | |||+—-1: Button altitude down (ah - ab)
| | | | | || | ||+——2: Button turn to right
| | | | | || | |+——-3: Button altitude up (ah - ab)
| | | | | || | +———4: Button - z-axis (r1 - l1)
| | | | | || +————6: Button + z-axis (r1 - l1)
| | | | | |+—————8: Button emergency reset all
| | | | | +—————-9: Button Takeoff / Landing
| | | | +—————————-18: y-axis trim +1 (Trim increase at +/- 1??/s)
| | | +——————————-20: x-axis trim +1 (Trim increase at +/- 1??/s)
| | +———————————-22: z-axis trim +1 (Trim increase at +/- 1??/s)
| +————————————-24: x-axis +1
+——————————————-28: y-axis +1
AT*REF=<sequence>,<UI>
AT*PCMD=<sequence>,<enable>,<pitch>,<roll>,<gaz>,<yaw>
(float)0.01 = (int)1008981770 (float)-0.01 = (int)-1138501878
(float)0.05 = (int)1028443341 (float)-0.05 = (int)-1119040307
(float)0.1 = (int)1036831949 (float)-0.1 = (int)-1110651699
(float)0.2 = (int)1045220557 (float)-0.2 = (int)-1102263091
(float)0.5 = (int)1056964608 (float)-0.5 = (int)-1090519040
AT*ANIM=<sequence>,<animation>,<duration>
AT*CONFIG=<sequence>,\"<name>\",\"<value>\"
altitude max2m: java ARDrone 192.168.1.1 AT*CONFIG=1,\"control:altitude_max\",\"2000\"
Takeoff: java ARDrone 192.168.1.1 AT*REF=101,290718208
Landing: java ARDrone 192.168.1.1 AT*REF=102,290717696
Hovering: java ARDrone 192.168.1.1 AT*PCMD=201,1,0,0,0,0
gaz 0.1: java ARDrone 192.168.1.1 AT*PCMD=301,1,0,0,1036831949,0
gaz -0.1: java ARDrone 192.168.1.1 AT*PCMD=302,1,0,0,-1110651699,0
pitch 0.1: java ARDrone 192.168.1.1 AT*PCMD=303,1,1036831949,0,0,0
pitch -0.1: java ARDrone 192.168.1.1 AT*PCMD=304,1,-1110651699,0,0,0
yaw 0.1: java ARDrone 192.168.1.1 AT*PCMD=305,1,0,0,0,1036831949
yaw -0.1: java ARDrone 192.168.1.1 AT*PCMD=306,1,0,0,0,-1110651699
roll 0.1: java ARDrone 192.168.1.1 AT*PCMD=307,1,0,1036831949,0,0
roll -0.1: java ARDrone 192.168.1.1 AT*PCMD=308,1,0,-1110651699,0,0
pitch -30 deg: java ARDrone 192.168.1.1 AT*ANIM=401,0,1000
pitch 30 deg: java ARDrone 192.168.1.1 AT*ANIM=402,1,1000
*/
import java.net.*;
import java.util.*;
class ARDrone {
public static void main(String args[]) throws Exception {
if (args.length<2) {
System.out.println("Usage: java ARDrone <IP> <AT command>");
System.exit(-1);
}
StringTokenizer st = new StringTokenizer(args[0], ".");
byte[] ip_bytes = new byte[4];
if (st.countTokens() == 4){
for (int i = 0; i < 4; i++){
ip_bytes[i] = (byte)Integer.parseInt(st.nextToken());
}
}
else {
System.out.println("Incorrect IP address format: " + args[0]);
System.exit(-1);
}
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(3000);
byte[] buffer = args[1].getBytes();
DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByAddress(ip_bytes), 5556);
socket.send(packet);
socket.receive(packet);
System.out.println(new String(packet.getData(),0,packet.getLength()));
}
}
-
Купил wifi адаптер и подсоединил его к своему PC
Включил AR.Drone
В списке беспроводных сетей нашел сеть drone и подключился к ней
Та программа MAPGPS, которую я ранее публиковал не совсем правильная, он забыл добавить "\r" в конце строки команды.
Вот ссылка на правильную программу
[внешняя ссылка]
Вот текст программы
Код: /*
Author: MAPGPS on [url="https://projects.ardrone.org"]https://projects.ardrone.org[/url]
Initial: 2010.09.20
Updated: 2010.09.24
UI_BIT:
00010001010101000000000000000000
| | | | | || | ||||+—0: Button turn to left
| | | | | || | |||+—-1: Button altitude down (ah - ab)
| | | | | || | ||+——2: Button turn to right
| | | | | || | |+——-3: Button altitude up (ah - ab)
| | | | | || | +———4: Button - z-axis (r1 - l1)
| | | | | || +————6: Button + z-axis (r1 - l1)
| | | | | |+—————8: Button emergency reset all
| | | | | +—————-9: Button Takeoff / Landing
| | | | +—————————-18: y-axis trim +1 (Trim increase at +/- 1??/s)
| | | +——————————-20: x-axis trim +1 (Trim increase at +/- 1??/s)
| | +———————————-22: z-axis trim +1 (Trim increase at +/- 1??/s)
| +————————————-24: x-axis +1
+——————————————-28: y-axis +1
AT*REF=<sequence>,<UI>
AT*PCMD=<sequence>,<enable>,<pitch>,<roll>,<gaz>,<yaw>
(float)0.01 = (int)1008981770 (float)-0.01 = (int)-1138501878
(float)0.05 = (int)1028443341 (float)-0.05 = (int)-1119040307
(float)0.1 = (int)1036831949 (float)-0.1 = (int)-1110651699
(float)0.2 = (int)1045220557 (float)-0.2 = (int)-1102263091
(float)0.5 = (int)1056964608 (float)-0.5 = (int)-1090519040
AT*ANIM=<sequence>,<animation>,<duration>
AT*CONFIG=<sequence>,\"<name>\",\"<value>\"
altitude max2m: java ARDrone 192.168.1.1 AT*CONFIG=1,\"control:altitude_max\",\"2000\"
Takeoff: java ARDrone 192.168.1.1 AT*REF=101,290718208
Landing: java ARDrone 192.168.1.1 AT*REF=102,290717696
Hovering: java ARDrone 192.168.1.1 AT*PCMD=201,1,0,0,0,0
gaz 0.1: java ARDrone 192.168.1.1 AT*PCMD=301,1,0,0,1036831949,0
gaz -0.1: java ARDrone 192.168.1.1 AT*PCMD=302,1,0,0,-1110651699,0
pitch 0.1: java ARDrone 192.168.1.1 AT*PCMD=303,1,1036831949,0,0,0
pitch -0.1: java ARDrone 192.168.1.1 AT*PCMD=304,1,-1110651699,0,0,0
yaw 0.1: java ARDrone 192.168.1.1 AT*PCMD=305,1,0,0,0,1036831949
yaw -0.1: java ARDrone 192.168.1.1 AT*PCMD=306,1,0,0,0,-1110651699
roll 0.1: java ARDrone 192.168.1.1 AT*PCMD=307,1,0,1036831949,0,0
roll -0.1: java ARDrone 192.168.1.1 AT*PCMD=308,1,0,-1110651699,0,0
pitch -30 deg: java ARDrone 192.168.1.1 AT*ANIM=401,0,1000
pitch 30 deg: java ARDrone 192.168.1.1 AT*ANIM=402,1,1000
*/
import java.net.*;
import java.util.*;
class ARDrone {
public static void main(String args[]) throws Exception {
if (args.length<2) {
System.out.println("Usage: java ARDrone <IP> <AT command>");
System.exit(-1);
}
StringTokenizer st = new StringTokenizer(args[0], ".");
byte[] ip_bytes = new byte[4];
if (st.countTokens() == 4){
for (int i = 0; i < 4; i++){
ip_bytes[i] = (byte)Integer.parseInt(st.nextToken());
}
}
else {
System.out.println("Incorrect IP address format: " + args[0]);
System.exit(-1);
}
DatagramSocket socket = new DatagramSocket();
socket.setSoTimeout(3000);
byte[] buffer = (args[1] + "\r").getBytes();
DatagramPacket packet = new DatagramPacket(buffer,buffer.length,InetAddress.getByAddress(ip_bytes), 5556);
socket.send(packet);
//socket.receive(packet); //AR.Drone does not send back ack message (like "OK")
//System.out.println(new String(packet.getData(),0,packet.getLength()));
}
}
После того как eclipse создал класс идем в Far, выбираем каталог в котором находится класс и в командной строке Far пишем
java ARDrone 192.168.1.1 AT*CONFIG=605,\"leds:leds_anim\",\"3,1073741824,2\"
Выполняем и получаем иллюминацию светодиодами drone
Аргументы команды пишутся после знака "равно". Их три. Первый - порядковый номер команды, собственно важно чтобы он был больше номера предыдущей команды. Правила использования порядкового номера описаны в пункте 6.2 руководства к использованию. SDK
Второй аргумент команды - это строка, опция указывающая на конкретное содержание команды
Третий аргумент - это строка состоящая из трех чисел, разделенных запятой. Первое число - это номер анимации в списке из файла ARDroneLib/Soft/Common/led_animation.h
Второй аргумент это частота, выраженная в форме числа с плавающей запятой
Третий аргумент это длительность анимации