Compare commits

...

12 Commits

Author SHA1 Message Date
16fa3780d9 Включён таймер
Почему-то каждый раз слетает
2025-04-04 12:03:50 +03:00
c6f2acf140 Переписанный код на c++/cli
Рабочий вариант
2025-04-04 11:49:03 +03:00
9f0faac821 Тест 2025-04-04 00:05:34 +03:00
994b0f8712 Создание класса клиента 2025-04-03 13:07:57 +03:00
e83f355fa3 Переписывание подключения 2025-04-03 13:05:30 +03:00
34d53ad7f1 Разделение кода на функции
Нужно, чтобы создать класс клиента
2025-04-03 11:45:18 +03:00
7248be8217 Написан код клиента c++
Подключение, отправка и получение данных
2025-04-02 22:00:47 +03:00
e28a8a01bf Тест подключения 2025-04-01 20:00:52 +03:00
acf6379279 Чистка кода от мусора 2025-04-01 14:27:21 +03:00
eeb7c5764f Удаление спрятанного .gitignore 2025-04-01 14:23:14 +03:00
17d2edfceb Загрузка DroneClientCpp 2025-04-01 14:13:49 +03:00
b565ec7608 Новый .gitignore 2025-04-01 14:12:24 +03:00
25 changed files with 1995 additions and 712 deletions

58
.gitignore vendored Normal file
View File

@ -0,0 +1,58 @@
# Файлы и папки Visual Studio
*.obj
*.exe
*.pdb
*.user
*.aps
*.pch
*.vspscc
*.vssscc
*_i.c
*_p.c
*.ncb
*.suo
*.tlb
*.tlh
*.bak
*.cache
*.ilk
*.log
*.sbr
*.scc
*.idb
*.tlog
*.ipch
*.db
# Папки сборки
bin/
obj/
[Bb]in/
[Oo]bj/
Debug/
Release/
x64/
x86/
[Any CPU]/
# Файлы кэша и настройки VS
.vscode/
*.code-workspace
.vs/
*.sln.docstates
# NuGet
packages/
*.nupkg
*.snupkg
# Дополнительные временные файлы
Thumbs.db
*.DS_Store
# Игнорировать файлы резервирования
~$*
# Опционально: игнорировать файлы конфигурации пользователя
appsettings.json
*.config.user

View File

@ -1,3 +0,0 @@
.vs/
obj/
bin/

View File

