
DIY: A robot submarine to explore the waters of the Moscow River. Part 1
This is a brief history of the creation of an underwater autonomous robot by a very middle manager. The current goal is to create an up-to-date map of the fairway of the Moscow River. When searching, there is no problem finding such a map , but its relevance raises the question. The river bed is constantly changing. Erosion of the riverbanks occurs and the channel map changes. These processes are especially noticeable, given the nutrition of the Moscow River snow (61%), ground (27%) and rain (12%). The ultimate goal is to create a multifunctional underwater robot for the study of the deep sea. The oceans covering 2/3 of the Earth’s surface has been studied only 5%. To create an autonomous robot, you need a simple “autopilot”.

The Moscow River is the main waterway of the city of Moscow, the length within the city is 80 km. The width of the river inside the city varies from 120 to 200 m, from the narrowest part near the Kremlin to the widest near Luzhniki. It is generally accepted that the river flow rate is 0.5 m / s. Quite favorable conditions for testing the robot.
It might be more efficient and easier to make a boat, but the task of making an underwater robot seems a lot more interesting.
Robot submarine to explore the waters of the Moscow River.

The approximate arrangement of the elements I saw as follows.

Installing the collector motor.

Servo-drive steering.

Servo-drive steering depth.

As a joke, I can say that I'm preparing for the X-Prize competition .
The goal is to develop an autonomous underwater robot, not ROV . (Remotely operated underwater vehicle).
The electronic part is not distinguished by the complexity and build quality of the
Arduino nano + L293D + Bluetooth + 3 servo + Power bank (Special thanks to the online store that sold such for 3 cents). Separately connected to the Power bank smartphone Samsung Galaxy S3 to maintain charge. The smartphone communicates with Arduino via Bluetooth.
“We are meeting our fate on the path that we have chosen to leave from it”
Jean de Lafontaine
I always tried to avoid programming on Android. When it became possible to develop even a lightweight application with the ability to get to know Android in action, I gave in.
But the time has come! Indeed, stop wasting money on nameplates for Arduino. All you need is already in your old smartphones. At hand was the Samsung Galaxy S3 and a bit of magic.
As a decent geek, I asked a question on the toaster . Maybe I asked hard. Perhaps a poorly worded question. And it seemed more likely this was not a question. But in response, I did not get what I expected.
Yandex to me in the bay! All requests “Android GPS”, “Programming Android GPS” and so on gave answers that definitely did not work on Android Studio.
What a relief for me was finding SL4A. It turns out you can prototype and program on Android using Python. They control, after all, even rockets .
If you have an Android phone, but you have one. You're a geek, not a fan of sugary fruits.
We select a program for recognizing QR codes .
To use SL4A, you must install the application on your phone.

The Python interpreter is here.

Or QPython3
It is possible to write programs on the phone, but you can’t call it a fun activity.

Using Yandex.maps or Google.maps, select points in the center of the river. This is an example route. For tests and setup I use a truncated version of the points.
[55.671110, 37.686625], [55.668448, 37.675467], [55.660847, 37.671776], [55.654649, 37.671175]

In the plans:
PS: Why did I decide to write a post before the launch of the robot? I want to find like-minded people. If you have a desire - do your robot. A great occasion to gather at the May holidays for an aqua ride on the Moscow River on robots! For all questions you can write to me VK . Please repost, maybe one of your friends will want to take part in the aqua marathon.
Let me remind you: the
contest of robotic lawnmowers will be held in Skolkovo on June 3. Everyone can try their hand at robotics. Following the results of the competition, we want to select a team for a startup. We will make the first Russian commercial robot mulcher. Valuable prizes and gifts for all participants.
How to make an affordable and easy autopilot for DIY projects and sail on it along the Moscow River?

The Moscow River is the main waterway of the city of Moscow, the length within the city is 80 km. The width of the river inside the city varies from 120 to 200 m, from the narrowest part near the Kremlin to the widest near Luzhniki. It is generally accepted that the river flow rate is 0.5 m / s. Quite favorable conditions for testing the robot.
It might be more efficient and easier to make a boat, but the task of making an underwater robot seems a lot more interesting.
Design
Robot submarine to explore the waters of the Moscow River.

The approximate arrangement of the elements I saw as follows.

Installing the collector motor.

Servo-drive steering.

Servo-drive steering depth.

As a joke, I can say that I'm preparing for the X-Prize competition .
It remains to save $ 2000. :)

