初始化提交
This commit is contained in:
commit
7b6eec1d2a
15
.gitignore
vendored
Normal file
15
.gitignore
vendored
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Binaries
|
||||||
|
DerivedDataCache
|
||||||
|
Intermediate
|
||||||
|
Saved
|
||||||
|
Build
|
||||||
|
.vscode
|
||||||
|
.vs
|
||||||
|
*.VC.db
|
||||||
|
*.opensdf
|
||||||
|
*.opendb
|
||||||
|
*.sdf
|
||||||
|
*.sln
|
||||||
|
*.suo
|
||||||
|
*.xcodeproj
|
||||||
|
*.xcworkspace
|
0
Config/DefaultEditor.ini
Normal file
0
Config/DefaultEditor.ini
Normal file
24
Config/DefaultEngine.ini
Normal file
24
Config/DefaultEngine.ini
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
|
||||||
|
[/Script/EngineSettings.GameMapsSettings]
|
||||||
|
GameDefaultMap=/Game/Level.Level
|
||||||
|
EditorStartupMap=/Game/Level.Level
|
||||||
|
GlobalDefaultGameMode=/Game/BP_RaspberryVehicleGameMode.BP_RaspberryVehicleGameMode_C
|
||||||
|
|
||||||
|
[/Script/HardwareTargeting.HardwareTargetingSettings]
|
||||||
|
TargetedHardwareClass=Desktop
|
||||||
|
AppliedTargetedHardwareClass=Desktop
|
||||||
|
DefaultGraphicsPerformance=Maximum
|
||||||
|
AppliedDefaultGraphicsPerformance=Maximum
|
||||||
|
|
||||||
|
[/Script/Engine.Engine]
|
||||||
|
+ActiveGameNameRedirects=(OldGameName="TP_Blank",NewGameName="/Script/RaspberryVehicle")
|
||||||
|
+ActiveGameNameRedirects=(OldGameName="/Script/TP_Blank",NewGameName="/Script/RaspberryVehicle")
|
||||||
|
+ActiveClassRedirects=(OldClassName="TP_BlankGameModeBase",NewClassName="RaspberryVehicleGameModeBase")
|
||||||
|
|
||||||
|
[/Script/AndroidRuntimeSettings.AndroidRuntimeSettings]
|
||||||
|
bPackageDataInsideApk=True
|
||||||
|
|
||||||
|
[/Script/Engine.RendererSettings]
|
||||||
|
r.DefaultFeature.AntiAliasing=0
|
||||||
|
|
3
Config/DefaultGame.ini
Normal file
3
Config/DefaultGame.ini
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
|
||||||
|
[/Script/EngineSettings.GeneralProjectSettings]
|
||||||
|
ProjectID=ECA46B7040CB59E1C5052F9417760C22
|
5
Config/DefaultInput.ini
Normal file
5
Config/DefaultInput.ini
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
[/Script/Engine.InputSettings]
|
||||||
|
DefaultTouchInterface=None
|
||||||
|
|
BIN
Content/BP_RaspberryVehicleGameMode.uasset
Normal file
BIN
Content/BP_RaspberryVehicleGameMode.uasset
Normal file
Binary file not shown.
BIN
Content/Level.umap
Normal file
BIN
Content/Level.umap
Normal file
Binary file not shown.
BIN
Content/Level_BuiltData.uasset
Normal file
BIN
Content/Level_BuiltData.uasset
Normal file
Binary file not shown.
BIN
Content/UMG.uasset
Normal file
BIN
Content/UMG.uasset
Normal file
Binary file not shown.
12
README.md
Normal file
12
README.md
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
### RaspberryVehicle
|
||||||
|
|
||||||
|
> 这是 2021年山大未来科学营(夏季)- 人工智能与发明创造未来科学营 的作业
|
||||||
|
|
||||||
|
RaspberryVehicle.py - 树莓派车入口
|
||||||
|
RaspberryVehicle.uproject - 控制端入口
|
||||||
|
|
||||||
|
基于树莓派的简单网络遥控车实现方案。
|
||||||
|
支持传感器数据上传,摄像头图像实时上传,远程操作。
|
||||||
|
网络协议基于 UDP ,车作为服务端,控制端作为客户端接入。
|
||||||
|
客户端基于 Unreal Engine 4 ,其中控制端在 Windows 10 x64 和 安卓 平台上测试通过。
|
||||||
|
[查看更多](https://www.myredstone.top/archives/2563)
|
319
RaspberryVehicle.py
Normal file
319
RaspberryVehicle.py
Normal file
@ -0,0 +1,319 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import re
|
||||||
|
import cv2
|
||||||
|
import time
|
||||||
|
import struct
|
||||||
|
import socket
|
||||||
|
import _thread
|
||||||
|
import threading
|
||||||
|
import RPi.GPIO as GPIO
|
||||||
|
|
||||||
|
stop = False
|
||||||
|
|
||||||
|
interval = 0.1
|
||||||
|
|
||||||
|
udp_addr = ("192.168.1.1", 6000)
|
||||||
|
|
||||||
|
GPIO.setmode(GPIO.BCM)
|
||||||
|
|
||||||
|
speedl_pin = 18
|
||||||
|
speedr_pin = 17
|
||||||
|
|
||||||
|
GPIO.setup(speedl_pin, GPIO.IN)
|
||||||
|
GPIO.setup(speedr_pin, GPIO.IN)
|
||||||
|
|
||||||
|
speed_mutex = threading.Lock()
|
||||||
|
speedl_count = 0
|
||||||
|
speedr_count = 0
|
||||||
|
|
||||||
|
def speedl_callback(pin):
|
||||||
|
|
||||||
|
global speedl_count
|
||||||
|
global speed_mutex
|
||||||
|
|
||||||
|
speed_mutex.acquire()
|
||||||
|
speedl_count = speedl_count + 1
|
||||||
|
speed_mutex.release()
|
||||||
|
|
||||||
|
def speedr_callback(pin):
|
||||||
|
|
||||||
|
global speedr_count
|
||||||
|
global speed_mutex
|
||||||
|
|
||||||
|
speed_mutex.acquire()
|
||||||
|
speedr_count = speedr_count + 1
|
||||||
|
speed_mutex.release()
|
||||||
|
|
||||||
|
GPIO.add_event_detect(speedl_pin, GPIO.RISING, callback = speedl_callback)
|
||||||
|
GPIO.add_event_detect(speedr_pin, GPIO.RISING, callback = speedr_callback)
|
||||||
|
|
||||||
|
ultrasound_tri_pin = 13
|
||||||
|
ultrasound_ech_pin = 16
|
||||||
|
|
||||||
|
GPIO.setup(ultrasound_tri_pin, GPIO.OUT)
|
||||||
|
GPIO.setup(ultrasound_ech_pin, GPIO.IN)
|
||||||
|
|
||||||
|
ultrasound_distance = 0.0
|
||||||
|
|
||||||
|
def ultrasound_thread():
|
||||||
|
|
||||||
|
global stop
|
||||||
|
|
||||||
|
global ultrasound_tri_pin
|
||||||
|
global ultrasound_ech_pin
|
||||||
|
global ultrasound_distance
|
||||||
|
|
||||||
|
while not stop:
|
||||||
|
|
||||||
|
GPIO.output(ultrasound_tri_pin, True)
|
||||||
|
time.sleep(0.00001)
|
||||||
|
GPIO.output(ultrasound_tri_pin, False)
|
||||||
|
|
||||||
|
count = 10000
|
||||||
|
while GPIO.input(ultrasound_ech_pin) != True and count > 0:
|
||||||
|
count = count - 1
|
||||||
|
|
||||||
|
start = time.time()
|
||||||
|
|
||||||
|
count = 10000
|
||||||
|
while GPIO.input(ultrasound_ech_pin) != False and count > 0:
|
||||||
|
count = count - 1
|
||||||
|
|
||||||
|
finish = time.time()
|
||||||
|
|
||||||
|
pulse_len = finish - start
|
||||||
|
ultrasound_distance = pulse_len / 0.000058
|
||||||
|
|
||||||
|
time.sleep(interval * 0.01)
|
||||||
|
|
||||||
|
motor_mutex = threading.Lock()
|
||||||
|
motor_pins = [21, 26, 20, 19]
|
||||||
|
motor_pwms = []
|
||||||
|
|
||||||
|
GPIO.setup(motor_pins, GPIO.OUT)
|
||||||
|
|
||||||
|
for motor_index in range(0, 4):
|
||||||
|
|
||||||
|
motor_pwms.append(GPIO.PWM(motor_pins[motor_index], 500))
|
||||||
|
motor_pwms[motor_index].start(0)
|
||||||
|
|
||||||
|
motor_mode = 0
|
||||||
|
motor_time = 0
|
||||||
|
motor_speed = 0
|
||||||
|
|
||||||
|
def motor_thread():
|
||||||
|
|
||||||
|
global stop
|
||||||
|
|
||||||
|
global motor_mode
|
||||||
|
global motor_time
|
||||||
|
global motor_speed
|
||||||
|
global motor_mutex
|
||||||
|
|
||||||
|
while not stop:
|
||||||
|
|
||||||
|
motor_mutex.acquire()
|
||||||
|
|
||||||
|
if motor_time < time.time():
|
||||||
|
|
||||||
|
motor_pwms[0].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[1].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[2].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[3].ChangeDutyCycle(0)
|
||||||
|
|
||||||
|
elif motor_mode == 0:
|
||||||
|
|
||||||
|
motor_pwms[0].ChangeDutyCycle(motor_speed)
|
||||||
|
motor_pwms[1].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[2].ChangeDutyCycle(motor_speed)
|
||||||
|
motor_pwms[3].ChangeDutyCycle(0)
|
||||||
|
|
||||||
|
elif motor_mode == 1:
|
||||||
|
|
||||||
|
motor_pwms[0].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[1].ChangeDutyCycle(motor_speed)
|
||||||
|
motor_pwms[2].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[3].ChangeDutyCycle(motor_speed)
|
||||||
|
|
||||||
|
elif motor_mode == 2:
|
||||||
|
|
||||||
|
motor_pwms[0].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[1].ChangeDutyCycle(motor_speed * 0.75)
|
||||||
|
motor_pwms[2].ChangeDutyCycle(motor_speed * 0.75)
|
||||||
|
motor_pwms[3].ChangeDutyCycle(0)
|
||||||
|
|
||||||
|
elif motor_mode == 3:
|
||||||
|
|
||||||
|
motor_pwms[0].ChangeDutyCycle(motor_speed * 0.75)
|
||||||
|
motor_pwms[1].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[2].ChangeDutyCycle(0)
|
||||||
|
motor_pwms[3].ChangeDutyCycle(motor_speed * 0.75)
|
||||||
|
|
||||||
|
elif motor_mode == 4:
|
||||||
|
|
||||||
|
motor_pwms[0].ChangeDutyCycle(motor_speed)
|
||||||
|
motor_pwms[1].ChangeDutyCycle(motor_speed)
|
||||||
|
motor_pwms[2].ChangeDutyCycle(motor_speed)
|
||||||
|
motor_pwms[3].ChangeDutyCycle(motor_speed)
|
||||||
|
|
||||||
|
motor_mutex.release()
|
||||||
|
|
||||||
|
time.sleep(interval * 0.01)
|
||||||
|
|
||||||
|
|
||||||
|
def cap_thread():
|
||||||
|
|
||||||
|
global stop
|
||||||
|
|
||||||
|
global udp_addr
|
||||||
|
|
||||||
|
cap = cv2.VideoCapture(0)
|
||||||
|
cap.set(3, 256)
|
||||||
|
cap.set(4, 256)
|
||||||
|
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
|
||||||
|
if cap == None: return
|
||||||
|
|
||||||
|
while not stop:
|
||||||
|
|
||||||
|
for chunk_index in range(0, 256):
|
||||||
|
|
||||||
|
if chunk_index % 32 == 0:
|
||||||
|
|
||||||
|
ret, frame = cap.read()
|
||||||
|
if ret == False: return
|
||||||
|
|
||||||
|
chunk_bytes = struct.pack("!H", chunk_index) + frame.tobytes()[chunk_index * 768 : chunk_index * 768 + 768]
|
||||||
|
|
||||||
|
sock.sendto(chunk_bytes, udp_addr)
|
||||||
|
|
||||||
|
if stop: return
|
||||||
|
|
||||||
|
cap.release()
|
||||||
|
|
||||||
|
clp_pin = 23
|
||||||
|
near_pin = 27
|
||||||
|
is_pins = [22, 24, 25, 12, 5]
|
||||||
|
|
||||||
|
GPIO.setup(clp_pin, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
|
||||||
|
GPIO.setup(near_pin, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
|
||||||
|
GPIO.setup(is_pins, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
|
||||||
|
|
||||||
|
def udp_thread():
|
||||||
|
|
||||||
|
global stop
|
||||||
|
|
||||||
|
global udp_addr
|
||||||
|
|
||||||
|
global speedl_count
|
||||||
|
global speedr_count
|
||||||
|
global speed_mutex
|
||||||
|
|
||||||
|
global motor_mode
|
||||||
|
global motor_time
|
||||||
|
global motor_speed
|
||||||
|
global motor_mutex
|
||||||
|
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
sock.bind(("0.0.0.0", 6000))
|
||||||
|
sock.setblocking(False)
|
||||||
|
|
||||||
|
while not stop:
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
(data, source) = sock.recvfrom(1024)
|
||||||
|
|
||||||
|
if len(data) == 8:
|
||||||
|
|
||||||
|
udp_addr = source
|
||||||
|
|
||||||
|
order, param = struct.unpack("!ii", data)
|
||||||
|
|
||||||
|
if order >= 0 and order < 5:
|
||||||
|
|
||||||
|
motor_mutex.acquire()
|
||||||
|
|
||||||
|
motor_mode = order
|
||||||
|
motor_speed = param
|
||||||
|
|
||||||
|
if motor_speed < 0.0:
|
||||||
|
|
||||||
|
motor_speed = 0.0
|
||||||
|
|
||||||
|
elif motor_speed > 100.0:
|
||||||
|
|
||||||
|
motor_speed = 100.0
|
||||||
|
|
||||||
|
motor_time = time.time() + 0.13
|
||||||
|
|
||||||
|
motor_mutex.release()
|
||||||
|
|
||||||
|
except socket.error:
|
||||||
|
|
||||||
|
motor_mode = 0
|
||||||
|
|
||||||
|
data = bytes()
|
||||||
|
|
||||||
|
clp_state = GPIO.input(clp_pin) == True
|
||||||
|
near_state = GPIO.input(near_pin) == True
|
||||||
|
|
||||||
|
data = data + struct.pack("!??", clp_state, near_state)
|
||||||
|
|
||||||
|
for is_pin in is_pins:
|
||||||
|
|
||||||
|
is_state = GPIO.input(is_pin) == True
|
||||||
|
|
||||||
|
data = data + struct.pack("!?", is_state)
|
||||||
|
|
||||||
|
speed_mutex.acquire()
|
||||||
|
|
||||||
|
data = data + struct.pack("!BB", speedl_count, speedr_count)
|
||||||
|
|
||||||
|
speedl_count = 0
|
||||||
|
speedr_count = 0
|
||||||
|
|
||||||
|
speed_mutex.release()
|
||||||
|
|
||||||
|
data = data + struct.pack("!f", ultrasound_distance)
|
||||||
|
|
||||||
|
sock.sendto(data, udp_addr)
|
||||||
|
|
||||||
|
time.sleep(interval)
|
||||||
|
|
||||||
|
sock.close()
|
||||||
|
|
||||||
|
threads = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
threads.append(threading.Thread(target = ultrasound_thread, args = ()))
|
||||||
|
threads.append(threading.Thread(target = motor_thread, args = ()))
|
||||||
|
threads.append(threading.Thread(target = cap_thread, args = ()))
|
||||||
|
threads.append(threading.Thread(target = udp_thread, args = ()))
|
||||||
|
|
||||||
|
for thread in threads: thread.start()
|
||||||
|
|
||||||
|
while True:
|
||||||
|
|
||||||
|
time.sleep(interval)
|
||||||
|
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
|
||||||
|
print("\nKeyboardInterrupt")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
|
||||||
|
stop = True
|
||||||
|
|
||||||
|
for thread in threads:
|
||||||
|
|
||||||
|
if thread.isAlive():
|
||||||
|
|
||||||
|
thread.join()
|
||||||
|
|
||||||
|
GPIO.cleanup()
|
||||||
|
|
||||||
|
print("Exit")
|
13
RaspberryVehicle.uproject
Normal file
13
RaspberryVehicle.uproject
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"FileVersion": 3,
|
||||||
|
"EngineAssociation": "4.26",
|
||||||
|
"Category": "",
|
||||||
|
"Description": "",
|
||||||
|
"Modules": [
|
||||||
|
{
|
||||||
|
"Name": "RaspberryVehicle",
|
||||||
|
"Type": "Runtime",
|
||||||
|
"LoadingPhase": "Default"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
14
Source/RaspberryVehicle.Target.cs
Normal file
14
Source/RaspberryVehicle.Target.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
using UnrealBuildTool;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class RaspberryVehicleTarget : TargetRules
|
||||||
|
{
|
||||||
|
public RaspberryVehicleTarget( TargetInfo Target) : base(Target)
|
||||||
|
{
|
||||||
|
Type = TargetType.Game;
|
||||||
|
DefaultBuildSettings = BuildSettingsVersion.V2;
|
||||||
|
ExtraModuleNames.AddRange( new string[] { "RaspberryVehicle" } );
|
||||||
|
}
|
||||||
|
}
|
31
Source/RaspberryVehicle/RaspberryVehicle.Build.cs
Normal file
31
Source/RaspberryVehicle/RaspberryVehicle.Build.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
using UnrealBuildTool;
|
||||||
|
|
||||||
|
public class RaspberryVehicle : ModuleRules
|
||||||
|
{
|
||||||
|
public RaspberryVehicle(ReadOnlyTargetRules Target) : base(Target)
|
||||||
|
{
|
||||||
|
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
|
||||||
|
|
||||||
|
PublicDependencyModuleNames.AddRange(
|
||||||
|
new string[]
|
||||||
|
{
|
||||||
|
"Core",
|
||||||
|
"Engine",
|
||||||
|
"InputCore" ,
|
||||||
|
"CoreUObject",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
PrivateDependencyModuleNames.AddRange(
|
||||||
|
new string[]
|
||||||
|
{
|
||||||
|
"RHI",
|
||||||
|
"Sockets",
|
||||||
|
"Networking",
|
||||||
|
"RenderCore",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
6
Source/RaspberryVehicle/RaspberryVehicle.cpp
Normal file
6
Source/RaspberryVehicle/RaspberryVehicle.cpp
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
#include "RaspberryVehicle.h"
|
||||||
|
#include "Modules/ModuleManager.h"
|
||||||
|
|
||||||
|
IMPLEMENT_PRIMARY_GAME_MODULE( FDefaultGameModuleImpl, RaspberryVehicle, "RaspberryVehicle" );
|
6
Source/RaspberryVehicle/RaspberryVehicle.h
Normal file
6
Source/RaspberryVehicle/RaspberryVehicle.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
|
139
Source/RaspberryVehicle/RaspberryVehicleGameMode.cpp
Normal file
139
Source/RaspberryVehicle/RaspberryVehicleGameMode.cpp
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
#include "RaspberryVehicleGameMode.h"
|
||||||
|
|
||||||
|
#include "Sockets.h"
|
||||||
|
#include "Networking.h"
|
||||||
|
#include "Misc/Timespan.h"
|
||||||
|
#include "SocketSubsystem.h"
|
||||||
|
#include "Engine/Texture2DDynamic.h"
|
||||||
|
|
||||||
|
ARaspberryVehicleGameMode::ARaspberryVehicleGameMode(const FObjectInitializer& ObjectInitializer)
|
||||||
|
{
|
||||||
|
PrimaryActorTick.bCanEverTick = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARaspberryVehicleGameMode::BeginPlay()
|
||||||
|
{
|
||||||
|
Super::BeginPlay();
|
||||||
|
|
||||||
|
SocketSubsystem = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM);
|
||||||
|
|
||||||
|
UDPSocket = SocketSubsystem->CreateSocket(NAME_DGram, TEXT("Raspberry Socket"), FNetworkProtocolTypes::IPv4);
|
||||||
|
|
||||||
|
UDPBuffer.SetNumUninitialized(1024);
|
||||||
|
|
||||||
|
CameraBuffer.Init(255, 256 * 256 * 4);
|
||||||
|
|
||||||
|
UDPLastTime = FDateTime(0);
|
||||||
|
UDPSendTime = FDateTime(0);
|
||||||
|
|
||||||
|
CameraTexture = UTexture2D::CreateTransient(256, 256);
|
||||||
|
void* Pixels = CameraTexture->PlatformData->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
|
||||||
|
FMemory::Memcpy(Pixels, CameraBuffer.GetData(), 256 * 256 * 4);
|
||||||
|
CameraTexture->PlatformData->Mips[0].BulkData.Unlock();
|
||||||
|
CameraTexture->UpdateResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARaspberryVehicleGameMode::Tick(float DeltaSeconds)
|
||||||
|
{
|
||||||
|
Super::Tick(DeltaSeconds);
|
||||||
|
|
||||||
|
int32 BytesNum = 0;
|
||||||
|
TSharedRef<FInternetAddr> Addr = SocketSubsystem->CreateInternetAddr();
|
||||||
|
|
||||||
|
bool bIsValid;
|
||||||
|
Addr->SetIp(TEXT("192.168.1.1"), bIsValid);
|
||||||
|
Addr->SetIp(*IP, bIsValid);
|
||||||
|
Addr->SetPort(6000);
|
||||||
|
|
||||||
|
if ((FDateTime::Now() - UDPSendTime) > FTimespan::FromSeconds(0.1))
|
||||||
|
{
|
||||||
|
uint8* MotorModeBuffer = (uint8*)&MotorMode;
|
||||||
|
|
||||||
|
UDPBuffer[0] = MotorModeBuffer[3];
|
||||||
|
UDPBuffer[1] = MotorModeBuffer[2];
|
||||||
|
UDPBuffer[2] = MotorModeBuffer[1];
|
||||||
|
UDPBuffer[3] = MotorModeBuffer[0];
|
||||||
|
|
||||||
|
uint8* MotorSpeedBuffer = (uint8*)&MotorSpeed;
|
||||||
|
|
||||||
|
UDPBuffer[4] = MotorSpeedBuffer[3];
|
||||||
|
UDPBuffer[5] = MotorSpeedBuffer[2];
|
||||||
|
UDPBuffer[6] = MotorSpeedBuffer[1];
|
||||||
|
UDPBuffer[7] = MotorSpeedBuffer[0];
|
||||||
|
|
||||||
|
UDPSocket->SendTo(UDPBuffer.GetData(), 8, BytesNum, *Addr);
|
||||||
|
|
||||||
|
UDPSendTime = FDateTime::Now();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 PendingDataSize;
|
||||||
|
while(UDPSocket->HasPendingData(PendingDataSize))
|
||||||
|
{
|
||||||
|
UDPSocket->RecvFrom(UDPBuffer.GetData(), UDPBuffer.Num(), BytesNum, *Addr);
|
||||||
|
|
||||||
|
if (BytesNum == 13)
|
||||||
|
{
|
||||||
|
UDPLastTime = FDateTime::Now();
|
||||||
|
|
||||||
|
bCLP = (bool)UDPBuffer[0];
|
||||||
|
bNear = (bool)UDPBuffer[1];
|
||||||
|
|
||||||
|
bIS1 = (bool)UDPBuffer[2];
|
||||||
|
bIS2 = (bool)UDPBuffer[3];
|
||||||
|
bIS3 = (bool)UDPBuffer[4];
|
||||||
|
bIS4 = (bool)UDPBuffer[5];
|
||||||
|
bIS5 = (bool)UDPBuffer[6];
|
||||||
|
|
||||||
|
SpeedL = UDPBuffer[7] * 0.5;
|
||||||
|
SpeedR = UDPBuffer[8] * 0.5;
|
||||||
|
|
||||||
|
uint8 DistanceBuffer[4];
|
||||||
|
|
||||||
|
DistanceBuffer[3] = UDPBuffer[9];
|
||||||
|
DistanceBuffer[2] = UDPBuffer[10];
|
||||||
|
DistanceBuffer[1] = UDPBuffer[11];
|
||||||
|
DistanceBuffer[0] = UDPBuffer[12];
|
||||||
|
|
||||||
|
FMemory::Memcpy(&Distance, DistanceBuffer, sizeof Distance);
|
||||||
|
}
|
||||||
|
else if (BytesNum == 770)
|
||||||
|
{
|
||||||
|
int32 ChunkIndex;
|
||||||
|
uint8* ChunkIndexBuffer = (uint8*)&ChunkIndex;
|
||||||
|
|
||||||
|
ChunkIndexBuffer[0] = UDPBuffer[1];
|
||||||
|
ChunkIndexBuffer[1] = UDPBuffer[0];
|
||||||
|
ChunkIndexBuffer[2] = 0;
|
||||||
|
ChunkIndexBuffer[3] = 0;
|
||||||
|
|
||||||
|
uint8* Src = &UDPBuffer[2];
|
||||||
|
|
||||||
|
for (int32 PixelIndex = 0; PixelIndex < 256; ++PixelIndex)
|
||||||
|
{
|
||||||
|
CameraBuffer[(ChunkIndex * 256 + PixelIndex) * 4 + 0] = Src[PixelIndex * 3 + 0];
|
||||||
|
CameraBuffer[(ChunkIndex * 256 + PixelIndex) * 4 + 1] = Src[PixelIndex * 3 + 1];
|
||||||
|
CameraBuffer[(ChunkIndex * 256 + PixelIndex) * 4 + 2] = Src[PixelIndex * 3 + 2];
|
||||||
|
CameraBuffer[(ChunkIndex * 256 + PixelIndex) * 4 + 3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void* Buffer = CameraBuffer.GetData();
|
||||||
|
FRHITexture2D* RHICameraTexture = CameraTexture->Resource->GetTexture2DRHI();
|
||||||
|
ENQUEUE_RENDER_COMMAND(RaspberryCameraUpdate)(
|
||||||
|
[RHICameraTexture, Buffer](FRHICommandListImmediate& RHICmdList)
|
||||||
|
{
|
||||||
|
uint32 Stride = 0;
|
||||||
|
void* Pixels = RHILockTexture2D(RHICameraTexture, 0, RLM_WriteOnly, Stride, false);
|
||||||
|
FMemory::Memcpy(Pixels, Buffer, 256 * 256 * 4);
|
||||||
|
RHIUnlockTexture2D(RHICameraTexture, 0, false);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ARaspberryVehicleGameMode::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
||||||
|
{
|
||||||
|
SocketSubsystem->DestroySocket(UDPSocket);
|
||||||
|
|
||||||
|
Super::EndPlay(EndPlayReason);
|
||||||
|
}
|
82
Source/RaspberryVehicle/RaspberryVehicleGameMode.h
Normal file
82
Source/RaspberryVehicle/RaspberryVehicleGameMode.h
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CoreMinimal.h"
|
||||||
|
#include "Misc/DateTime.h"
|
||||||
|
#include "GameFramework/GameModeBase.h"
|
||||||
|
#include "RaspberryVehicleGameMode.generated.h"
|
||||||
|
|
||||||
|
class FSocket;
|
||||||
|
class UTexture2D;
|
||||||
|
class ISocketSubsystem;
|
||||||
|
|
||||||
|
UCLASS(Blueprintable)
|
||||||
|
class ARaspberryVehicleGameMode : public AGameModeBase
|
||||||
|
{
|
||||||
|
GENERATED_BODY()
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ARaspberryVehicleGameMode(const FObjectInitializer& ObjectInitializer);
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite)
|
||||||
|
FString IP;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
FDateTime UDPLastTime;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
bool bCLP;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
bool bNear;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
bool bIS1;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
bool bIS2;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
bool bIS3;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
bool bIS4;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
bool bIS5;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
float SpeedL = 0.0f;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
float SpeedR = 0.0f;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadOnly)
|
||||||
|
float Distance = 0.0f;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite)
|
||||||
|
int32 MotorMode = -1;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite)
|
||||||
|
int32 MotorSpeed = 100;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite)
|
||||||
|
UTexture2D* CameraTexture;
|
||||||
|
|
||||||
|
ISocketSubsystem* SocketSubsystem;
|
||||||
|
|
||||||
|
FSocket* UDPSocket;
|
||||||
|
|
||||||
|
TArray<uint8> UDPBuffer;
|
||||||
|
|
||||||
|
TArray<uint8> CameraBuffer;
|
||||||
|
|
||||||
|
FDateTime UDPSendTime;
|
||||||
|
|
||||||
|
//~ Begin AActor Interface.
|
||||||
|
virtual void BeginPlay() override;
|
||||||
|
virtual void Tick(float DeltaSeconds) override;
|
||||||
|
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override;
|
||||||
|
//~ End AActor Interface.
|
||||||
|
|
||||||
|
};
|
14
Source/RaspberryVehicleEditor.Target.cs
Normal file
14
Source/RaspberryVehicleEditor.Target.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright Epic Games, Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
using UnrealBuildTool;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
public class RaspberryVehicleEditorTarget : TargetRules
|
||||||
|
{
|
||||||
|
public RaspberryVehicleEditorTarget( TargetInfo Target) : base(Target)
|
||||||
|
{
|
||||||
|
Type = TargetType.Editor;
|
||||||
|
DefaultBuildSettings = BuildSettingsVersion.V2;
|
||||||
|
ExtraModuleNames.AddRange( new string[] { "RaspberryVehicle" } );
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user