@ -1,67 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace DroneClient
{
internal class Drone
{
public struct DataOut
internal class Drone
{
public float AccX, AccY, AccZ;
public float GyrX, GyrY, GyrZ;
public float PosX, PosY;
public float LaserRange;
public struct DataOut
{
public float AccX, AccY, AccZ;
public float GyrX, GyrY, GyrZ;
public float PosX, PosY;
public float LaserRange;
}
public struct DataIn
{
public float MotorUL, MotorUR, MotorDL, MotorDR;
}
public static byte[] getBytes(object data)
{
int size = Marshal.SizeOf(data);
byte[] arr = new byte[size];
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(data, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return arr;
}
public static object fromBytes(byte[] arr, Type type)
{
object mem = new object();
int size = Marshal.SizeOf(type);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
mem = Marshal.PtrToStructure(ptr, type);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return mem;
}
}
public struct DataIn
{
public float MotorUL, MotorUR, MotorDL, MotorDR;
}
public static byte[] getBytes(object data)
{
int size = Marshal.SizeOf(data);
byte[] arr = new byte[size];
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(data, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return arr;
}
public static object fromBytes(byte[] arr, Type type)
{
object mem = new object();
int size = Marshal.SizeOf(type);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
mem = Marshal.PtrToStructure(ptr, type);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return mem;
}
}
}

View File

@ -1,108 +1,103 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Net;
namespace DroneSimulator
{
internal class NetClient
{
public class ConnectData
internal class NetClient
{
public bool Connect;
public class ConnectData
{
public bool Connect;
public Socket? Server;
public Socket? Server;
}
public class ReceiveData
{
public byte[]? Buffer;
public int Size;
public Socket? Server;
}
private class ServerData
{
public const int size = 1024;
public byte[] buffer = new byte[size];
}
private bool Connected = false;
private Socket? ServerSocket = null;
private ServerData DataServer = new ServerData();
public delegate void ClientCallback(object o);
private ClientCallback? ConnectionCallback;
private ClientCallback? ReceiveCallback;
public enum ClientState { Error, Connected, Stop };
public ClientState Connect(string Addr, int Port, ClientCallback Connection, ClientCallback Receive)
{
if (Connected)
{
try { ServerSocket?.Shutdown(SocketShutdown.Both); } catch { }
ServerSocket?.Close();
Connected = false;
return ClientState.Stop;
}
ConnectionCallback = Connection;
ReceiveCallback = Receive;
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(Addr), Port);
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try { ServerSocket.Connect(ep); }
catch { ServerSocket.Close(); return ClientState.Error; }
Connected = true;
ConnectionCallback(new ConnectData { Connect = true, Server = ServerSocket });
ReceiveData receiveData = new ReceiveData { Buffer = DataServer.buffer, Size = ServerData.size, Server = ServerSocket };
try { ServerSocket.BeginReceive(DataServer.buffer, 0, ServerData.size, 0, new AsyncCallback(ReadCallback), receiveData); }
catch { }
return ClientState.Connected;
}
public void Close()
{
try { ServerSocket?.Shutdown(SocketShutdown.Both); } catch { }
ServerSocket?.Close();
Connected = false;
}
public void ReadCallback(IAsyncResult ar)
{
ReceiveData cd = (ReceiveData)ar.AsyncState;
if (cd == null) return;
int bytes = 0;
try { bytes = ServerSocket.EndReceive(ar); } catch { }
if (bytes == 0)
{
ServerSocket?.Close();
Connected = false;
if (ServerSocket != null) ConnectionCallback(new ConnectData { Connect = false, Server = null });
return;
}
ReceiveCallback(new ReceiveData { Buffer = cd.Buffer, Size = bytes, Server = ServerSocket });
try { ServerSocket?.BeginReceive(cd.Buffer, 0, ServerData.size, 0, new AsyncCallback(ReadCallback), cd); }
catch { }
}
}
public class ReceiveData
{
public byte[]? Buffer;
public int Size;
public Socket? Server;
}
private class ServerData
{
public const int size = 1024;
public byte[] buffer = new byte[size];
}
private bool Connected = false;
private Socket? ServerSocket = null;
private ServerData DataServer = new ServerData();
public delegate void ClientCallback(object o);
private ClientCallback? ConnectionCallback;
private ClientCallback? ReceiveCallback;
public enum ClientState { Error, Connected, Stop };
public ClientState Connect(string Addr, int Port, ClientCallback Connection, ClientCallback Receive)
{
if (Connected)
{
try { ServerSocket?.Shutdown(SocketShutdown.Both); } catch { }
ServerSocket?.Close();
Connected = false;
return ClientState.Stop;
}
ConnectionCallback = Connection;
ReceiveCallback = Receive;
IPEndPoint ep = new IPEndPoint(IPAddress.Parse(Addr), Port);
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try { ServerSocket.Connect(ep); }
catch { ServerSocket.Close(); return ClientState.Error; }
Connected = true;
ConnectionCallback(new ConnectData { Connect = true, Server = ServerSocket });
ReceiveData receiveData = new ReceiveData { Buffer = DataServer.buffer, Size = ServerData.size, Server = ServerSocket };
try { ServerSocket.BeginReceive(DataServer.buffer, 0, ServerData.size, 0, new AsyncCallback(ReadCallback), receiveData); }
catch { }
return ClientState.Connected;
}
public void Close()
{
try { ServerSocket?.Shutdown(SocketShutdown.Both); } catch { }
ServerSocket?.Close();
Connected = false;
}
public void ReadCallback(IAsyncResult ar)
{
ReceiveData cd = (ReceiveData)ar.AsyncState;
if (cd == null) return;
int bytes = 0;
try { bytes = ServerSocket.EndReceive(ar); } catch { }
if (bytes == 0)
{
ServerSocket?.Close();
Connected = false;
if (ServerSocket != null) ConnectionCallback(new ConnectData { Connect = false, Server = null });
return;
}
ReceiveCallback(new ReceiveData { Buffer = cd.Buffer, Size = bytes, Server = ServerSocket });
try { ServerSocket?.BeginReceive(cd.Buffer, 0, ServerData.size, 0, new AsyncCallback(ReadCallback), cd); }
catch { }
}
}
}

106
DroneClientCpp/Client.cpp Normal file
View File

@ -0,0 +1,106 @@
#pragma once
#include "Client.h"
Client::Client(const char* ip, int port) : running(true), Connection(INVALID_SOCKET)
{
if (!ConnectToServer(ip, port))
{
std::cerr << "Failed to connect to server!" << std::endl;
}
}
Client::~Client()
{
Stop();
CloseConnection();
}
bool Client::ConnectToServer(const char* ip, int port)
{
WSAData wsaData;
WORD DLLVersion = MAKEWORD(2, 2);
if (WSAStartup(DLLVersion, &wsaData) != 0)
{
std::cerr << "Error: WSAStartup failed" << std::endl;
return false;
}
SOCKADDR_IN addr;
inet_pton(AF_INET, ip, &addr.sin_addr);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
Connection = socket(AF_INET, SOCK_STREAM, 0);
if (Connection == INVALID_SOCKET)
{
std::cerr << "Error: Failed to create socket" << std::endl;
WSACleanup();
return false;
}
if (connect(Connection, (SOCKADDR*)&addr, sizeof(addr)) != 0)
{
std::cerr << "Error: Failed to connect to server" << std::endl;
closesocket(Connection);
WSACleanup();
return false;
}
return true;
}
void Client::CloseConnection()
{
if (Connection != INVALID_SOCKET)
{
closesocket(Connection);
WSACleanup();
Connection = INVALID_SOCKET;
}
}
void Client::ReceiveHandler()
{
while (running)
{
DataIn tempData;
int result = recv(Connection, (char*)&tempData, sizeof(tempData), 0);
if (result <= 0)
{
std::cerr << "Error: Connection lost (recv failed)" << std::endl;
running = false;
break;
}
std::lock_guard<std::mutex> lock(dataMutex);
dataIn = tempData;
}
}
void Client::SendHandler()
{
while (running)
{
{
std::lock_guard<std::mutex> lock(dataMutex);
send(Connection, (char*)&dataOut, sizeof(dataOut), 0);
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void Client::Start()
{
recvThread = std::thread(&Client::ReceiveHandler, this);
sendThread = std::thread(&Client::SendHandler, this);
}
void Client::Stop()
{
running = false;
if (recvThread.joinable()) recvThread.join();
if (sendThread.joinable()) sendThread.join();
}

44
DroneClientCpp/Client.h Normal file
View File

@ -0,0 +1,44 @@
#pragma once
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <thread>
#include <atomic>
#include <mutex>
#pragma comment(lib, "Ws2_32.lib")
class Client
{
public:
Client(const char* ip, int port);
~Client();
void Start(); // Запуск потоков
void Stop(); // Остановка потоков
struct DataIn
{
float AccX, AccY, AccZ;
float GyrX, GyrY, GyrZ;
float PosX, PosY, LaserRange;
} dataIn;
struct DataOut
{
float MotorUL, MotorUR, MotorDL, MotorDR;
} dataOut;
bool ConnectToServer(const char* ip, int port);
void CloseConnection();
private:
std::atomic<bool> running;
std::mutex dataMutex;
SOCKET Connection;
std::thread recvThread;
std::thread sendThread;
void ReceiveHandler();
void SendHandler();
};

View File

@ -0,0 +1,65 @@
#pragma once
#include <Windows.h>
#include <vcclr.h>
#using <System.dll>
#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
namespace DroneClient {
public ref class Drone
{
public:
value struct DataOut
{
float AccX, AccY, AccZ;
float GyrX, GyrY, GyrZ;
float PosX, PosY;
float LaserRange;
};
value struct DataIn
{
float MotorUL, MotorUR, MotorDL, MotorDR;
};
static array<Byte>^ GetBytes(Object^ data)
{
int size = Marshal::SizeOf(data);
array<Byte>^ arr = gcnew array<Byte>(size);
IntPtr ptr = IntPtr::Zero;
try
{
ptr = Marshal::AllocHGlobal(size);
Marshal::StructureToPtr(data, ptr, true);
Marshal::Copy(ptr, arr, 0, size);
}
finally
{
Marshal::FreeHGlobal(ptr);
}
return arr;
}
static Object^ FromBytes(array<Byte>^ arr, Type^ type)
{
int size = Marshal::SizeOf(type);
IntPtr ptr = IntPtr::Zero;
try
{
ptr = Marshal::AllocHGlobal(size);
Marshal::Copy(arr, 0, ptr, size);
return Marshal::PtrToStructure(ptr, type);
}
finally
{
Marshal::FreeHGlobal(ptr);
}
}
};
}

View File

@ -0,0 +1,38 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.12.35527.113
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DroneClientCpp", "DroneClientCpp.vcxproj", "{690C304C-A70B-4B0F-BF61-8C51290BF444}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TestClientConnection", "..\TestClientConnection\TestClientConnection.vcxproj", "{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{690C304C-A70B-4B0F-BF61-8C51290BF444}.Debug|x64.ActiveCfg = Debug|x64
{690C304C-A70B-4B0F-BF61-8C51290BF444}.Debug|x64.Build.0 = Debug|x64
{690C304C-A70B-4B0F-BF61-8C51290BF444}.Debug|x86.ActiveCfg = Debug|Win32
{690C304C-A70B-4B0F-BF61-8C51290BF444}.Debug|x86.Build.0 = Debug|Win32
{690C304C-A70B-4B0F-BF61-8C51290BF444}.Release|x64.ActiveCfg = Release|x64
{690C304C-A70B-4B0F-BF61-8C51290BF444}.Release|x64.Build.0 = Release|x64
{690C304C-A70B-4B0F-BF61-8C51290BF444}.Release|x86.ActiveCfg = Release|Win32
{690C304C-A70B-4B0F-BF61-8C51290BF444}.Release|x86.Build.0 = Release|Win32
{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}.Debug|x64.ActiveCfg = Debug|x64
{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}.Debug|x64.Build.0 = Debug|x64
{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}.Debug|x86.ActiveCfg = Debug|Win32
{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}.Debug|x86.Build.0 = Debug|Win32
{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}.Release|x64.ActiveCfg = Release|x64
{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}.Release|x64.Build.0 = Release|x64
{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}.Release|x86.ActiveCfg = Release|Win32
{B7CC5245-B628-40E9-A9A0-A904E2BF25EA}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,138 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<ProjectGuid>{690C304C-A70B-4B0F-BF61-8C51290BF444}</ProjectGuid>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<Keyword>ManagedCProj</Keyword>
<RootNamespace>DroneClientCpp</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="FormMain.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="DroneClient.h" />
<ClInclude Include="FormMain.h">
<FileType>CppForm</FileType>
</ClInclude>
<ClInclude Include="NetClient.h" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="FormMain.resx">
<DependentUpon>FormMain.h</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Исходные файлы">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Файлы заголовков">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Файлы ресурсов">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="FormMain.cpp">
<Filter>Исходные файлы</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="FormMain.h">
<Filter>Файлы заголовков</Filter>
</ClInclude>
<ClInclude Include="NetClient.h">
<Filter>Файлы заголовков</Filter>
</ClInclude>
<ClInclude Include="DroneClient.h">
<Filter>Файлы заголовков</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -0,0 +1,12 @@
#include "FormMain.h"
#include <Windows.h>
using namespace DroneClientCpp;
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew FormMain);
return 0;
}

BIN
DroneClientCpp/FormMain.h Normal file

Binary file not shown.

View File

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>310, 17</value>
</metadata>
</root>

12
DroneClientCpp/MyForm.cpp Normal file
View File

@ -0,0 +1,12 @@
#include "MyForm.h"
#include <Windows.h>
using namespace DroneClientCpp;
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
Application::EnableVisualStyles();
Application::SetCompatibleTextRenderingDefault(false);
Application::Run(gcnew MyForm);
return 0;
}

BIN
DroneClientCpp/MyForm.h Normal file

Binary file not shown.

120
DroneClientCpp/MyForm.resx Normal file
View File

@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

256
DroneClientCpp/NetClient.h Normal file
View File

@ -0,0 +1,256 @@
// NetClient.h
#pragma once
#include <Windows.h>
#include <vcclr.h>
#using <System.dll>
#using <System.Net.dll>
using namespace System;
using namespace System::Net;
using namespace System::Net::Sockets;
using namespace System::Runtime::InteropServices;
namespace DroneSimulator
{
public ref class NetClient
{
public:
// Вложенный класс для данных подключения
ref class ConnectData
{
public:
property bool Connect;
property Socket^ Server;
};
// Вложенный класс для данных приема
ref class ReceiveData
{
public:
property array<Byte>^ Buffer;
property int Size;
property Socket^ Server;
};
// Состояния клиента
enum class ClientState { Error, Connected, Stop };
// Делегат для callback-функций
delegate void ClientCallback(Object^ o);
NetClient()
{
Connected = false;
ServerSocket = nullptr;
DataServer = gcnew ServerData();
}
~NetClient()
{
// Вызываем Close() для корректного закрытия соединения
Close();
// Дополнительная очистка ресурсов
if (DataServer != nullptr)
{
// Очищаем буфер данных
DataServer->buffer = nullptr;
DataServer = nullptr;
}
// Обнуляем callback-делегаты
ConnectionCallback = nullptr;
ReceiveCallback = nullptr;
}
ClientState Connect(String^ addr, int port, ClientCallback^ connectionCallback, ClientCallback^ receiveCallback)
{
if (Connected)
{
Disconnect();
return ClientState::Stop;
}
ConnectionCallback = connectionCallback;
ReceiveCallback = receiveCallback;
try
{
IPEndPoint^ ep = gcnew IPEndPoint(IPAddress::Parse(addr), port);
ServerSocket = gcnew Socket(AddressFamily::InterNetwork, SocketType::Stream, ProtocolType::Tcp);
ServerSocket->Connect(ep);
Connected = true;
// Уведомление о подключении
ConnectData^ connectData = gcnew ConnectData();
connectData->Connect = true;
connectData->Server = ServerSocket;
ConnectionCallback(connectData);
// Начало приема данных
ReceiveData^ receiveData = gcnew ReceiveData();
receiveData->Buffer = DataServer->buffer;
receiveData->Size = ServerData::size;
receiveData->Server = ServerSocket;
ServerSocket->BeginReceive(DataServer->buffer, 0, ServerData::size, SocketFlags::None, gcnew AsyncCallback(this, &NetClient::ReadCallback), receiveData);
return ClientState::Connected;
}
catch (Exception^)
{
if (ServerSocket != nullptr)
{
ServerSocket->Close();
}
return ClientState::Error;
}
}
void Close()
{
Disconnect();
}
private:
ref class ServerData
{
public:
static const int size = 1024;
array<Byte>^ buffer = gcnew array<Byte>(size);
};
bool Connected;
Socket^ ServerSocket;
ServerData^ DataServer;
ClientCallback^ ConnectionCallback;
ClientCallback^ ReceiveCallback;
void Disconnect()
{
if (ServerSocket != nullptr)
{
try { ServerSocket->Shutdown(SocketShutdown::Both); }
catch (...) {}
ServerSocket->Close();
ServerSocket = nullptr;
}
Connected = false;
}
void ReadCallback(IAsyncResult^ ar)
{
try
{
// Проверка на null входного параметра
if (ar == nullptr) return;
// Безопасное приведение типа
ReceiveData^ cd = dynamic_cast<ReceiveData^>(ar->AsyncState);
if (cd == nullptr || ServerSocket == nullptr || !ServerSocket->Connected)
{
Disconnect();
return;
}
int bytes = 0;
try
{
bytes = ServerSocket->EndReceive(ar);
}
catch (ObjectDisposedException^)
{
// Сокет был закрыт
Disconnect();
return;
}
catch (SocketException^ ex)
{
// Логирование ошибки сокета
System::Diagnostics::Debug::WriteLine(
"Socket receive error: " + ex->Message);
Disconnect();
return;
}
catch (...)
{
Disconnect();
return;
}
// Проверка на разрыв соединения
if (bytes == 0)
{
Disconnect();
if (ConnectionCallback != nullptr)
{
ConnectData^ disconnectData = gcnew ConnectData();
disconnectData->Connect = false;
disconnectData->Server = nullptr;
ConnectionCallback(disconnectData);
}
return;
}
// Вызов callback получения данных
if (ReceiveCallback != nullptr && cd->Buffer != nullptr)
{
try
{
ReceiveCallback(cd);
}
catch (Exception^ ex)
{
System::Diagnostics::Debug::WriteLine(
"ReceiveCallback error: " + ex->Message);
}
}
// Продолжаем прием данных
if (ServerSocket != nullptr && ServerSocket->Connected)
{
try
{
IAsyncResult^ result = ServerSocket->BeginReceive(
cd->Buffer,
0,
ServerData::size,
SocketFlags::None,
gcnew AsyncCallback(this, &NetClient::ReadCallback),
cd);
// Проверка на ошибку асинхронной операции
if (result == nullptr)
{
Disconnect();
}
}
catch (ObjectDisposedException^)
{
Disconnect();
}
catch (SocketException^ ex)
{
System::Diagnostics::Debug::WriteLine(
"BeginReceive error: " + ex->Message);
Disconnect();
}
catch (...)
{
Disconnect();
}
}
}
catch (Exception^ ex)
{
System::Diagnostics::Debug::WriteLine(
"ReadCallback general error: " + ex->Message);
Disconnect();
}
}
};
}

11
DroneClientCpp/Source.cpp Normal file
View File

@ -0,0 +1,11 @@
#include "MyForm.h"
using namespace MyWinFormsApp; // ???????????? ???? ?????? ???????
[STAThread]
int main(array<String^>^ args) {
Application::EnableVisualStyles(); // ???????? ??????????? ????? ????????? ??????????
Application::SetCompatibleTextRenderingDefault(false); // ????????? ?????????? ??????
Application::Run(gcnew MyForm()); // ?????? ?????
return 0;
}

View File

@ -1,3 +0,0 @@
.vs/
obj/
bin/

View File

@ -1,262 +1,256 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using static System.Windows.Forms.AxHost;
namespace DroneSimulator
{
internal class Drone
{
public int ID;
public float Mass; // Масса
public bool Active; // Живой?
public float Length; // Длинна лучей
public Vector3 PosXYZ, SpdXYZ, AccXYZ; // Положение в пространстве: Позиция, Скорость, Ускорение
public Quaternion Quat; // Основной кватернион
public float Power = 0; // Тяга всех двигателей
public Vector3 SpdPRY, AccPRY; // Поворот в пространстве: pitch roll yaw
public Vector3 Acc, Gyr; // Имитация: Акселерометр, Гироскоп
public float LaserRange; // Имитация: Дальномер
private const float Gravity = 1.0f;
private const float TO_GRAD = 180 / MathF.PI;
private const float TO_RADI = MathF.PI / 180;
private Thread DroneThread;
private int Timer;
private static int CounterID = 0;
public struct DataOut
internal class Drone
{
public float AccX, AccY, AccZ;
public float GyrX, GyrY, GyrZ;
public float PosX, PosY;
public float LaserRange;
public int ID;
public float Mass; // Масса
public bool Active; // Живой?
public float Length; // Длинна лучей
public Vector3 PosXYZ, SpdXYZ, AccXYZ; // Положение в пространстве: Позиция, Скорость, Ускорение
public Quaternion Quat; // Основной кватернион
public float Power = 0; // Тяга всех двигателей
public Vector3 SpdPRY, AccPRY; // Поворот в пространстве: pitch roll yaw
public byte[] getBytes()
{
int size = Marshal.SizeOf(this);
byte[] arr = new byte[size];
public Vector3 Acc, Gyr; // Имитация: Акселерометр, Гироскоп
public float LaserRange; // Имитация: Дальномер
IntPtr ptr = IntPtr.Zero;
try
private const float Gravity = 1.0f;
private const float TO_GRAD = 180 / MathF.PI;
private const float TO_RADI = MathF.PI / 180;
private Thread DroneThread;
private int Timer;
private static int CounterID = 0;
public struct DataOut
{
ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(this, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return arr;
}
}
public float AccX, AccY, AccZ;
public float GyrX, GyrY, GyrZ;
public float PosX, PosY;
public float LaserRange;
public struct DataIn
{
public float MotorUL, MotorUR, MotorDL, MotorDR;
public byte[] getBytes()
{
int size = Marshal.SizeOf(this);
byte[] arr = new byte[size];
public void fromBytes(byte[] arr)
{
DataIn mem = new DataIn();
int size = Marshal.SizeOf(mem);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
mem = (DataIn)Marshal.PtrToStructure(ptr, mem.GetType());
}
finally
{
Marshal.FreeHGlobal(ptr);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(this, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
}
finally
{
Marshal.FreeHGlobal(ptr);
}
return arr;
}
}
this = mem;
}
}
private void ThreadFunction()
{
while (DroneThread != null)
{
float time = Environment.TickCount - Timer;
Timer = Environment.TickCount;
Action(time / 100);
Thread.Sleep(1);
}
}
public Drone(int id)
{
ID = id;
Active = false;
PosXYZ = new Vector3(2000, 1000, 0);
SpdXYZ = Vector3.Zero;
AccXYZ = Vector3.Zero;
Quat = Quaternion.Identity;
DroneThread = new Thread(new ThreadStart(ThreadFunction));
Timer = Environment.TickCount;
DroneThread.Start();
}
public int Create(float mass, float len)
{
Mass = Range(mass);
Length = len;
Active = true;
return ID;
}
public void Close()
{
DroneThread = null;
}
private float GetAngle(float a1, float a2, float az)
{
if (a2 == 0.0f && az == 0.0f)
{
if (a1 > 0) return 90;
if (a1 < 0) return -90;
return 0;
}
return MathF.Atan(a1 / MathF.Sqrt(a2 * a2 + az * az)) * TO_GRAD;
}
public void Rotate(float x, float y, float z)
{
x = x * MathF.PI / 180;
y = y * MathF.PI / 180;
z = -z * MathF.PI / 180;
Quaternion map = Quat;
Quaternion spd = new Quaternion(x, y, z, 0);
Quaternion aq = spd * map;
map.W -= 0.5f * aq.W;
map.X -= 0.5f * aq.X;
map.Y -= 0.5f * aq.Y;
map.Z -= 0.5f * aq.Z;
Quat = Quaternion.Normalize(map);
}
public Vector4 GetOrientation()
{
Quaternion grav = new Quaternion(0, 0, 1, 0);
grav = (Quat * grav) * Quaternion.Inverse(Quat);
float yaw = 2 * MathF.Atan2(Quat.Z, Quat.W) * TO_GRAD;
if (yaw < 0.0f) yaw = 360.0f + yaw;
return new Vector4(GetAngle(grav.Y, grav.X, grav.Z), GetAngle(-grav.X, grav.Y, grav.Z), yaw, grav.Z);
}
public void Action(float time)
{
if (!Active) return;
float flow = Power;
if (PosXYZ.Z < 100)
{
flow += flow * 0.1f; // Воздушная подушка
}
Quaternion pow = Quaternion.Inverse(Quat) * new Quaternion(0, 0, flow, 0) * Quat;
AccXYZ = new Vector3(pow.X, pow.Y, pow.Z) / Mass;
SpdPRY += AccPRY * time / (Mass * Length);
SpdXYZ += (AccXYZ + new Vector3(0, 0, -Gravity)) * time;
PosXYZ += SpdXYZ * time;
if (PosXYZ.Z < 0)
{
SpdPRY = Vector3.Zero;
SpdXYZ.X = 0;
SpdXYZ.Y = 0;
Quat = Quaternion.Identity;
}
else Rotate(SpdPRY.X, SpdPRY.Y, SpdPRY.Z);
Vector4 ori = GetOrientation();
if (PosXYZ.Z < 0)
{
PosXYZ.Z = 0;
/*if (SpdXYZ.Z < -5)
public struct DataIn
{
Active = false; // Сильно ударился о землю
}*/
public float MotorUL, MotorUR, MotorDL, MotorDR;
/*if (MathF.Abs(ori.X) > 45 || MathF.Abs(ori.Y) > 45)
public void fromBytes(byte[] arr)
{
DataIn mem = new DataIn();
int size = Marshal.SizeOf(mem);
IntPtr ptr = IntPtr.Zero;
try
{
ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(arr, 0, ptr, size);
mem = (DataIn)Marshal.PtrToStructure(ptr, mem.GetType());
}
finally
{
Marshal.FreeHGlobal(ptr);
}
this = mem;
}
}
private void ThreadFunction()
{
Active = false; // Повредил винты при посадке
}*/
while (DroneThread != null)
{
float time = Environment.TickCount - Timer;
Timer = Environment.TickCount;
Action(time / 100);
Thread.Sleep(1);
}
}
SpdXYZ.Z = 0;
Acc = new Vector3(0, 0, 1);
Gyr = Vector3.Zero;
LaserRange = 0;
}
else
{
/*if (ori.W < 0)
public Drone(int id)
{
Active = false; // Перевернулся вверх ногами
}*/
ID = id;
Active = false;
PosXYZ = new Vector3(2000, 1000, 0);
SpdXYZ = Vector3.Zero;
AccXYZ = Vector3.Zero;
Quat = Quaternion.Identity;
Quaternion grav = new Quaternion(AccXYZ.X, AccXYZ.Y, AccXYZ.Z, 0);
grav = (Quat * grav) * Quaternion.Inverse(Quat);
Acc = new Vector3(grav.X, grav.Y, grav.Z);
DroneThread = new Thread(new ThreadStart(ThreadFunction));
Timer = Environment.TickCount;
DroneThread.Start();
}
Gyr = SpdPRY;
public int Create(float mass, float len)
{
Mass = Range(mass);
Length = len;
float tilt = (MathF.Abs(ori.X) + MathF.Abs(ori.Y)) * TO_RADI;
Active = true;
if (tilt < 90 && ori.W > 0) LaserRange = PosXYZ.Z / MathF.Cos(tilt);
else LaserRange = float.MaxValue;
}
return ID;
}
public void Close()
{
DroneThread = null;
}
private float GetAngle(float a1, float a2, float az)
{
if (a2 == 0.0f && az == 0.0f)
{
if (a1 > 0) return 90;
if (a1 < 0) return -90;
return 0;
}
return MathF.Atan(a1 / MathF.Sqrt(a2 * a2 + az * az)) * TO_GRAD;
}
public void Rotate(float x, float y, float z)
{
x = x * MathF.PI / 180;
y = y * MathF.PI / 180;
z = -z * MathF.PI / 180;
Quaternion map = Quat;
Quaternion spd = new Quaternion(x, y, z, 0);
Quaternion aq = spd * map;
map.W -= 0.5f * aq.W;
map.X -= 0.5f * aq.X;
map.Y -= 0.5f * aq.Y;
map.Z -= 0.5f * aq.Z;
Quat = Quaternion.Normalize(map);
}
public Vector4 GetOrientation()
{
Quaternion grav = new Quaternion(0, 0, 1, 0);
grav = (Quat * grav) * Quaternion.Inverse(Quat);
float yaw = 2 * MathF.Atan2(Quat.Z, Quat.W) * TO_GRAD;
if (yaw < 0.0f) yaw = 360.0f + yaw;
return new Vector4(GetAngle(grav.Y, grav.X, grav.Z), GetAngle(-grav.X, grav.Y, grav.Z), yaw, grav.Z);
}
public void Action(float time)
{
if (!Active) return;
float flow = Power;
if (PosXYZ.Z < 100)
{
flow += flow * 0.1f; // Воздушная подушка
}
Quaternion pow = Quaternion.Inverse(Quat) * new Quaternion(0, 0, flow, 0) * Quat;
AccXYZ = new Vector3(pow.X, pow.Y, pow.Z) / Mass;
SpdPRY += AccPRY * time / (Mass * Length);
SpdXYZ += (AccXYZ + new Vector3(0, 0, -Gravity)) * time;
PosXYZ += SpdXYZ * time;
if (PosXYZ.Z < 0)
{
SpdPRY = Vector3.Zero;
SpdXYZ.X = 0;
SpdXYZ.Y = 0;
Quat = Quaternion.Identity;
}
else Rotate(SpdPRY.X, SpdPRY.Y, SpdPRY.Z);
Vector4 ori = GetOrientation();
if (PosXYZ.Z < 0)
{
PosXYZ.Z = 0;
/*if (SpdXYZ.Z < -5)
{
Active = false; // Сильно ударился о землю
}*/
/*if (MathF.Abs(ori.X) > 45 || MathF.Abs(ori.Y) > 45)
{
Active = false; // Повредил винты при посадке
}*/
SpdXYZ.Z = 0;
Acc = new Vector3(0, 0, 1);
Gyr = Vector3.Zero;
LaserRange = 0;
}
else
{
/*if (ori.W < 0)
{
Active = false; // Перевернулся вверх ногами
}*/
Quaternion grav = new Quaternion(AccXYZ.X, AccXYZ.Y, AccXYZ.Z, 0);
grav = (Quat * grav) * Quaternion.Inverse(Quat);
Acc = new Vector3(grav.X, grav.Y, grav.Z);
Gyr = SpdPRY;
float tilt = (MathF.Abs(ori.X) + MathF.Abs(ori.Y)) * TO_RADI;
if (tilt < 90 && ori.W > 0) LaserRange = PosXYZ.Z / MathF.Cos(tilt);
else LaserRange = float.MaxValue;
}
}
private float Range(float pow)
{
if (pow > 1) pow = 1;
if (pow < 0) pow = 0;
return pow;
}
public void SetQadroPow(float ul, float ur, float dl, float dr)
{
ul = Range(ul); ur = Range(ur); dl = Range(dl); dr = Range(dr);
Power = (ul + ur + dl + dr) / 4;
AccPRY.Y = ((ul + dl) - (ur + dr));
AccPRY.X = ((ul + ur) - (dl + dr));
AccPRY.Z = ((ul + dr) - (dl + ur)) / 4;
}
}
private float Range(float pow)
{
if (pow > 1) pow = 1;
if (pow < 0) pow = 0;
return pow;
}
public void SetQadroPow(float ul, float ur, float dl, float dr)
{
ul = Range(ul); ur = Range(ur); dl = Range(dl); dr = Range(dr);
Power = (ul + ur + dl + dr) / 4;
AccPRY.Y = ((ul + dl) - (ur + dr));
AccPRY.X = ((ul + ur) - (dl + dr));
AccPRY.Z = ((ul + dr) - (dl + ur)) / 4;
}
}
}

View File

@ -1,145 +1,140 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Net;
namespace DroneSimulator
{
internal class NetServerClients
{
public class ConnectData
internal class NetServerClients
{
public int ID;
public bool Connect;
public int Count;
public Socket? Client;
}
public class ReceiveData
{
public int ID;
public byte[]? Buffer;
public int Size;
public Socket? Client;
}
private class ClientData
{
public int ID;
public Socket? workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
}
private int SocketID = 0;
private int SocketLimit;
private Socket? ServerSocket;
private List<ClientData> ClientSockets = new List<ClientData>();
public delegate void ServerCallback(object o);
private ServerCallback? ConnectionCallback;
private ServerCallback? ReceiveCallback;
private bool Active = false;
public enum ServerState { Error, Start, Stop };
public ServerState StartServer(int Port, int Limit, ServerCallback Connection, ServerCallback Receive)
{
if (Active)
{
ServerSocket?.Close();
foreach (ClientData c in ClientSockets)
public class ConnectData
{
try { c.workSocket?.Shutdown(SocketShutdown.Both); } catch { }
c.workSocket?.Close();
public int ID;
public bool Connect;
public int Count;
public Socket? Client;
}
ClientSockets.Clear();
return ServerState.Stop;
}
ConnectionCallback = Connection;
ReceiveCallback = Receive;
public class ReceiveData
{
public int ID;
public byte[]? Buffer;
public int Size;
SocketLimit = Limit;
public Socket? Client;
}
IPEndPoint ip = new(IPAddress.Any, Port);
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
private class ClientData
{
public int ID;
public Socket? workSocket = null;
public const int BufferSize = 1024;
public byte[] buffer = new byte[BufferSize];
}
try
{
ServerSocket.Bind(ip);
ServerSocket.Listen(10);
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
Active = true;
}
catch { ServerSocket.Close(); return ServerState.Error; }
private int SocketID = 0;
private int SocketLimit;
private Socket? ServerSocket;
private List<ClientData> ClientSockets = new List<ClientData>();
return ServerState.Start;
public delegate void ServerCallback(object o);
private ServerCallback? ConnectionCallback;
private ServerCallback? ReceiveCallback;
private bool Active = false;
public enum ServerState { Error, Start, Stop };
public ServerState StartServer(int Port, int Limit, ServerCallback Connection, ServerCallback Receive)
{
if (Active)
{
ServerSocket?.Close();
foreach (ClientData c in ClientSockets)
{
try { c.workSocket?.Shutdown(SocketShutdown.Both); } catch { }
c.workSocket?.Close();
}
ClientSockets.Clear();
return ServerState.Stop;
}
ConnectionCallback = Connection;
ReceiveCallback = Receive;
SocketLimit = Limit;
IPEndPoint ip = new(IPAddress.Any, Port);
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
ServerSocket.Bind(ip);
ServerSocket.Listen(10);
ServerSocket.BeginAccept(new AsyncCallback(AcceptCallback), ServerSocket);
Active = true;
}
catch { ServerSocket.Close(); return ServerState.Error; }
return ServerState.Start;
}
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
if (listener == null) return;
Socket handler;
try { handler = listener.EndAccept(ar); }
catch { ServerSocket?.Close(); Active = false; return; }
if (SocketLimit > ClientSockets.Count)
{
ClientData clientData = new ClientData();
clientData.ID = ++SocketID;
clientData.workSocket = handler;
ClientSockets.Add(clientData);
ConnectionCallback(new ConnectData { ID = clientData.ID, Connect = true, Count = ClientSockets.Count, Client = handler });
handler.BeginReceive(clientData.buffer, 0, ClientData.BufferSize, 0, new AsyncCallback(ReadCallback), clientData);
}
else handler.Close();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
public void ReadCallback(IAsyncResult ar)
{
ClientData cd = (ClientData)ar.AsyncState;
if (cd == null) return;
int bytes = 0;
try { bytes = cd.workSocket.EndReceive(ar); }
catch { }
if (bytes == 0)
{
cd.workSocket?.Close();
ClientSockets.Remove(cd);
ConnectionCallback(new ConnectData { ID = cd.ID, Connect = false, Count = ClientSockets.Count, Client = null });
return;
}
ReceiveCallback(new ReceiveData { ID = cd.ID, Buffer = cd.buffer, Size = bytes, Client = cd.workSocket });
try
{
cd.workSocket?.BeginReceive(cd.buffer, 0, ClientData.BufferSize, 0, new AsyncCallback(ReadCallback), cd);
}
catch { }
}
}
public void AcceptCallback(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
if (listener == null) return;
Socket handler;
try { handler = listener.EndAccept(ar); }
catch{ ServerSocket?.Close(); Active = false; return; }
if (SocketLimit > ClientSockets.Count)
{
ClientData clientData = new ClientData();
clientData.ID = ++SocketID;
clientData.workSocket = handler;
ClientSockets.Add(clientData);
ConnectionCallback(new ConnectData { ID = clientData.ID, Connect = true, Count = ClientSockets.Count, Client = handler });
handler.BeginReceive(clientData.buffer, 0, ClientData.BufferSize, 0, new AsyncCallback(ReadCallback), clientData);
}
else handler.Close();
listener.BeginAccept(new AsyncCallback(AcceptCallback), listener);
}
public void ReadCallback(IAsyncResult ar)
{
ClientData cd = (ClientData)ar.AsyncState;
if (cd == null) return;
int bytes = 0;
try { bytes = cd.workSocket.EndReceive(ar); }
catch { }
if (bytes == 0)
{
cd.workSocket?.Close();
ClientSockets.Remove(cd);
ConnectionCallback(new ConnectData { ID = cd.ID, Connect = false, Count = ClientSockets.Count, Client = null });
return;
}
ReceiveCallback(new ReceiveData { ID = cd.ID, Buffer = cd.buffer, Size = bytes, Client = cd.workSocket });
try
{
cd.workSocket?.BeginReceive(cd.buffer, 0, ClientData.BufferSize, 0, new AsyncCallback(ReadCallback), cd);
}
catch { }
}
}
}