The registration deadline is 30 June, 2016 (11:59 PM UTC / 4: 59 PM PST). The registration fee is $ 2,000.00 USD.
The goal is to develop an autonomous underwater robot, not ROV . (Remotely operated underwater vehicle).
The electronic part is not distinguished by the complexity and build quality of the
Arduino nano + L293D + Bluetooth + 3 servo + Power bank (Special thanks to the online store that sold such for 3 cents). Separately connected to the Power bank smartphone Samsung Galaxy S3 to maintain charge. The smartphone communicates with Arduino via Bluetooth.
Management Software
“We are meeting our fate on the path that we have chosen to leave from it”
Jean de Lafontaine
I always tried to avoid programming on Android. When it became possible to develop even a lightweight application with the ability to get to know Android in action, I gave in.
But the time has come! Indeed, stop wasting money on nameplates for Arduino. All you need is already in your old smartphones. At hand was the Samsung Galaxy S3 and a bit of magic.
As a decent geek, I asked a question on the toaster . Maybe I asked hard. Perhaps a poorly worded question. And it seemed more likely this was not a question. But in response, I did not get what I expected.
Yandex to me in the bay! All requests “Android GPS”, “Programming Android GPS” and so on gave answers that definitely did not work on Android Studio.
What a relief for me was finding SL4A. It turns out you can prototype and program on Android using Python. They control, after all, even rockets .
SL4A Python
If you have an Android phone, but you have one. You're a geek, not a fan of sugary fruits.
We select a program for recognizing QR codes .
To use SL4A, you must install the application on your phone.

The Python interpreter is here.

Or QPython3
It is possible to write programs on the phone, but you can’t call it a fun activity.
There is a way out
Source: http://habrahabr.ru/post/134184/
Let's redirect all local traffic coming to port 9999 to the Android device (assume that the server is listening on port 46136):
$ adb forward tcp: 9999 tcp: 46136 It
remains to create an environment variable and the setup is finished:
$ AP_PORT = 9999 It
remains to add the android.py file to the Python library folder, and that’s it, now you can write applications on your computer, run them, and you can see the result right away on the phone. To run helloWorld on an Android device, now just enter in the Python interpreter:
>>> import android
>>> droid = android.Android ()
>>> droid.makeToast (“Hello, world!”)
In the first line, the android library is imported, then a droid object is created, using which the Android API is used. The last line displays the message “Hello, World!” On the device screen.
Now is the time to take a closer look at the API that SL4A provides.
Let's redirect all local traffic coming to port 9999 to the Android device (assume that the server is listening on port 46136):
$ adb forward tcp: 9999 tcp: 46136 It
remains to create an environment variable and the setup is finished:
$ AP_PORT = 9999 It
remains to add the android.py file to the Python library folder, and that’s it, now you can write applications on your computer, run them, and you can see the result right away on the phone. To run helloWorld on an Android device, now just enter in the Python interpreter:
>>> import android
>>> droid = android.Android ()
>>> droid.makeToast (“Hello, world!”)
In the first line, the android library is imported, then a droid object is created, using which the Android API is used. The last line displays the message “Hello, World!” On the device screen.
Now is the time to take a closer look at the API that SL4A provides.
Building a path. Point selection

Using Yandex.maps or Google.maps, select points in the center of the river. This is an example route. For tests and setup I use a truncated version of the points.
[55.671110, 37.686625], [55.668448, 37.675467], [55.660847, 37.671776], [55.654649, 37.671175]
How to make an affordable and easy autopilot for DIY projects from an andoid phone and 70 lines of code?

