From 4b3b960d222ac82033a1891e3a2a6b959d38e175 Mon Sep 17 00:00:00 2001 From: Piv <18462828+Piv200@users.noreply.github.com> Date: Wed, 6 May 2020 21:44:42 +0930 Subject: [PATCH] iOS simple controller works --- .vscode/launch.json | 4 +- .../xcshareddata/swiftpm/Package.resolved | 4 +- .../CarController/ContentView.swift | 14 +++- CarControlleriOS/CarController/PiLoader.swift | 67 +++++++++---------- .../CarController/ServerData.swift | 18 +++-- .../CarController/Settings.bundle/Root.plist | 42 +++--------- .../CarController/SimpleControllerView.swift | 38 ++++++----- 7 files changed, 90 insertions(+), 97 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index ffe4adf..7c79804 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -10,9 +10,9 @@ "request": "launch", "module": "car", "env": { - "CAR_LIDAR": "LIDAR_RPLIDAR", + "CAR_LIDAR": "LIDAR_MOCK", "CAR_VEHICLE": "CAR_MOCK", - "LIDAR_DEVICE": "/dev/tty.usbserial-0001" + // "LIDAR_DEVICE": "/dev/tty.usbserial-0001" } }, { diff --git a/CarControlleriOS/CarController.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/CarControlleriOS/CarController.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index c90f41d..12fe0a3 100644 --- a/CarControlleriOS/CarController.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/CarControlleriOS/CarController.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -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" } }, { diff --git a/CarControlleriOS/CarController/ContentView.swift b/CarControlleriOS/CarController/ContentView.swift index 5f8de90..7044469 100644 --- a/CarControlleriOS/CarController/ContentView.swift +++ b/CarControlleriOS/CarController/ContentView.swift @@ -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()) } } diff --git a/CarControlleriOS/CarController/PiLoader.swift b/CarControlleriOS/CarController/PiLoader.swift index 3e007dd..1c42a58 100644 --- a/CarControlleriOS/CarController/PiLoader.swift +++ b/CarControlleriOS/CarController/PiLoader.swift @@ -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) +} diff --git a/CarControlleriOS/CarController/ServerData.swift b/CarControlleriOS/CarController/ServerData.swift index e23830e..c049235 100644 --- a/CarControlleriOS/CarController/ServerData.swift +++ b/CarControlleriOS/CarController/ServerData.swift @@ -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(){ diff --git a/CarControlleriOS/CarController/Settings.bundle/Root.plist b/CarControlleriOS/CarController/Settings.bundle/Root.plist index b1b6fea..1261bd8 100644 --- a/CarControlleriOS/CarController/Settings.bundle/Root.plist +++ b/CarControlleriOS/CarController/Settings.bundle/Root.plist @@ -6,23 +6,15 @@ Root PreferenceSpecifiers - - Type - PSGroupSpecifier - Title - Group - Type PSTextFieldSpecifier Title - Name + Host Key - name_preference + host DefaultValue - - IsSecure - + 10.0.0.53 KeyboardType Alphabet AutocapitalizationType @@ -32,29 +24,17 @@ Type - PSToggleSwitchSpecifier + PSTextFieldSpecifier Title - Enabled + Port Key - enabled_preference + port DefaultValue - - - - Type - PSSliderSpecifier - Key - slider_preference - DefaultValue - 0.5 - MinimumValue - 0 - MaximumValue - 1 - MinimumValueImage - - MaximumValueImage - + 50051 + IsSecure + + KeyboardType + NumberPad diff --git a/CarControlleriOS/CarController/SimpleControllerView.swift b/CarControlleriOS/CarController/SimpleControllerView.swift index ee5188f..fa866ec 100644 --- a/CarControlleriOS/CarController/SimpleControllerView.swift +++ b/CarControlleriOS/CarController/SimpleControllerView.swift @@ -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() } } }