View File

@ -1,186 +1,180 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using System.Reflection.Metadata;
using System.Text;
using System.Threading.Tasks;
using System.Numerics;
namespace DroneSimulator
{
internal class Screen2D
{
public delegate void DrawCallback(Bitmap bmp);
public Screen2D(DrawCallback callback)
internal class Screen2D
{
drawCallback = callback;
}
private class DroneInfo
{
public int ID;
public Color RGB;
public Bitmap? Drone;
public Point PosXY;
public int Height = 0;
public delegate void DrawCallback(Bitmap bmp);
public PointF TiltXY = new Point(0, 0);
public int Azimuth = 0;
}
private DrawCallback drawCallback;
private Bitmap MainArea = new Bitmap(4096, 2560);
private List<DroneInfo> DroneList = new List<DroneInfo>();
public static Bitmap DrawQadro(Color ColorFill)
{
Bitmap drone = new Bitmap(130, 130);
using (Graphics g = Graphics.FromImage(drone))
{
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
SolidBrush solidBrush = new SolidBrush(ColorFill);
Point[] mid = { new Point(35, 65), new Point(70, 40), new Point(70, 90) };
g.FillPolygon(solidBrush, mid);
g.FillEllipse(solidBrush, new Rectangle(15, 15, 35, 35));
g.FillEllipse(solidBrush, new Rectangle(15, 80, 35, 35));
g.FillEllipse(solidBrush, new Rectangle(80, 80, 35, 35));
g.FillEllipse(solidBrush, new Rectangle(80, 15, 35, 35));
g.FillRectangle(solidBrush, new Rectangle(50, 60, 50, 10));
g.DrawEllipse(new Pen(ColorFill), new Rectangle(0, 0, 129, 129));
solidBrush.Dispose();
}
return RotateImage(drone, 90);
}
private static Bitmap RotateImage(Bitmap bmp, float angle)
{
Bitmap rotatedImage = new Bitmap(bmp.Width, bmp.Height);
using (Graphics g = Graphics.FromImage(rotatedImage))
{
// Set the rotation point to the center in the matrix
g.TranslateTransform(bmp.Width / 2, bmp.Height / 2);
// Rotate
g.RotateTransform(angle);
// Restore rotation point in the matrix
g.TranslateTransform(-bmp.Width / 2, -bmp.Height / 2);
// Draw the image on the bitmap
g.DrawImage(bmp, new Point(0, 0));
}
return rotatedImage;
}
public void CreateDrone(Color ColorFill, int ID)
{
DroneInfo info = new DroneInfo();
info.ID = ID;
info.RGB = ColorFill;
info.Drone = DrawQadro(ColorFill);
DroneList.Add(info);
}
public void RemoveDrone(int ID)
{
foreach (DroneInfo i in DroneList)
{
if (i.ID != ID) continue;
DroneList.Remove(i);
break;
}
}
public void DrawScene()
{
using (Graphics g = Graphics.FromImage(MainArea))
{
g.Clear(Color.Gainsboro);
SolidBrush shadowBrush = new SolidBrush(Color.Black);
g.DrawRectangle(new Pen(Color.Black), new Rectangle { Width = MainArea.Width - 1, Height = MainArea.Height - 1 });
foreach (var d in DroneList)
public Screen2D(DrawCallback callback)
{
if (d.Azimuth >= 360) d.Azimuth -= 360;
var bmp = RotateImage(d.Drone, d.Azimuth);
g.FillEllipse(new SolidBrush(Color.FromArgb(50, d.RGB)), d.PosXY.X + d.Height, d.PosXY.Y + d.Height, 130, 130);
g.DrawLine(new Pen(Color.Black), new Point(d.PosXY.X + d.Drone.Width / 2, d.PosXY.Y + d.Drone.Height / 2), new Point(d.PosXY.X + d.Height + d.Drone.Width / 2, d.PosXY.Y + d.Height + d.Drone.Height / 2));
//g.DrawImage(bmp, new Rectangle(d.PosXY.X+32, d.PosXY.Y, 65, 130));
float x1 = 0, y1 = 0;
float x2 = 130, y2 = 0;
float x3 = 0, y3 = 130;
const float TO_RADI = MathF.PI / 180;
Quaternion tilt = new Quaternion(d.TiltXY.X, d.TiltXY.Y, 0, 0);
Quaternion rotate = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), d.Azimuth * TO_RADI);
tilt = tilt * rotate * rotate;
if (tilt.Y > 0)
{
x1 = (int)(Math.Sin(tilt.Y) * 130);
x3 = (int)(Math.Sin(tilt.Y) * 130);
}
else
{
x2 = (int)(Math.Cos(tilt.Y) * 130);
}
if (tilt.X > 0)
{
y1 = (int)(Math.Sin(tilt.X) * 130);
y2 = (int)(Math.Sin(tilt.X) * 130);
}
else
{
y3 = (int)(Math.Cos(tilt.X) * 130);
}
PointF ul = new PointF(d.PosXY.X + x1, d.PosXY.Y + y1); PointF ur = new PointF(d.PosXY.X + x2, d.PosXY.Y + y2);
PointF dl = new PointF(d.PosXY.X + x3, d.PosXY.Y + y3);
PointF[] dest = { ul, ur, dl };
g.DrawImage(bmp, dest);
drawCallback = callback;
}
}
drawCallback(MainArea);
private class DroneInfo
{
public int ID;
public Color RGB;
public Bitmap? Drone;
public Point PosXY;
public int Height = 0;
public PointF TiltXY = new Point(0, 0);
public int Azimuth = 0;
}
private DrawCallback drawCallback;
private Bitmap MainArea = new Bitmap(4096, 2560);
private List<DroneInfo> DroneList = new List<DroneInfo>();
public static Bitmap DrawQadro(Color ColorFill)
{
Bitmap drone = new Bitmap(130, 130);
using (Graphics g = Graphics.FromImage(drone))
{
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighSpeed;
SolidBrush solidBrush = new SolidBrush(ColorFill);
Point[] mid = { new Point(35, 65), new Point(70, 40), new Point(70, 90) };
g.FillPolygon(solidBrush, mid);
g.FillEllipse(solidBrush, new Rectangle(15, 15, 35, 35));
g.FillEllipse(solidBrush, new Rectangle(15, 80, 35, 35));
g.FillEllipse(solidBrush, new Rectangle(80, 80, 35, 35));
g.FillEllipse(solidBrush, new Rectangle(80, 15, 35, 35));
g.FillRectangle(solidBrush, new Rectangle(50, 60, 50, 10));
g.DrawEllipse(new Pen(ColorFill), new Rectangle(0, 0, 129, 129));
solidBrush.Dispose();
}
return RotateImage(drone, 90);
}
private static Bitmap RotateImage(Bitmap bmp, float angle)
{
Bitmap rotatedImage = new Bitmap(bmp.Width, bmp.Height);
using (Graphics g = Graphics.FromImage(rotatedImage))
{
// Set the rotation point to the center in the matrix
g.TranslateTransform(bmp.Width / 2, bmp.Height / 2);
// Rotate
g.RotateTransform(angle);
// Restore rotation point in the matrix
g.TranslateTransform(-bmp.Width / 2, -bmp.Height / 2);
// Draw the image on the bitmap
g.DrawImage(bmp, new Point(0, 0));
}
return rotatedImage;
}
public void CreateDrone(Color ColorFill, int ID)
{
DroneInfo info = new DroneInfo();
info.ID = ID;
info.RGB = ColorFill;
info.Drone = DrawQadro(ColorFill);
DroneList.Add(info);
}
public void RemoveDrone(int ID)
{
foreach (DroneInfo i in DroneList)
{
if (i.ID != ID) continue;
DroneList.Remove(i);
break;
}
}
public void DrawScene()
{
using (Graphics g = Graphics.FromImage(MainArea))
{
g.Clear(Color.Gainsboro);
SolidBrush shadowBrush = new SolidBrush(Color.Black);
g.DrawRectangle(new Pen(Color.Black), new Rectangle { Width = MainArea.Width - 1, Height = MainArea.Height - 1 });
foreach (var d in DroneList)
{
if (d.Azimuth >= 360) d.Azimuth -= 360;
var bmp = RotateImage(d.Drone, d.Azimuth);
g.FillEllipse(new SolidBrush(Color.FromArgb(50, d.RGB)), d.PosXY.X + d.Height, d.PosXY.Y + d.Height, 130, 130);
g.DrawLine(new Pen(Color.Black), new Point(d.PosXY.X + d.Drone.Width / 2, d.PosXY.Y + d.Drone.Height / 2), new Point(d.PosXY.X + d.Height + d.Drone.Width / 2, d.PosXY.Y + d.Height + d.Drone.Height / 2));
//g.DrawImage(bmp, new Rectangle(d.PosXY.X+32, d.PosXY.Y, 65, 130));
float x1 = 0, y1 = 0;
float x2 = 130, y2 = 0;
float x3 = 0, y3 = 130;
const float TO_RADI = MathF.PI / 180;
Quaternion tilt = new Quaternion(d.TiltXY.X, d.TiltXY.Y, 0, 0);
Quaternion rotate = Quaternion.CreateFromAxisAngle(new Vector3(0, 0, 1), d.Azimuth * TO_RADI);
tilt = tilt * rotate * rotate;
if (tilt.Y > 0)
{
x1 = (int)(Math.Sin(tilt.Y) * 130);
x3 = (int)(Math.Sin(tilt.Y) * 130);
}
else
{
x2 = (int)(Math.Cos(tilt.Y) * 130);
}
if (tilt.X > 0)
{
y1 = (int)(Math.Sin(tilt.X) * 130);
y2 = (int)(Math.Sin(tilt.X) * 130);
}
else
{
y3 = (int)(Math.Cos(tilt.X) * 130);
}
PointF ul = new PointF(d.PosXY.X + x1, d.PosXY.Y + y1); PointF ur = new PointF(d.PosXY.X + x2, d.PosXY.Y + y2);
PointF dl = new PointF(d.PosXY.X + x3, d.PosXY.Y + y3);
PointF[] dest = { ul, ur, dl };
g.DrawImage(bmp, dest);
}
}
drawCallback(MainArea);
}
public void Move(int id, Vector3 pos, Vector4 tilt)
{
const float TO_GRAD = 180 / MathF.PI;
const float TO_RADI = MathF.PI / 180;
foreach (var d in DroneList)
{
if (d.ID != id) continue;
d.PosXY.X = (int)pos.X;
d.PosXY.Y = MainArea.Height - (int)pos.Y;
d.Height = (int)pos.Z;
d.TiltXY.X = tilt.X * TO_RADI;
d.TiltXY.Y = tilt.Y * TO_RADI;
d.Azimuth = (int)tilt.Z;
break;
}
}
}
public void Move(int id, Vector3 pos, Vector4 tilt)
{
const float TO_GRAD = 180 / MathF.PI;
const float TO_RADI = MathF.PI / 180;
foreach (var d in DroneList)
{
if (d.ID != id) continue;
d.PosXY.X = (int)pos.X;
d.PosXY.Y = MainArea.Height - (int)pos.Y;
d.Height = (int)pos.Z;
d.TiltXY.X = tilt.X * TO_RADI;
d.TiltXY.Y = tilt.Y * TO_RADI;
d.Azimuth = (int)tilt.Z;
break;
}
}
}
}