Autopilot code
import math,android,time
coordmas = [[55.671110, 37.686625],[55.668448, 37.675467],[55.660847, 37.671776],[55.654649, 37.671175]]
droid = android.Android()
droid.startSensingTimed(1,200)
droid.startLocating(5000, 30)
def getgps():
locs = droid.getLastKnownLocation()
gpspos = locs.result["gps"]
return gpspos
def distazim(llat1,llong1,llat2,llong2):
rad=6372795
#врадианах
lat1=llat1*math.pi/180.
lat2=llat2*math.pi/180.
long1=llong1*math.pi/180.
long2=llong2*math.pi/180.
cl1=math.cos(lat1)
cl2=math.cos(lat2)
sl1=math.sin(lat1)
sl2=math.sin(lat2)
delta=long2-long1
cdelta=math.cos(delta)
sdelta=math.sin(delta)
y=math.sqrt(math.pow(cl2*sdelta,2)+math.pow(cl1*sl2-sl1*cl2*cdelta,2))
x=sl1*sl2+cl1*cl2*cdelta
ad=math.atan2(y,x)
dist=ad*rad
x=(cl1*sl2)-(sl1*cl2*cdelta)
y=sdelta*cl2
z=math.degrees(math.atan(-y/x))
if(x<0):
z=z+180.
z2=(z+180.)%360.-180.
z2=-math.radians(z2)
anglerad2=z2-((2*math.pi)*math.floor((z2/(2*math.pi))))
angledeg=(anglerad2*180.)/math.pi
return [dist,angledeg]
def servoangle(azdiff):
if azdiff>10 or azdiff<-10:
deg=azdiff
if deg>90:
deg=90
if deg<-90:
deg=-90
return deg
gpspos=getgps()
oldlat = gpspos["latitude"]
oldlon = gpspos["longitude"]
for c in range(len(coordmas)):
#получение координат текцщей целевой точки
curcoord=coordmas[c]
targetlat=curcoord[0]
targetlon=curcoord[1]
darange=11;
while darange>10:
gpspos=getgps()
curlat = gpspos["latitude"]
curlon = gpspos["longitude"]
time.sleep(0.5)
da=distazim(curlat,curlon,targetlat,targetlon)
darange = da[0]
dazimut = round(da[1])
pol=droid.sensorsReadOrientation()
pol2=pol.result
turn = round(pol2[0])
turn = (-turn) *180/ 3.2
azdiff=turn-dazimut
deg=servoangle(azdiff)
oldlat = curlat
oldlon = curlon
Code with comments
import math,android,time
#Массив координат
coordmas = [[55.671110, 37.686625],[55.668448, 37.675467],[55.660847, 37.671776],[55.654649, 37.671175]]
#Инициализация, запуск GPS, сенсоров
droid = android.Android()
droid.startSensingTimed(1,200)
droid.startLocating(5000, 30)
#Функции
#GPS
def getgps():
locs = droid.getLastKnownLocation()
gpspos = locs.result["gps"]
return gpspos
#Функция определения расстояния и азимута между двумя GPS-точками
def distazim(llat1,llong1,llat2,llong2):
rad=6372795
#врадианах
lat1=llat1*math.pi/180.
lat2=llat2*math.pi/180.
long1=llong1*math.pi/180.
long2=llong2*math.pi/180.
#косинусыисинусыширотиразницыдолгот
cl1=math.cos(lat1)
cl2=math.cos(lat2)
sl1=math.sin(lat1)
sl2=math.sin(lat2)
delta=long2-long1
cdelta=math.cos(delta)
sdelta=math.sin(delta)
#вычислениядлиныбольшогокруга
y=math.sqrt(math.pow(cl2*sdelta,2)+math.pow(cl1*sl2-sl1*cl2*cdelta,2))
x=sl1*sl2+cl1*cl2*cdelta
ad=math.atan2(y,x)
dist=ad*rad
#вычислениеначальногоазимута
x=(cl1*sl2)-(sl1*cl2*cdelta)
y=sdelta*cl2
z=math.degrees(math.atan(-y/x))
if(x<0):
z=z+180.
z2=(z+180.)%360.-180.
z2=-math.radians(z2)
anglerad2=z2-((2*math.pi)*math.floor((z2/(2*math.pi))))
angledeg=(anglerad2*180.)/math.pi
return [dist,angledeg]
def servoangle(azdiff):
if azdiff>10 or azdiff<-10:
deg=azdiff
if deg>90:
deg=90
if deg<-90:
deg=-90
return deg
#принятие текущего положения за старую точку
gpspos=getgps()
oldlat = gpspos["latitude"]
oldlon = gpspos["longitude"]
#Цикл
for c in range(len(coordmas)):
#получение координат текцщей целевой точки
curcoord=coordmas[c]
targetlat=curcoord[0]
targetlon=curcoord[1]
#выполняем цикл пока расстояние больше 10 метров до след.точки
darange=11;
while darange>10:
#определение координат
gpspos=getgps()
curlat = gpspos["latitude"]
curlon = gpspos["longitude"]
time.sleep(0.5)
#сравнение дальности и азимута до след. точки.
da=distazim(curlat,curlon,targetlat,targetlon)
darange = da[0]
dazimut = round(da[1])
#определяем угол телефона
pol=droid.sensorsReadOrientation()
pol2=pol.result
turn = round(pol2[0])
#[1.57=left, 0=stop, -1.57=right]
turn = (-turn) *180/ 3.2
#если угол точки отличается от угла телефона на 10 градусов готовим команду на поворот
azdiff=turn-dazimut
#готовим данные для угла поворота сервы руля
deg=servoangle(azdiff)
#отправляем по блютус угол поворота серво
#Меняем координаты старой точки, т.к. ожидается смена координат текущей цели
oldlat = curlat
oldlon = curlon
Python For Android. Features I've been looking for for a long time
Battery:
droid.batteryStartMonitoring () - started working with the battery.
droid.batteryStopMonitoring ()
droid.batteryGetHealth () - returns the battery status (1-unknown, 2-good, 3 - overheating, 4 - dead, 5 - overload, 6 - unknown failure)
droid.batteryGetStatus () - returns the battery status ( 1 - unknown, 2 - charging, 3 - discharging, 4 - not charging, 5 - maximum charge)
droid.batteryGetTechnology ()
droid.readBatteryData () - data about the battery.
droid.batteryGetTemperature ()
droid.batteryGetVoltage ()
droid.batteryGetLevel ()
Bluetooth:
droid.checkBluetoothState () - checks if Bluetooth is turned on
droid.toggleBluetoothState () - turns on if in brackets True and turns off if False
droid.bluetoothAccept () - accepts a connection
droid.bluetoothActiveConnections () - checks if there are any
droid.bluetoothGetConnectedDeviceName ()
connections droid.bluetoothMakeDiscoverable () - time interval in seconds
droid.bluetoothStop ()
Wi-Fi:
droid.checkWifiState () - checks if Wi-Fi is on
droid.toggleWifiState () - turns on if in brackets True and turns off if False
droid.wifiStartScan ()
droid.wifiGetScanResults ( )
droid.wifiGetConnectionInfo ()
Other settings:
droid.checkAirplaneMode () - checks if the “Airplane” mode is on
droid.checkRingerSilentMode () - checks whether the silent mode enabled
droid.checkScreenOn () - if the screen is enabled
droid.toggleRingerSilentMode () - includes a silent mode
droid.toggleAirplaneMode ()
droid.toggleVibrateMode ()
Obtaining information about the settings:
droid.getMaxMediaVolume ()
droid .getMaxRingerVolume ()
droid.getMediaVolume ()
droid.getRingerVolume ()
droid.getScreenBrightness ()
droid.getScreenTimeout ()
droid.getVibrateMode ()
Setting:
droid.setMediaVolume ()
droid.setRingerVolume ()
droid.setScreenBrightness ()
droid.setScreenTimeOut ()
droid.batteryStartMonitoring () - started working with the battery.
droid.batteryStopMonitoring ()
droid.batteryGetHealth () - returns the battery status (1-unknown, 2-good, 3 - overheating, 4 - dead, 5 - overload, 6 - unknown failure)
droid.batteryGetStatus () - returns the battery status ( 1 - unknown, 2 - charging, 3 - discharging, 4 - not charging, 5 - maximum charge)
droid.batteryGetTechnology ()
droid.readBatteryData () - data about the battery.
droid.batteryGetTemperature ()
droid.batteryGetVoltage ()
droid.batteryGetLevel ()
Bluetooth:
droid.checkBluetoothState () - checks if Bluetooth is turned on
droid.toggleBluetoothState () - turns on if in brackets True and turns off if False
droid.bluetoothAccept () - accepts a connection
droid.bluetoothActiveConnections () - checks if there are any
droid.bluetoothGetConnectedDeviceName ()
connections droid.bluetoothMakeDiscoverable () - time interval in seconds
droid.bluetoothStop ()
Wi-Fi:
droid.checkWifiState () - checks if Wi-Fi is on
droid.toggleWifiState () - turns on if in brackets True and turns off if False
droid.wifiStartScan ()
droid.wifiGetScanResults ( )
droid.wifiGetConnectionInfo ()
Other settings:
droid.checkAirplaneMode () - checks if the “Airplane” mode is on
droid.checkRingerSilentMode () - checks whether the silent mode enabled
droid.checkScreenOn () - if the screen is enabled
droid.toggleRingerSilentMode () - includes a silent mode
droid.toggleAirplaneMode ()
droid.toggleVibrateMode ()
Obtaining information about the settings:
droid.getMaxMediaVolume ()
droid .getMaxRingerVolume ()
droid.getMediaVolume ()
droid.getRingerVolume ()
droid.getScreenBrightness ()
droid.getScreenTimeout ()
droid.getVibrateMode ()
Setting:
droid.setMediaVolume ()
droid.setRingerVolume ()
droid.setScreenBrightness ()
droid.setScreenTimeOut ()
In the plans:
- Configure Bluetooth data sending to arduino.
- Getting depth data from arduino. I will measure the depth with an ultrasonic sensor.
- Sending data about the current position and depth measurements to the server.
- Finalization of the design. The boat should be with zero buoyancy so that the depth can be changed by rudders. Perhaps the design of the submarine will have to go to the surface vehicle.
- Test, test, test
PS: Why did I decide to write a post before the launch of the robot? I want to find like-minded people. If you have a desire - do your robot. A great occasion to gather at the May holidays for an aqua ride on the Moscow River on robots! For all questions you can write to me VK . Please repost, maybe one of your friends will want to take part in the aqua marathon.
Let me remind you: the
contest of robotic lawnmowers will be held in Skolkovo on June 3. Everyone can try their hand at robotics. Following the results of the competition, we want to select a team for a startup. We will make the first Russian commercial robot mulcher. Valuable prizes and gifts for all participants.