iOS simple controller works

This commit is contained in:
Piv
2020-05-06 21:44:42 +09:30
parent 9376bd70ed
commit 4b3b960d22
7 changed files with 90 additions and 97 deletions

View File

@@ -24,8 +24,8 @@
"repositoryURL": "https://github.com/apple/swift-nio.git",
"state": {
"branch": null,
"revision": "e876fb37410e0036b98b5361bb18e6854739572b",
"version": "2.16.0"
"revision": "40bdad80882d307abe2c0bb36cf3bd4d3e03fe04",
"version": "2.16.1"
}
},
{

View File

@@ -15,16 +15,26 @@ struct ContentView: View {
NavigationLink(destination: SimpleControllerView()){
Text("Simple Controller")
}
// TODO: Change these when other functionality is implemented
NavigationLink(destination: SimpleControllerView()){
Text("Gamepad controller")
}
NavigationLink(destination: SimpleControllerView()){
Text("SLAM Controller")
}
NavigationLink(destination: SimpleControllerView()){
Text("Tracking Controller")
Text("Lidar Tracking Controller")
}
NavigationLink(destination: SimpleControllerView()){
Text("Mono Camera Tracking Controller")
}
NavigationLink(destination: SimpleControllerView()){
Text("Hybrid Lidar Camera Tracking Controller")
}
}
.navigationBarTitle(Text("Controllers"))
}
.navigationViewStyle(StackNavigationViewStyle())
}
}

View File

@@ -15,42 +15,32 @@ class PiLoader: ObservableObject {
// Find a cleaner way to handle these properties
@Published var throttle: Float = 0.5
@Published var steering: Float = 0.5
let port: Int = 50051
var stopped = false
func makeClient(port: Int, group: EventLoopGroup) -> MotorControl_CarControlClient {
let channel = ClientConnection.insecure(group: group)
// TODO: Pass the host in based on the settings.
.connect(host: "10.0.0.55", port: port)
return MotorControl_CarControlClient(channel: channel)
}
func startUpdating() {
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
try? group.syncShutdownGracefully()
}
let client = makeClient(port: self.port, group: group)
let options = CallOptions(timeout: .seconds(rounding: 10))
let call = client.stream_vehicle_2d(callOptions: options)
call.response.whenFailure { error in
print("RecordRoute Failed: \(error)")
self.stop()
}
call.status.whenComplete { _ in
print("Finished RecordRoute")
self.stop()
}
call.response.whenSuccess { summary in
print("Finished")
self.stop()
}
DispatchQueue.global(qos: .userInteractive).async{
func startUpdating(forPort port: Int, atHost host: String) {
DispatchQueue.global(qos: .background).async{
let group = PlatformSupport.makeEventLoopGroup(loopCount: 1)
defer {
try? group.syncShutdownGracefully()
}
let client = makeClient(port: port, host: host, group: group)
let options = CallOptions(timeout: .seconds(rounding: 10))
let call = client.stream_vehicle_2d(callOptions: options)
call.response.whenFailure { error in
print("Failed: \(error)")
self.stop()
}
call.status.whenComplete { _ in
print("Finished")
self.stop()
}
call.response.whenSuccess { summary in
print("Finished")
self.stop()
}
// Running in background. Do the update thread stuff.
while (!self.stopped){
call.sendMessage(self.createProto(), promise: nil)
@@ -74,3 +64,12 @@ class PiLoader: ObservableObject {
}
}
}
func makeClient(port: Int, host: String, group: EventLoopGroup) -> MotorControl_CarControlClient {
let channel = ClientConnection.insecure(group: group)
// TODO: Pass the host in based on the settings.
.connect(host: host, port: port)
return MotorControl_CarControlClient(channel: channel)
}

View File

@@ -8,20 +8,18 @@
import Foundation
struct UserKeys{
static let host = "host"
static let port = "port"
}
final class ServerData: ObservableObject{
// TODO: Find a way to save/represent this stuff in iOS settings/preferences (user can access via settings app).
// Then load the below values ar runtime, from settings.
// Ideally want to be able to open this settings page from within the app as well.
@Published var port: Int = 50051
@Published var grpcPort: Int = 50050
@Published var host: String = "10.0.0.53"
@Published var host: String = UserDefaults.standard.string(forKey: UserKeys.host) ?? "10.0.0.53"
@Published var grpcPort: Int = UserDefaults.standard.integer(forKey: UserKeys.port)
func load(){
// Load the server values from settings, if they had been
// previously saved.
// Load the server values from settings, if they had been previously saved.
}
func save(){

View File

@@ -6,23 +6,15 @@
<string>Root</string>
<key>PreferenceSpecifiers</key>
<array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict>
<key>Type</key>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Name</string>
<string>Host</string>
<key>Key</key>
<string>name_preference</string>
<string>host</string>
<key>DefaultValue</key>
<string></string>
<key>IsSecure</key>
<false/>
<string>10.0.0.53</string>
<key>KeyboardType</key>
<string>Alphabet</string>
<key>AutocapitalizationType</key>
@@ -32,29 +24,17 @@
</dict>
<dict>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
<string>PSTextFieldSpecifier</string>
<key>Title</key>
<string>Enabled</string>
<string>Port</string>
<key>Key</key>
<string>enabled_preference</string>
<string>port</string>
<key>DefaultValue</key>
<true/>
</dict>
<dict>
<key>Type</key>
<string>PSSliderSpecifier</string>
<key>Key</key>
<string>slider_preference</string>
<key>DefaultValue</key>
<real>0.5</real>
<key>MinimumValue</key>
<integer>0</integer>
<key>MaximumValue</key>
<integer>1</integer>
<key>MinimumValueImage</key>
<string></string>
<key>MaximumValueImage</key>
<string></string>
<string>50051</string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key>
<string>NumberPad</string>
</dict>
</array>
</dict>

View File

@@ -10,27 +10,33 @@ import SwiftUI
struct SimpleControllerView: View {
@EnvironmentObject var server: ServerData
// Need lazy so that we can initialise with local properties.
@ObservedObject var grpcController: PiLoader = PiLoader()
var body: some View {
HStack{
Slider(value: $grpcController.throttle, in: 0...1){_ in
self.grpcController.throttle = 0.5
VStack (alignment: .trailing, spacing: 0){
Spacer()
HStack{
// Move this up a bit, due to being rotated.
Slider(value: self.$grpcController.throttle, in: 0...1){_ in
self.grpcController.throttle = 0.5
}
.offset(x: 200)
.frame(width: 300)
.rotationEffect(.degrees(270))
Spacer()
Slider(value: self.$grpcController.steering, in: 0...1){_ in
self.grpcController.steering = 0.5
}
.frame(width:300)
.offset(x: -50, y: -200)
.padding()
}
.rotationEffect(.degrees(270))
Slider(value: $grpcController.steering, in: 0...1){_ in
self.grpcController.steering = 0.5
.onAppear(){
self.grpcController.startUpdating(forPort: self.server.grpcPort, atHost: self.server.host)
}
.onDisappear(){
self.grpcController.stop()
}
}
.onAppear(){
self.grpcController.startUpdating()
}
.onDisappear(){
// Stop the gRPC updater.
self.grpcController.stop()
}
}
}