View File

@ -0,0 +1,140 @@
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <thread>
#include <atomic>
#include <mutex>
#pragma comment(lib, "Ws2_32.lib")
struct DataIn
{
float AccX, AccY, AccZ;
float GyrX, GyrY, GyrZ;
float PosX, PosY, LaserRange;
} dataIn;
struct DataOut
{
float MotorUL, MotorUR, MotorDL, MotorDR;
} dataOut;
std::atomic<bool> running(true); // Флаг работы потоков
std::mutex dataMutex; // Мьютекс для синхронизации доступа к dataIn и dataOut
SOCKET ConnectToServer(const char* ip, int port)
{
WSAData wsaData;
WORD DLLVersion = MAKEWORD(2, 1);
if (WSAStartup(DLLVersion, &wsaData) != 0)
{
std::cout << "Error: WSAStartup failed\n";
return INVALID_SOCKET;
}
SOCKADDR_IN addr;
inet_pton(AF_INET, ip, &addr.sin_addr);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
SOCKET Connection = socket(AF_INET, SOCK_STREAM, 0);
if (Connection == INVALID_SOCKET)
{
std::cout << "Error: Failed to create socket\n";
WSACleanup();
return INVALID_SOCKET;
}
if (connect(Connection, (SOCKADDR*)&addr, sizeof(addr)) != 0)
{
std::cout << "Error: Failed to connect to server\n";
closesocket(Connection);
WSACleanup();
return INVALID_SOCKET;
}
return Connection;
}
void CloseConnection(SOCKET& socket)
{
if (socket != INVALID_SOCKET)
{
closesocket(socket);
WSACleanup();
socket = INVALID_SOCKET;
}
}
// Функция приема данных
void ReceiveHandler(SOCKET socket)
{
while (running)
{
DataIn tempData;
int result = recv(socket, (char*)&tempData, sizeof(tempData), 0);
if (result <= 0)
{
std::cout << "Error: Connection lost (recv failed)\n";
running = false;
break;
}
// Потокобезопасное обновление данных
std::lock_guard<std::mutex> lock(dataMutex);
dataIn = tempData;
}
}
// Функция отправки данных
void SendHandler(SOCKET socket)
{
while (running)
{
{
std::lock_guard<std::mutex> lock(dataMutex);
send(socket, (char*)&dataOut, sizeof(dataOut), 0);
}
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // Задержка для уменьшения нагрузки
}
}
int main()
{
SOCKET Connection = ConnectToServer("127.0.0.1", 1001);
if (Connection == INVALID_SOCKET)
{
return 1;
}
dataOut.MotorUL = 10;
dataOut.MotorUR = 10;
dataOut.MotorDL = 10;
dataOut.MotorDR = 10;
// Создание потоков
std::thread recvThread(ReceiveHandler, Connection);
std::thread sendThread(SendHandler, Connection);
for (int i = 0; i < 1000000; i++)
{
{
std::lock_guard<std::mutex> lock(dataMutex);
std::cout << "Laser Range: " << dataIn.LaserRange << std::endl;
}
std::cout << "-----------------------------------------------------------" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // Задержка вывода
}
// Завершаем работу потоков
running = false;
recvThread.join();
sendThread.join();
CloseConnection(Connection);
system("pause");
return 0;
}

View File

@ -0,0 +1,135 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>17.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{b7cc5245-b628-40e9-a9a0-a904e2bf25ea}</ProjectGuid>
<RootNamespace>TestClientConnection</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="TestClientConnection.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Исходные файлы">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Файлы заголовков">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Файлы ресурсов">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="TestClientConnection.cpp">
<Filter>Исходные файлы</Filter>
</ClCompile>
</ItemGroup>
</Project>