Compare commits

..
30 Commits
Author SHA1 Message Date
zeunerti74726 3dea00a8d1 Too big too handle 2023-03-03 19:48:03 +01:00
zeunerti74726 960b05e76f Testfahrten 2023-03-03 18:57:35 +01:00
zeunerti74726 94e9c4ba7a Faster! 2023-03-03 18:47:41 +01:00
zeunerti74726 6da9bfff54 Bugs found during tests 2023-03-03 18:46:31 +01:00
zeunerti74726 c40b69ebe2 Save video 2023-03-03 18:45:03 +01:00
zeunerti74726 397e6fe331 Let signals to stop always pass 2023-02-23 20:39:28 +01:00
zeunerti74726 60fbc8758d fabs instead of abs 2023-02-23 20:38:18 +01:00
zeunerti74726 fe4af52380 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/yasarba71520/Line-Following-Robot 2023-02-23 11:12:40 +01:00
zeunerti74726 426f57798e uint -> int; max send rate; 2023-02-22 14:45:50 +01:00
zeunerti74726 9d896df965 Index error 2023-02-22 14:42:09 +01:00
bockva71868 ce6ca27490 Error Handling 2023-02-08 12:13:18 +01:00
zeunerti74726 bc3484acae Implement correct interface for manual mode. 2023-02-07 21:32:19 +01:00
zeunerti74726 1f172a8b7a start stop token 2023-02-07 21:29:24 +01:00
zeunerti74726 6577c39a1b Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/yasarba71520/Line-Following-Robot 2023-02-07 21:26:06 +01:00
zeunerti74726 9a80ec1410 SChneller 2023-02-07 21:25:38 +01:00
zeunerti74726 366b3db8f9 Merge branch 'master' of https://git.efi.th-nuernberg.de/gitea/yasarba71520/Line-Following-Robot 2023-02-07 21:21:03 +01:00
zeunerti74726 65516babfc Use buffer for zerstückelte Messages 2023-02-07 21:20:49 +01:00
zeunerti74726 a920aefa54 Debug Messages 2023-02-07 21:20:10 +01:00
bockva71868 a34657dc1a Error handling 2023-02-07 19:54:14 +01:00
zeunerti74726 8cda9e8c0f Add start and end signal to telegram 2023-02-07 16:07:17 +01:00
zeunerti74726 e9114fdfe5 Wait for 250ms before sending again 2023-02-07 15:27:28 +01:00
zeunerti74726 a8e8ccbbe1 call asynctask through mainactivity 2023-02-07 14:57:29 +01:00
zeunerti74726 ffb38996e8 connectToWifi in Future 2023-02-07 14:56:44 +01:00
bockva71868 e248dc3e0c Threadsave socket 2023-02-07 13:48:59 +01:00
bockva71868 8831c130cd Threadsave socket 2023-02-07 13:46:04 +01:00
zeunerti74726 b361fad52d Dont use AsyncTask 2023-02-06 10:53:38 +01:00
yasarba71520 2ee3603229 App: Socket in Async Task 2023-02-05 15:24:43 +01:00
yasarba71520 cd6973efbb App: Sending data in Async Task 2023-02-05 15:24:09 +01:00
zeunerti74726 60e19a8968 Adjust telegramm 2023-02-03 20:38:52 +01:00
zeunerti74726 a929bbebed missing , 2023-02-02 09:25:34 +01:00
17 changed files with 450 additions and 146 deletions
@@ -36,7 +36,7 @@ void ControlModule::adjustSpeed(){
for(int i = 0; i < 4; i++)
{
motors[i] *= maxSpeed;
motors[i] *= factor;
}
};
@@ -85,7 +85,7 @@ void ControlModule::calcSpeeds(int imageColumsMiddle, int contourColumsMiddle, d
std::unique_lock<std::mutex> lock(mtx);
double rotationRatio = ratio(angle);
rotate(rotationRatio);
drive(1.0-rotationRatio);
drive(1.0-std::fabs(rotationRatio));
unit();
adjustSpeed();
}
@@ -102,13 +102,21 @@ double ControlModule::ratio(double angle)
double maxAngularSpeed = 1.0;
double speedRange = maxAngularSpeed - minAngularSpeed;
double minAngle = -90.0;
double maxAngle = 90.0;
double minAngle = -20.0;
double maxAngle = 20.0;
double angularRange = maxAngle - minAngle;
if(angle < minAngle)
{
angle = minAngle;
}
if(angle > maxAngle)
{
angle = maxAngle;
}
double progress = angle - minAngle;
double progressPercent = progress/angularRange;
double speed = minAngularSpeed + progressPercent*speedRange;
return abs(speed);
return speed;
}
@@ -2,6 +2,7 @@
#include <mutex>
#include <vector>
#include <iostream>
#include <cmath>
class ControlModule
{
+37 -24
View File
@@ -2,6 +2,7 @@
LFR_UART::LFR_UART() : fileDescriptor(-1) {
this->last =std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
this->openSerialPort();
this->configureSerialPort();
}
@@ -13,12 +14,13 @@ void LFR_UART::openFile(const char *fileName) {
this->fileDescriptor = open(fileName, O_RDWR | O_NONBLOCK);
}
int LFR_UART::writeDataToFile(uint8_t *buff, uint32_t bufferLength) {
std::cout << "Sending uart telegram" << std::endl;
int LFR_UART::writeDataToFile(int8_t *buff, uint32_t bufferLength) {
//std::cout << "Sending uart: " << std::bitset<8>(buff[0]) << std::endl;
std::cout << "Sending Uart: " << std::bitset<8>(buff[0]) << ", " << std::bitset<8>(buff[1]) << ", " << std::bitset<8>(buff[2]) << ", " << std::bitset<8>(buff[3]) << " csum: " << std::bitset<8>(buff[4]) << std::endl;
return write(this->fileDescriptor, buff, bufferLength);
}
int LFR_UART::readFromFile(uint8_t *buff, uint32_t bufferLength) {
int LFR_UART::readFromFile(int8_t *buff, uint32_t bufferLength) {
return read(this->fileDescriptor, buff, bufferLength);
}
@@ -26,37 +28,32 @@ int LFR_UART::closeFile() {
return close(this->fileDescriptor);
}
uint8_t LFR_UART::doubleToByte(double in){
int8_t LFR_UART::doubleToByte(double in){
/*
* Map the range of -1.0 to 1.0 as double to the range of a byte.
*
* -1 -> 0
* 0.0 -> 127
* 1.0 -> 254
* Not using the full range upto 254 to hit the 0.0
* Map the range of -1.0 to 1.0 as double to the range of a byte. (int8 range)
*/
double minDouble = -1.0;
double maxDouble = 1.0;
double rangeDouble = maxDouble - minDouble;
double minByte = 0.0;
double maxByte = 255.0;
double minByte = -128.0;
double maxByte = 127.0;
double rangeByte = maxByte - minByte;
double progress = in - minDouble;
double progressPercent = progress/rangeDouble;
double inputInByteRange = minByte + progressPercent*rangeByte;
return uint8_t(inputInByteRange);
return int8_t(inputInByteRange);
}
double LFR_UART::byteToDouble(uint8_t in){
double LFR_UART::byteToDouble(int8_t in){
double minDouble = -1.0;
double maxDouble = 1.0;
double rangeDouble = maxDouble - minDouble;
double minByte = 0.0;
double maxByte = 255.0;
double minByte = -128.0;
double maxByte = 127.0;
double rangeByte = maxByte - minByte;
double progress = double(in) - minByte;
@@ -67,27 +64,43 @@ double LFR_UART::byteToDouble(uint8_t in){
}
void LFR_UART::sendTelegram(double wheel1, double wheel2, double wheel3, double wheel4){
std::chrono::milliseconds now = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
unsigned int deltaMs = static_cast<unsigned int>((now-last).count());
if (deltaMs < 50 && (std::fabs(wheel1)+std::fabs(wheel2)+std::fabs(wheel3)+std::fabs(wheel4)) > 0.0005)
{
std::cout << "Too fast" << std::endl;
return;
}
last = now;
if(wheel1 > 1.0 || wheel2 > 1.0 || wheel3 > 1.0 || wheel4 > 1.0){
throw CommunicatorException("Wheel value must not be greater than 1.0");
}
if(wheel1 < -1.0 || wheel2 < -1.0 || wheel3 < -1.0 || wheel4 < -1.0){
throw CommunicatorException("Wheel value must not be smaller than -1.0");
}
// Discrepancy between the numbering of the wheels in App/Pi and the µc
// Our - their
// 1 - 4
// 2 - 2
// 3 - 3
// 4 - 1
int8_t wheel1B = this->doubleToByte(wheel4);
//int8_t wheel1B = this->doubleToByte(wheel1);
int8_t wheel2B = this->doubleToByte(wheel2);
int8_t wheel3B = this->doubleToByte(wheel3);
int8_t wheel4B = this->doubleToByte(wheel1);
//int8_t wheel4B = this->doubleToByte(wheel4);
uint8_t wheel1B = this->doubleToByte(wheel1);
uint8_t wheel2B = this->doubleToByte(wheel2);
uint8_t wheel3B = this->doubleToByte(wheel3);
uint8_t wheel4B = this->doubleToByte(wheel4);
int8_t checksum = wheel1B^wheel2B^wheel3B^wheel4B;
uint8_t checksum = wheel1B^wheel2B^wheel3B^wheel4B;
uint8_t telegram_buffer[5] = {wheel1B, wheel2B, wheel3B, wheel4B, checksum};
int8_t telegram_buffer[5] = {wheel1B, wheel2B, wheel3B, wheel4B, checksum};
uint32_t telegram_length = 5;
this->writeDataToFile(telegram_buffer, telegram_length);
}
bool LFR_UART::readTelegram(double* buffer){
uint8_t tmp_buffer[5] = {0, 0, 0, 0, 0};
int8_t tmp_buffer[5] = {0, 0, 0, 0, 0};
uint32_t telegram_length = 5;
this->readFromFile(tmp_buffer, telegram_length);
+9 -4
View File
@@ -11,12 +11,16 @@
#include <iostream>
#include <exception>
#include <iostream>
#include <chrono>
#include <cmath>
#include <bitset>
class LFR_UART
{
public:
std::chrono::milliseconds last;
int fileDescriptor;
const char* serialPortPath = "/dev/ttyS0";
@@ -29,13 +33,14 @@ class LFR_UART
void configureSerialPort();
void closeSerialPort();
int writeDataToFile(uint8_t *buff, uint32_t bufferLength);
int readFromFile(uint8_t *buff, uint32_t bufferLength);
int writeDataToFile(int8_t *buff, uint32_t bufferLength);
int readFromFile(int8_t *buff, uint32_t bufferLength);
public:
uint8_t doubleToByte(double in);
double byteToDouble(uint8_t in);
int8_t doubleToByte(double in);
double byteToDouble(int8_t in);
void sendTelegram(double wheel1, double wheel2, double wheel3, double wheel4);
bool readTelegram(double* buffer);
+1 -1
View File
@@ -25,7 +25,7 @@
</map>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="11" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
@@ -11,53 +11,41 @@ import java.util.Iterator;
import java.util.Objects;
public class Communication {
public boolean sendData(String data, String ip, int port) {
try {
Socket socket = new Socket(ip, port);
DataOutputStream DOS = new DataOutputStream(socket.getOutputStream());
DOS.writeUTF(data);
socket.close();
} catch (Exception e) {
e.printStackTrace();
return true; //ToDo: change to false to test connection - currently always true is delivered
}
return true;
}
public String telegram(int[] wheels, int strenght){
String tel = "";
tel += "0;"; //Manuel mode
String tel = "aa";
tel += "0"; //Manuel mode
for(int i = 0; i < wheels.length; i++){
if(wheels[i] == 1){
tel += Float.toString(((float)strenght)/100) + ";";
tel += ";" + Float.toString(((float)strenght)/100) ;
}else if(wheels[i] == -1)
tel += Float.toString(((float)-strenght)/100) + ";";
tel += ";" + Float.toString(((float)-strenght)/100);
else{
tel += "0.00;";
tel += ";0.00";
}
}
Log.v("TAG", tel + "\n");
tel += "zz";
return tel;
}
public String telegram(boolean startStop, ArrayList<String> list){
String tel = "";
tel += "1;"; //Autonomous mode
String tel = "aa";
tel += "1"; //Autonomous mode
if(startStop){
tel += "1;";
tel += ";1";
}else{
tel += "0;";
return "aa0;0.0;0.0;0.0;0.0zz";
}
for (String i : list) {
if(i.equals("Links")){
tel += "0;";
tel += ";0";
}else if (i.equals("Rechts")){
tel += "1;";
tel += ";1";
}
}
Log.v("TAG", tel + "\n");
tel += "zz";
return tel;
}
}
@@ -0,0 +1,49 @@
package com.example.lfrmobileapp;
import android.os.AsyncTask;
import android.util.Log;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class DataTransferAsyncTask extends AsyncTask<Void, Void, Void> {
private static final double sendRatePerSecond = 4.0;
private boolean connected;
private final ExtendedSocket socket;
private BlockingQueue<String> blockingQueue;
public DataTransferAsyncTask(ExtendedSocket socket) {
this.socket = socket;
this.connected = true;
this.blockingQueue = new LinkedBlockingQueue<>();
}
public void writeTelegram(String telegram) {
// Schau mal hier bei Fehler
blockingQueue.offer(telegram);
}
@Override
protected Void doInBackground(Void... params) {
while(!isCancelled() && connected) {
try {
synchronized (socket) {
String message = blockingQueue.poll((long) (1000.0/sendRatePerSecond), TimeUnit.MILLISECONDS);
if(message != null){
Log.v("TAG", message + "\n");
socket.sendMessage(message);
}
}
} catch (Exception e) {
e.printStackTrace();
connected = false;
}
}
return null;
}
}
@@ -0,0 +1,25 @@
package com.example.lfrmobileapp;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
public class ExtendedSocket {
private final Socket socket;
public ExtendedSocket(Socket socket) {
this.socket = socket;
}
public void sendMessage(String message) throws IOException {
synchronized (socket){
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeBytes(message);
outputStream.flush();
}
}
public void closeSocket() throws IOException {
this.socket.close();
}
}
@@ -3,6 +3,7 @@ package com.example.lfrmobileapp;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.widget.Toast;
import com.google.android.material.bottomnavigation.BottomNavigationView;
@@ -14,11 +15,21 @@ import androidx.navigation.ui.NavigationUI;
import com.example.lfrmobileapp.databinding.ActivityMainBinding;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class MainActivity extends AppCompatActivity {
private ActivityMainBinding binding;
private ExtendedSocket socket;
private DataTransferAsyncTask dataTransferAsyncTask;
public Boolean connected = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -38,5 +49,43 @@ public class MainActivity extends AppCompatActivity {
NavigationUI.setupWithNavController(binding.navView, navController);
}
public boolean connectToWifi(String ipAddress, int port){
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Boolean> future = executor.submit(() -> {
Socket tempSocket = new Socket();
tempSocket.connect(new InetSocketAddress(ipAddress, port), 1000);
try {
socket = new ExtendedSocket(tempSocket);
socket.sendMessage("Verbindung aufbauen");
} catch (Exception e) {
socket.closeSocket();
return false;
}
return true;
});
try {
connected = future.get();
} catch (InterruptedException e) {
System.err.println("InterruptedException: " + e.getMessage());
} catch (ExecutionException e) {
System.err.println("ExecutionException: " + e.getCause().getMessage());
}
executor.shutdown();
if(connected){
dataTransferAsyncTask = new DataTransferAsyncTask(socket);
dataTransferAsyncTask.execute();
return true;
}else{
return false;
}
}
public void sendTelegram(String telegram)
{
this.dataTransferAsyncTask.writeTelegram(telegram);
}
}
@@ -18,6 +18,8 @@ import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.lfrmobileapp.Communication;
import com.example.lfrmobileapp.DataTransferAsyncTask;
import com.example.lfrmobileapp.MainActivity;
import com.example.lfrmobileapp.R;
import com.example.lfrmobileapp.databinding.FragmentAutomatikBinding;
@@ -27,20 +29,22 @@ import java.util.Arrays;
import kotlin.collections.UArraySortingKt;
// Autonomous Mode
public class DashboardFragment extends Fragment {
String ipKey = "ipkey";
String portKey = "portkey";
String ipAddress = "192.168.0.1";
int port = 8000;
Communication com = new Communication();
private FragmentAutomatikBinding binding;
MainActivity mainActivity;
//Keys for Shared Preferences
String listKey = "listkey";
@Override
public void onAttach(Context context) {
super.onAttach(context);
mainActivity = (MainActivity) context;
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
DashboardViewModel dashboardViewModel =
@@ -59,17 +63,16 @@ public class DashboardFragment extends Fragment {
//Get Arraylist from Shared Preferences String
ArrayList<String> autoList = stringToArraylist(sharedPref.getString(listKey, ""));
ipAddress = sharedPref.getString(ipKey, "");
port = sharedPref.getInt(portKey, -1);
binding.startAutomatic.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mainActivity.connected){
if(isChecked){
com.sendData(com.telegram(true, autoList), ipAddress, port);
mainActivity.sendTelegram(com.telegram(true, autoList));
}else{
com.sendData(com.telegram(false, autoList), ipAddress, port);
mainActivity.sendTelegram(com.telegram(false, autoList));
}
}
}
});
@@ -1,9 +1,12 @@
package com.example.lfrmobileapp.ui.home;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
@@ -15,6 +18,8 @@ import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.lfrmobileapp.Communication;
import com.example.lfrmobileapp.DataTransferAsyncTask;
import com.example.lfrmobileapp.MainActivity;
import com.example.lfrmobileapp.R;
import com.example.lfrmobileapp.databinding.FragmentManuellBinding;
import com.example.lfrmobileapp.ui.notifications.NotificationsFragment;
@@ -31,10 +36,20 @@ public class HomeFragment extends Fragment {
String ipAddress = "192.168.0.1";
int port = 8000;
MainActivity mainActivity;
Communication com = new Communication();
long lastOnMoveCall = System.currentTimeMillis();
private FragmentManuellBinding binding;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mainActivity = (MainActivity) context;
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
HomeViewModel homeViewModel =
@@ -54,54 +69,90 @@ public class HomeFragment extends Fragment {
final TextView textView = binding.textHome;
homeViewModel.getText().observe(getViewLifecycleOwner(), textView::setText);
binding.rotateLeft.setOnClickListener(new View.OnClickListener(){
binding.rotateLeft.setOnTouchListener(new View.OnTouchListener(){
@SuppressLint("ClickableViewAccessibility")
@Override
public void onClick(View v){
com.sendData(com.telegram(new int[]{-1, 1, -1, 1}, 100), ipAddress, port);
};
public boolean onTouch(View v, MotionEvent event) {
if (mainActivity.connected) {
if (event.getAction() == MotionEvent.ACTION_UP) {
binding.rotateLeft.performClick();
mainActivity.sendTelegram(com.telegram(new int[]{0, 0, 0, 0}, 0));
return true;
} else {
mainActivity.sendTelegram(com.telegram(new int[]{-1, 1, -1, 1}, 50));
}
}
return false;
}
});
binding.rotateRight.setOnClickListener(new View.OnClickListener(){
binding.rotateRight.setOnTouchListener(new View.OnTouchListener(){
@SuppressLint("ClickableViewAccessibility")
@Override
public void onClick(View v){
com.sendData(com.telegram(new int[]{1, -1, 1, -1}, 100), ipAddress, port);
};
public boolean onTouch(View v, MotionEvent event) {
if (mainActivity.connected){
if(event.getAction() == MotionEvent.ACTION_UP){
binding.rotateRight.performClick();
mainActivity.sendTelegram(com.telegram(new int[]{0, 0, 0, 0}, 0));
return true;
}else{
mainActivity.sendTelegram(com.telegram(new int[]{1, -1, 1, -1}, 50));
}
}
return false;
}
});
JoystickView joystick = (JoystickView) binding.joystick;
joystick.setOnMoveListener(new JoystickView.OnMoveListener() {
@Override
public void onMove(int angle, int strength) {
boolean send = false;
if (System.currentTimeMillis() - lastOnMoveCall > 250){
send = true;
lastOnMoveCall = System.currentTimeMillis();
}
String telegram = "";
homeViewModel.setText(Integer.toString(angle), Integer.toString(strength));
//8 segments of the joystick
if((angle >= 338 || angle < 22) && strength != 0){
joystick.setBackgroundResource(R.mipmap.right);
com.sendData(com.telegram(new int[]{1, -1, -1, 1}, strength), ipAddress, port);
telegram = com.telegram(new int[]{1, -1, -1, 1}, strength);
}else if((angle >= 22 && angle < 67) && strength != 0){
joystick.setBackgroundResource(R.mipmap.right_forward);
com.sendData(com.telegram(new int[]{1, 0, 0, 1}, strength), ipAddress, port);
telegram = com.telegram(new int[]{1, 0, 0, 1}, strength);
}else if((angle >=67 && angle < 112) && strength != 0){
joystick.setBackgroundResource(R.mipmap.forward);
com.sendData(com.telegram(new int[]{1, 1, 1, 1}, strength), ipAddress, port);
telegram = com.telegram(new int[]{1, 1, 1, 1}, strength);
}else if((angle >=112 && angle < 157) && strength != 0){
joystick.setBackgroundResource(R.mipmap.left_forward);
com.sendData(com.telegram(new int[]{0, 1, 1, 0}, strength), ipAddress, port);
telegram = com.telegram(new int[]{0, 1, 1, 0}, strength);
}else if((angle >=157 && angle < 202) && strength != 0){
joystick.setBackgroundResource(R.mipmap.left);
com.sendData(com.telegram(new int[]{-1, 1, 1, -1}, strength), ipAddress, port);
telegram = com.telegram(new int[]{-1, 1, 1, -1}, strength);
}else if((angle >=202 && angle < 247) && strength != 0){
joystick.setBackgroundResource(R.mipmap.left_back);
com.sendData(com.telegram(new int[]{-1, 0, 0, -1}, strength), ipAddress, port);
telegram = com.telegram(new int[]{-1, 0, 0, -1}, strength);
}else if((angle >=247 && angle < 292) && strength != 0){
joystick.setBackgroundResource(R.mipmap.back);
com.sendData(com.telegram(new int[]{-1, -1, -1, -1}, strength), ipAddress, port);
telegram = com.telegram(new int[]{-1, -1, -1, -1}, strength);
}else if((angle >=292 && angle < 337) && strength != 0){
joystick.setBackgroundResource(R.mipmap.right_back);
com.sendData(com.telegram(new int[]{0, -1, -1, 0}, strength), ipAddress, port);
telegram = com.telegram(new int[]{0, -1, -1, 0}, strength);
}
else{
joystick.setBackgroundResource(R.mipmap.blank);
com.sendData(com.telegram(new int[]{0, 0, 0, 0}, strength), ipAddress, port);
telegram = com.telegram(new int[]{0, 0, 0, 0}, strength);
send=true;
}
if (send && mainActivity.connected)
{
mainActivity.sendTelegram(telegram);
// Log.v("TAG", telegram + "\n");
}
}
});
@@ -112,6 +163,7 @@ public class HomeFragment extends Fragment {
@Override
public void onDestroyView() {
super.onDestroyView();
// dataTransferAsyncTask.cancel(false);
binding = null;
}
}
@@ -1,6 +1,5 @@
package com.example.lfrmobileapp.ui.notifications;
import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
@@ -8,7 +7,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
@@ -16,24 +14,65 @@ import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import com.example.lfrmobileapp.Communication;
import com.example.lfrmobileapp.R;
import com.example.lfrmobileapp.DataTransferAsyncTask;
import com.example.lfrmobileapp.MainActivity;
import com.example.lfrmobileapp.databinding.FragmentEinstellungenBinding;
import java.io.DataOutputStream;
import java.net.Socket;
/*class NetworkThread extends Thread {
String ip;
int port;
boolean connected;
NetworkThread(String ip, int port) {
this.ip = ip;
this.port = port;
this.connected = false;
}
public void run() {
try {
Socket socket = new Socket(ip, port);
DataOutputStream outputStream = new DataOutputStream(socket.getOutputStream());
outputStream.writeBytes("Verbindung aufbauen");
outputStream.flush();
socket.close();
connected = true;
} catch (Exception e) {
e.printStackTrace();
connected = false;
}
}
}*/
public class NotificationsFragment extends Fragment {
Boolean connected = false;
MainActivity mainActivity;
String ipKey = "ipkey";
String portKey = "portkey";
String connectionFailed = "Verbindung fehlgeschlagen.";
String connectionSuccessful = "Verbindung erfolgreich.";
String ipAddress = "192.168.0.1";
int port = 8000;
String ipAddress = "192.168.4.1";
int port = 8080;
int duration = Toast.LENGTH_LONG;
DataTransferAsyncTask dataTransferAsyncTask;
private FragmentEinstellungenBinding binding;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mainActivity = (MainActivity) context;
}
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
NotificationsViewModel notificationsViewModel =
@@ -56,13 +95,21 @@ public class NotificationsFragment extends Fragment {
binding.port.setText("");
}
// dataTransferAsyncTask = new DataTransferAsyncTask(ipAddress, port);
final Button button = binding.connect;
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
ipAddress = String.valueOf(binding.ipAdress.getText());
port = Integer.parseInt(String.valueOf(binding.port.getText()));
if(com.sendData("", ipAddress, port)){
} catch (Exception e){
System.err.println("Parse Exception: " + e.getMessage());
}
connected = mainActivity.connectToWifi(ipAddress, port);
if(connected){
editor.putString(ipKey, ipAddress);
editor.putInt(portKey, port);
editor.apply();
@@ -71,17 +118,18 @@ public class NotificationsFragment extends Fragment {
}else{
Toast toast = Toast.makeText(v.getContext(), connectionFailed, duration);
toast.show();
// dataTransferAsyncTask.cancel(true);
}
}
});
return root;
}
@Override
public void onDestroyView() {
super.onDestroyView();
// dataTransferAsyncTask.cancel(true);
binding = null;
}
}
@@ -85,7 +85,7 @@
<ListView
android:id="@+id/automaticList"
android:layout_width="413dp"
android:layout_width="match_parent"
android:layout_height="470dp"
android:layout_marginTop="110dp"
app:layout_constraintEnd_toEndOf="parent"
+52 -11
View File
@@ -2,6 +2,7 @@
LFR_Socket::LFR_Socket(ExceptionCallback cb): cb(cb)
{
bufferIterator = std::begin(buffer);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
throw std::runtime_error("Failed opening the socket");
@@ -66,7 +67,7 @@ void LFR_Socket::createThread()
bool connected = false;
while(true)
{
LFR_Socket::LFR_Telegram telegram;
LFR_Socket::LFR_Telegram telegram = {};
bool received = false;
if(!stop && !listeners.empty())
{
@@ -91,32 +92,46 @@ void LFR_Socket::createThread()
}
else
{
//std::cout << "accepted connection" << std::endl;
std::cout << "accepted connection" << std::endl;
pollfds[1].fd = new_socket;
connected = true;
}
}
else if (connected && pollfds[0].revents & POLLIN)
{
//std::cout << "second connection incoming" << std::endl;
std::cout << "second connection incoming" << std::endl;
int tmp_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen);
close(tmp_socket);
//std::cout << "second connection closed" << std::endl;
std::cout << "second connection closed" << std::endl;
}
else if (pollfds[1].revents & POLLIN)
{
bytes_received = recv(new_socket, buffer, sizeof(buffer), 0);
if (bytes_received > 0)
LFR_Telegram tmpBuffer = {0};
bytesReceived = recv(new_socket, tmpBuffer, sizeof(tmpBuffer), 0);
if (bytesReceived > 0)
{
received = true;
std::copy(std::begin(buffer), std::end(buffer), std::begin(telegram));
//std::cout << "message received" << std::endl;
if(bufferIterator - std::begin(buffer) + bytesReceived > 1024)
{
//Too long for buffer. Clear it.
std::fill(std::begin(buffer), std::end(buffer), 0);
bufferIterator = std::begin(buffer);
}
else if(bytes_received == 0)
bufferIterator = std::copy_if(
std::begin(tmpBuffer),
std::begin(tmpBuffer)+bytesReceived,
bufferIterator,
[](char c){
return(c != '\n' && c != '\r');
});
//std::cout << "bytes received: " << bytesReceived << std::endl;
//received = true;
}
else if(bytesReceived == 0)
{
connected = false;
close(pollfds[1].fd);
//std::cout << "connection closed by peer" << std::endl;
std::cout << "connection closed by peer" << std::endl;
}
}
}
@@ -131,6 +146,32 @@ void LFR_Socket::createThread()
}
}
// Search the buffer for the start of a telegram
char *telegramStart = NULL;
telegramStart = strstr(buffer, "aa");
if(telegramStart && telegramStart != std::begin(buffer)) {
//Move the content of the buffer
auto delta = bufferIterator - telegramStart;
std::copy(telegramStart, std::end(buffer), std::begin(buffer));
bufferIterator = std::begin(buffer) + delta;
}
// Search the buffer for the end of a telegram
char *telegramEnd = NULL;
telegramEnd = strstr(buffer, "zz");
if(telegramEnd && telegramStart && telegramEnd-telegramStart>2) {
std::copy(telegramStart+2, telegramEnd, telegram);
received = true;
std::copy(telegramEnd+2, std::end(buffer), std::begin(buffer));
bufferIterator = std::begin(buffer);
}
else if(telegramEnd && telegramStart && telegramEnd-telegramStart<=2)
{
//Got an empty telegram
std::copy(telegramEnd, std::end(buffer), std::begin(buffer));
bufferIterator = std::begin(buffer);
}
//Invoke the callback method (ListenerPair second -> ListenerCallback)
if (received)
{
+3 -1
View File
@@ -13,6 +13,7 @@
#include <string>
#include <algorithm>
#include <exception>
#include <cstring>
class LFR_Socket
{
@@ -31,11 +32,12 @@ private:
std::unique_ptr<std::thread> thread;
mutable std::mutex mutex;
int server_fd, new_socket, bytes_received;
int server_fd, new_socket, bytesReceived;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char* bufferIterator;
//void provideOutput(Mat originalImage, Mat processedImage, const FrameData& frameData, const Rect& roi);
+41 -26
View File
@@ -25,12 +25,10 @@ void LFR_StateMachine::sanitize (string& s) const
bool LFR_StateMachine::checkStringValidity (const std::vector<std::string>& s) const
{
if(s.size() != 5)
{
return false;
}
try
{
int i = stoi(s[0]);
if(i == 0 && s.size() == 5)
{
for(int i = 0; i < 4; i ++)
{
@@ -39,8 +37,12 @@ bool LFR_StateMachine::checkStringValidity (const std::vector<std::string>& s) c
return false;
}
}
int i = stoi(s[4]);
if(i != 0 && i != 1)
}
else if(i == 1)
{
return true;
}
else
{
return false;
}
@@ -55,16 +57,20 @@ void LFR_StateMachine::parseString(string s)
std::vector<std::string> splitStr = split(s, ";");
if(!checkStringValidity(splitStr))
{
std::cout<<"Invalid String" << std::endl;
std::cout<<"Error: Invalid String: " << s << std::endl;
return;
}
double wheels[4] = {0.0, 0.0, 0.0, 0.0};
int mode = std::stoi(splitStr[4]);
for(int i = 0; i < 3; i++)
else
{
wheels[i] = std::stod(splitStr[i]);
std::cout<< s << std::endl;
}
double wheels[4] = {0.0, 0.0, 0.0, 0.0};
int mode = std::stoi(splitStr[0]);
if(mode == 0) {
for(int i = 1; i <= 4; i++)
{
wheels[i-1] = std::stod(splitStr[i]);
}
setState(State::Manual::getInstance());
uartCommunicator.sendTelegram(wheels[0], wheels[1], wheels[2], wheels[3]);
}
@@ -73,7 +79,7 @@ void LFR_StateMachine::parseString(string s)
}
LFR_StateMachine::LFR_StateMachine():
autonomousMode(videoHeight, videoWidth, thresholdBinary, gaussKernelSize, maxSpeed [&](std::exception const &ex)
autonomousMode(videoHeight, videoWidth, thresholdBinary, gaussKernelSize, maxSpeed, [&](std::exception const &ex)
{
std::unique_lock<std::mutex> lock(mutex);
std::cerr<<"camera exception:"<<ex.what()<<std::endl;
@@ -98,16 +104,26 @@ LFR_StateMachine::LFR_StateMachine():
currentState = &State::Idle::getInstance();
currentState->enter(this);
//Start the permanent loop
char input;
std::cout << "press q to quit" << std::endl;
std::cin >> input;
std::cout << "binned" << std::endl;
while (input != 'q')
cv::VideoWriter writer = cv::VideoWriter("video_200.avi", cv::VideoWriter::fourcc('M','J','P','G'), 4.0, cv::Size(videoWidth, videoHeight), true);
auto t_start = std::chrono::high_resolution_clock::now();
auto t_end = std::chrono::high_resolution_clock::now();
double dur = std::chrono::duration<double, std::milli>(t_end-t_start).count();
while(dur < 60000)
{
std::cin >> input;
std::cout << "binned" << std::endl;
t_end = std::chrono::high_resolution_clock::now();
dur = std::chrono::duration<double, std::milli>(t_end-t_start).count();
{
this_thread::sleep_for(std::chrono::milliseconds(50));
std::unique_lock<std::mutex> lock(imgMutex);
if(!this->image.empty())
{
writer.write(this->image);
}
}
}
writer.release();
std::cout << "Exiting central" << std::endl;
}
@@ -119,11 +135,6 @@ void LFR_StateMachine::setState(LFR_IState& newState)
currentState = &newState;
currentState->enter(this);
}
else
{
std::cout << "no switch" << std::endl;
}
}
void LFR_StateMachine::enterAutonomous()
@@ -145,6 +156,10 @@ void LFR_StateMachine::enterAutonomous()
double delta = static_cast<double>(deltaMs) / 1000.0;
double frameRate = 1.0 / static_cast<double>(delta);*/
double frameRate = -1.0;
{
std::unique_lock<std::mutex> lock(imgMutex);
image = result.rawImage;
}
if (result.validLane)
{
+6 -1
View File
@@ -16,7 +16,7 @@ class LFR_StateMachine
const int videoHeight = 720;
const int videoWidth = 1280;
const int gaussKernelSize = 11;
const double maxSpeed = 0.5;
const double maxSpeed = 0.20;
std::mutex mutex;
@@ -24,6 +24,9 @@ class LFR_StateMachine
LFR_UART uartCommunicator;
LFR_Socket socket;
std::mutex imgMutex;
Mat image;
vector<string> split (string s, string delimiter) const;
void sanitize (string& s) const;
bool checkStringValidity (const std::vector<std::string>& s) const;
@@ -36,3 +39,5 @@ public:
inline LFR_IState* getCurrentState() const {return currentState;}
void setState(LFR_IState& newState);
};