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

4
.vscode/launch.json vendored
View File

@@ -10,9 +10,9 @@
"request": "launch", "request": "launch",
"module": "car", "module": "car",
"env": { "env": {
"CAR_LIDAR": "LIDAR_RPLIDAR", "CAR_LIDAR": "LIDAR_MOCK",
"CAR_VEHICLE": "CAR_MOCK", "CAR_VEHICLE": "CAR_MOCK",
"LIDAR_DEVICE": "/dev/tty.usbserial-0001" // "LIDAR_DEVICE": "/dev/tty.usbserial-0001"
} }
}, },
{ {

View File

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

View File

@@ -15,16 +15,26 @@ struct ContentView: View {
NavigationLink(destination: SimpleControllerView()){ NavigationLink(destination: SimpleControllerView()){
Text("Simple Controller") Text("Simple Controller")
} }
// TODO: Change these when other functionality is implemented // TODO: Change these when other functionality is implemented
NavigationLink(destination: SimpleControllerView()){
Text("Gamepad controller")
}
NavigationLink(destination: SimpleControllerView()){ NavigationLink(destination: SimpleControllerView()){
Text("SLAM Controller") Text("SLAM Controller")
} }
NavigationLink(destination: SimpleControllerView()){ 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,33 +15,25 @@ class PiLoader: ObservableObject {
// Find a cleaner way to handle these properties // Find a cleaner way to handle these properties
@Published var throttle: Float = 0.5 @Published var throttle: Float = 0.5
@Published var steering: Float = 0.5 @Published var steering: Float = 0.5
let port: Int = 50051
var stopped = false var stopped = false
func makeClient(port: Int, group: EventLoopGroup) -> MotorControl_CarControlClient { func startUpdating(forPort port: Int, atHost host: String) {
let channel = ClientConnection.insecure(group: group) DispatchQueue.global(qos: .background).async{
// TODO: Pass the host in based on the settings. let group = PlatformSupport.makeEventLoopGroup(loopCount: 1)
.connect(host: "10.0.0.55", port: port)
return MotorControl_CarControlClient(channel: channel)
}
func startUpdating() {
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer { defer {
try? group.syncShutdownGracefully() try? group.syncShutdownGracefully()
} }
let client = makeClient(port: self.port, group: group) let client = makeClient(port: port, host: host, group: group)
let options = CallOptions(timeout: .seconds(rounding: 10)) let options = CallOptions(timeout: .seconds(rounding: 10))
let call = client.stream_vehicle_2d(callOptions: options) let call = client.stream_vehicle_2d(callOptions: options)
call.response.whenFailure { error in call.response.whenFailure { error in
print("RecordRoute Failed: \(error)") print("Failed: \(error)")
self.stop() self.stop()
} }
call.status.whenComplete { _ in call.status.whenComplete { _ in
print("Finished RecordRoute") print("Finished")
self.stop() self.stop()
} }
@@ -49,8 +41,6 @@ class PiLoader: ObservableObject {
print("Finished") print("Finished")
self.stop() self.stop()
} }
DispatchQueue.global(qos: .userInteractive).async{
// Running in background. Do the update thread stuff. // Running in background. Do the update thread stuff.
while (!self.stopped){ while (!self.stopped){
call.sendMessage(self.createProto(), promise: nil) 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 import Foundation
struct UserKeys{
static let host = "host"
static let port = "port"
}
final class ServerData: ObservableObject{ final class ServerData: ObservableObject{
// TODO: Find a way to save/represent this stuff in iOS settings/preferences (user can access via settings app). @Published var host: String = UserDefaults.standard.string(forKey: UserKeys.host) ?? "10.0.0.53"
// Then load the below values ar runtime, from settings. @Published var grpcPort: Int = UserDefaults.standard.integer(forKey: UserKeys.port)
// 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"
func load(){ func load(){
// Load the server values from settings, if they had been // Load the server values from settings, if they had been previously saved.
// previously saved.
} }
func save(){ func save(){

View File

@@ -6,23 +6,15 @@
<string>Root</string> <string>Root</string>
<key>PreferenceSpecifiers</key> <key>PreferenceSpecifiers</key>
<array> <array>
<dict>
<key>Type</key>
<string>PSGroupSpecifier</string>
<key>Title</key>
<string>Group</string>
</dict>
<dict> <dict>
<key>Type</key> <key>Type</key>
<string>PSTextFieldSpecifier</string> <string>PSTextFieldSpecifier</string>
<key>Title</key> <key>Title</key>
<string>Name</string> <string>Host</string>
<key>Key</key> <key>Key</key>
<string>name_preference</string> <string>host</string>
<key>DefaultValue</key> <key>DefaultValue</key>
<string></string> <string>10.0.0.53</string>
<key>IsSecure</key>
<false/>
<key>KeyboardType</key> <key>KeyboardType</key>
<string>Alphabet</string> <string>Alphabet</string>
<key>AutocapitalizationType</key> <key>AutocapitalizationType</key>
@@ -32,29 +24,17 @@
</dict> </dict>
<dict> <dict>
<key>Type</key> <key>Type</key>
<string>PSToggleSwitchSpecifier</string> <string>PSTextFieldSpecifier</string>
<key>Title</key> <key>Title</key>
<string>Enabled</string> <string>Port</string>
<key>Key</key> <key>Key</key>
<string>enabled_preference</string> <string>port</string>
<key>DefaultValue</key> <key>DefaultValue</key>
<true/> <string>50051</string>
</dict> <key>IsSecure</key>
<dict> <false/>
<key>Type</key> <key>KeyboardType</key>
<string>PSSliderSpecifier</string> <string>NumberPad</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>
</dict> </dict>
</array> </array>
</dict> </dict>

View File

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