diff --git a/SwiftyCar/Dockerfile b/SwiftyCar/Dockerfile deleted file mode 100644 index e829502..0000000 --- a/SwiftyCar/Dockerfile +++ /dev/null @@ -1,9 +0,0 @@ -FROM vato.ddns.net:8083/swift:latest as builder -WORKDIR /root -COPY . . -RUN swift build -c release - -FROM vato.ddns.net:8083/swift:slim -WORKDIR /root -COPY --from=builder /root . -CMD [".build/x86_64-unknown-linux/release/docker-test"] \ No newline at end of file diff --git a/SwiftyCar/Package.resolved b/SwiftyCar/Package.resolved deleted file mode 100644 index 2a9708e..0000000 --- a/SwiftyCar/Package.resolved +++ /dev/null @@ -1,106 +0,0 @@ -{ - "object": { - "pins": [ - { - "package": "grpc-swift", - "repositoryURL": "https://github.com/grpc/grpc-swift.git", - "state": { - "branch": null, - "revision": "640b0ef1d0be63bda0ada86786cfda678ab2aae9", - "version": "1.0.0-alpha.19" - } - }, - { - "package": "swift-log", - "repositoryURL": "https://github.com/apple/swift-log.git", - "state": { - "branch": null, - "revision": "173f567a2dfec11d74588eea82cecea555bdc0bc", - "version": "1.4.0" - } - }, - { - "package": "swift-nio", - "repositoryURL": "https://github.com/apple/swift-nio.git", - "state": { - "branch": null, - "revision": "5fc24345f92ec4c274121776c215ab0aa1ed4d50", - "version": "2.22.0" - } - }, - { - "package": "swift-nio-http2", - "repositoryURL": "https://github.com/apple/swift-nio-http2.git", - "state": { - "branch": null, - "revision": "1e68e51752be0b43c5a0ef35818c1dd24d13e77c", - "version": "1.14.1" - } - }, - { - "package": "swift-nio-ssl", - "repositoryURL": "https://github.com/apple/swift-nio-ssl.git", - "state": { - "branch": null, - "revision": "ea1dfd64193bf5af4490635a4a44c4fb43b1e1ae", - "version": "2.9.1" - } - }, - { - "package": "swift-nio-transport-services", - "repositoryURL": "https://github.com/apple/swift-nio-transport-services.git", - "state": { - "branch": null, - "revision": "bb56586c4cab9a79dce6ec4738baddb5802c5de7", - "version": "1.9.0" - } - }, - { - "package": "SwiftProtobuf", - "repositoryURL": "https://github.com/apple/swift-protobuf.git", - "state": { - "branch": null, - "revision": "0279688c9fc5a40028e1b5bb0cb56534a45a6020", - "version": "1.12.0" - } - }, - { - "package": "Swift2dCar", - "repositoryURL": "https://vato.ddns.net/gitlab/vato007/swift2dcar.git", - "state": { - "branch": "master", - "revision": "970aac902531408614db0a37a7300e9373dafb50", - "version": null - } - }, - { - "package": "SwiftRPLidar", - "repositoryURL": "https://vato.ddns.net/gitlab/vato007/swiftrplidar.git", - "state": { - "branch": "master", - "revision": "761eb0bc1a00b4627a7870ffac121a542ff0cd6b", - "version": null - } - }, - { - "package": "SwiftSerial", - "repositoryURL": "https://vato.ddns.net/gitlab/vato007/SwiftSerial.git", - "state": { - "branch": "master", - "revision": "27a5d92aa00f6e91581389485994364e16bed2c5", - "version": null - } - }, - { - "package": "SwiftyGPIO", - "repositoryURL": "https://github.com/uraimo/SwiftyGPIO.git", - "state": { - "branch": null, - "revision": "2038228e020cf12a62012b1ebe36bb9b8e6fdb6a", - "version": "1.2.5" - } - } - ] - }, - "version": 1 -} diff --git a/SwiftyCar/Package.swift b/SwiftyCar/Package.swift deleted file mode 100644 index 35852aa..0000000 --- a/SwiftyCar/Package.swift +++ /dev/null @@ -1,35 +0,0 @@ -// swift-tools-version:5.1 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription - -let package = Package( - name: "SwiftyCar", - products: [ - // Products define the executables and libraries produced by a package, and make them visible to other packages. - ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.19"), - .package(url: "https://github.com/uraimo/SwiftyGPIO.git", from: "1.0.0"), - .package(url: "https://vato.ddns.net/gitlab/vato007/swiftrplidar.git", .branch("master")), - .package(url: "https://vato.ddns.net/gitlab/vato007/SwiftSerial.git", .branch("master")), - .package(url: "https://vato.ddns.net/gitlab/vato007/swift2dcar.git", .branch("master")) - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages which this package depends on. - .target( - name: "SwiftyCar", - dependencies: [ - "SwiftyGPIO", - .product(name: "GRPC", package: "grpc-swift"), - "SwiftRPLidar", - "SwiftSerial", - "Swift2dCar"]), - .testTarget( - name: "SwiftyCarTests", - dependencies: ["SwiftyCar"]), - ] -) diff --git a/SwiftyCar/Sources/SwiftyCar/LidarProvider.swift b/SwiftyCar/Sources/SwiftyCar/LidarProvider.swift deleted file mode 100644 index 4397fba..0000000 --- a/SwiftyCar/Sources/SwiftyCar/LidarProvider.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// LidarProvider.swift -// -// -// Created by Michael Pivato on 10/7/20. -// - -import Foundation -import GRPC -import NIO -import SwiftProtobuf -import SwiftRPLidar - -class LidarProvider: Persontracking_PersonTrackingProvider { - - private let lidar: SwiftRPLidar - private var shouldScan: Bool = false - - init(lidar: SwiftRPLidar) { - self.lidar = lidar - } - - func set_tracking_group(request: Persontracking_Int32Value, context: StatusOnlyCallContext) -> EventLoopFuture { - return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty()) - } - - func stop_tracking(request: Google_Protobuf_Empty, context: StatusOnlyCallContext) -> EventLoopFuture { - shouldScan = false - return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty()) - } - - func start_tracking(request: Google_Protobuf_Empty, context: StatusOnlyCallContext) -> EventLoopFuture { - return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty()) - } - - func record(request: Google_Protobuf_BoolValue, context: StatusOnlyCallContext) -> EventLoopFuture { - return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty()) - } - - func save_lidar(request: MotorControl_SaveRequest, context: StatusOnlyCallContext) -> EventLoopFuture { - return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty()) - } - - func lidar_stream(request: Persontracking_StreamMessage, context: StreamingResponseCallContext) -> EventLoopFuture { - shouldScan = true - try! lidar.iterScans{scan in - _ = context.sendResponse(.with{protoScan in - protoScan.points = scan.map{ point in - Persontracking_Point.with{ protoPoint in - protoPoint.angle = Double(point.angle) - protoPoint.distance = Double(point.distance) - // Placeholder group number. - protoPoint.groupNumber = 0 - } - } - }) - return shouldScan - } - return context.eventLoop.makeSucceededFuture(.ok) - } -} diff --git a/SwiftyCar/Sources/SwiftyCar/MotorProvider.swift b/SwiftyCar/Sources/SwiftyCar/MotorProvider.swift deleted file mode 100644 index 86e5005..0000000 --- a/SwiftyCar/Sources/SwiftyCar/MotorProvider.swift +++ /dev/null @@ -1,58 +0,0 @@ -// -// MotorProvider.swift -// -// -// Created by Michael Pivato on 13/5/20. -// - -import Foundation -import GRPC -import NIO -import SwiftProtobuf -import Swift2dCar - -class MotorProvider: MotorControl_CarControlProvider{ - private var vehicle: Vehicle2D - - init(vehicle: Vehicle2D){ - self.vehicle = vehicle - } - - func set_throttle(request: MotorControl_ThrottleRequest, context: StatusOnlyCallContext) -> EventLoopFuture { - self.vehicle.throttle = request.throttle - return context.eventLoop.makeSucceededFuture(.with{ throttle in - throttle.throttleSet = true - }) - } - - func set_steering(request: MotorControl_SteeringRequest, context: StatusOnlyCallContext) -> EventLoopFuture { - self.vehicle.steering = request.steering - return context.eventLoop.makeSucceededFuture(.with{ - $0.steeringSet = true - }) - } - - func stream_vehicle_2d(context: UnaryResponseCallContext) -> EventLoopFuture<(StreamEvent) -> Void> { - return context.eventLoop.makeSucceededFuture({event in - switch event{ - case .message(let movement): - self.vehicle.throttle = movement.throttle.throttle - self.vehicle.steering = movement.steering.steering - case .end: - context.responsePromise.succeed(Google_Protobuf_Empty()) - } - - }) - } - - func record(request: MotorControl_RecordingReqeust, context: StatusOnlyCallContext) -> EventLoopFuture { - // TODO: Recording... - return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty()) - } - - func save_recorded_data(request: MotorControl_SaveRequest, context: StatusOnlyCallContext) -> EventLoopFuture { - // TODO Recording... - return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty()) - } -} - diff --git a/SwiftyCar/Sources/SwiftyCar/Vehicle.swift b/SwiftyCar/Sources/SwiftyCar/Vehicle.swift deleted file mode 100644 index 8ba4cfe..0000000 --- a/SwiftyCar/Sources/SwiftyCar/Vehicle.swift +++ /dev/null @@ -1,52 +0,0 @@ -// -// Vehicle.swift -// -// -// Created by Michael Pivato on 8/5/20. -// - -import Foundation -import Swift2dCar - -public typealias ThrottleHandler = (_ magnitude: Float) -> Float -public typealias SteeringHandler = (_ angle: Float) -> Float - - -public class IntelligentPiCar : RPiVehicle2D { - - private var vehicleLength: Float? - private var throttleFunc: ThrottleHandler? - private var steeringFunc: SteeringHandler? - - /**: - Calibration function for how the car moves (acoording to a bicycle model) for a given throttle/steering angle. This sets the way the - - Parameters - - carLength - */ - func calibrate(vehicleLength: Float, throttleFunc: @escaping ThrottleHandler, steeringFunc: @escaping SteeringHandler){ - // Define a function that indicates how the throttle/steering should be set for given magnitude/angle to move. - self.vehicleLength = vehicleLength - self.throttleFunc = throttleFunc - self.steeringFunc = steeringFunc - } - - /** - Move the car by the given magnitude and angle, depending on how the is known to move with apriori throttle/steering. - */ - func move2D(magnitude: Float, angle: Float) { - if let throttleFunc = self.throttleFunc { -// self.pwmThrottle.value = throttleFunc(magnitude) - } - - if let steeringFunc = steeringFunc { -// self.pwmSteering.value = steeringFunc(angle) - } - } - - /** - Move to the coordinates relative to the car. You must first calibrate the car. A bicycle model is assumed. - */ - func moveRelativeTo2D(x: Float, y: Float) { - // TODO: This function, has a lot of edge cases. Also is really - } -} diff --git a/SwiftyCar/Sources/SwiftyCar/VehicleFactory.swift b/SwiftyCar/Sources/SwiftyCar/VehicleFactory.swift deleted file mode 100644 index 16f1c7b..0000000 --- a/SwiftyCar/Sources/SwiftyCar/VehicleFactory.swift +++ /dev/null @@ -1,45 +0,0 @@ -// -// VehicleFactory.swift -// -// -// Created by Michael Pivato on 20/5/20. -// - -import Foundation -import SwiftyGPIO -import Swift2dCar -import SwiftSerial - -func getVehicle2D() throws -> Vehicle2D? { - // TODO: Clean up this factory, or see if we can get dependency injection working. - if let value = ProcessInfo.processInfo.environment["CAR_VEHICLE"] { - switch value{ - case "VEHICLE_2D": - // Get car for rpi. - let pwms = SwiftyGPIO.hardwarePWMs(for:.RaspberryPi3)! - return try RPiVehicle2D(withThrottlePin: PWMHardwareServo(forPin: (pwms[0]?[.P18])!)!, withSteeringPin:PWMHardwareServo(forPin: (pwms[1]?[.P19])!)!) - case "VEHICLE_SERIAL": - // TODO: Get from environment variable. tty won't work in macos anyway. - // We share the serialport object, as cu will block on macOS (required by SwiftSerial), so can't open 2 of the same port. - let serialPort = SerialPort(path: "/dev/ttyUSB0") - - // The port does not open/initialise inside of the ESP32ServoOutputs, as on macOS /dev/cu.* blocks. - try serialPort.openPort() - serialPort.setSettings(receiveRate: .baud115200, transmitRate: .baud115200, minimumBytesToRead: 1) - guard let throttlePin = Esp32ServoOutput(forChannel: 1, forPin: 14, onPort: serialPort) else { - print("Failed to create throttle pin.") - return nil - } - - guard let steeringPin = Esp32ServoOutput(forChannel: 2, forPin: 12, onPort: serialPort) else { - print("Failed to create steering pin.") - return nil - } - - return try RPiVehicle2D(withThrottlePin: PWMHardwareServo(forPin: throttlePin)!, withSteeringPin: PWMHardwareServo(forPin: steeringPin)!) - default: - return MockVehicle() - } - } - return MockVehicle() -} diff --git a/SwiftyCar/Sources/SwiftyCar/main.swift b/SwiftyCar/Sources/SwiftyCar/main.swift deleted file mode 100644 index d0b56b3..0000000 --- a/SwiftyCar/Sources/SwiftyCar/main.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// main.swift -// -// -// Created by Michael Pivato on 8/5/20. -// - -import NIO -import GRPC -import SwiftRPLidar -import SwiftSerial - -func doServer() throws { - // Copied from examples - // Create an event loop group for the server to run on. - let group = MultiThreadedEventLoopGroup(numberOfThreads: System.coreCount) - defer { - try! group.syncShutdownGracefully() - } - - let lidar = createLidar() - try lidar.iterMeasurements{measruement in - print(measruement.quality) - return false - } - // Create a provider using the features we read. - let provider = try MotorProvider(vehicle: getVehicle2D()!) - let trackingProvider = LidarProvider(lidar: lidar) - - // Start the server and print its address once it has started. - let server = Server.insecure(group: group) - .withServiceProviders([provider, trackingProvider]) - .bind(host: "localhost", port: 0) - - server.map { - $0.channel.localAddress - }.whenSuccess { address in - print("server started on port \(address!.port!)") - } - - // Wait on the server's `onClose` future to stop the program from exiting. - _ = try server.flatMap { - $0.onClose - }.wait() -} - -func createLidar() -> SwiftRPLidar{ - return try! SwiftRPLidar(onPort: SerialPort(path: "/dev/cu.usbserial0001")) - -} - -// Entry-Point to the Swift Car Controller -print("Starting Server") -do{ - try doServer() -} -catch{ - print("Server failed") -} - -extension SerialPort: LidarSerial{ - public func setBaudrate(baudrate: Int) { - // TODO: handle different baudrates. Only need this for now. - switch baudrate{ - default: - setSettings(receiveRate: .baud115200, transmitRate: .baud115200, minimumBytesToRead: 1) - } - - } -} diff --git a/SwiftyCar/Tests/LinuxMain.swift b/SwiftyCar/Tests/LinuxMain.swift deleted file mode 100644 index c68226f..0000000 --- a/SwiftyCar/Tests/LinuxMain.swift +++ /dev/null @@ -1,7 +0,0 @@ -import XCTest - -import SwiftyCarTests - -var tests = [XCTestCaseEntry]() -tests += SwiftyCarTests.allTests() -XCTMain(tests) diff --git a/SwiftyCar/Tests/SwiftyCarTests/SwiftyCarTests.swift b/SwiftyCar/Tests/SwiftyCarTests/SwiftyCarTests.swift deleted file mode 100644 index bebfbd1..0000000 --- a/SwiftyCar/Tests/SwiftyCarTests/SwiftyCarTests.swift +++ /dev/null @@ -1,15 +0,0 @@ -import XCTest -@testable import SwiftyCar - -final class SwiftyCarTests: XCTestCase { - func testExample() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct - // results. -// XCTAssertEqual(SwiftyCar().text, "Hello, World!") - } - - static var allTests = [ - ("testExample", testExample), - ] -} diff --git a/SwiftyCar/Tests/SwiftyCarTests/XCTestManifests.swift b/SwiftyCar/Tests/SwiftyCarTests/XCTestManifests.swift deleted file mode 100644 index 02cc67f..0000000 --- a/SwiftyCar/Tests/SwiftyCarTests/XCTestManifests.swift +++ /dev/null @@ -1,9 +0,0 @@ -import XCTest - -#if !canImport(ObjectiveC) -public func allTests() -> [XCTestCaseEntry] { - return [ - testCase(SwiftyCarTests.allTests), - ] -} -#endif diff --git a/SwiftyCar/build.gradle b/SwiftyCar/build.gradle deleted file mode 100644 index 38b27e0..0000000 --- a/SwiftyCar/build.gradle +++ /dev/null @@ -1,16 +0,0 @@ -configurations{ - swift { - canBeConsumed = false - canBeResolved = true - } -} - -dependencies { - swift project(path: ':protobuf', configuration: 'swift') -} - -task copySwiftCode(type: Copy, dependsOn: configurations.swift) { - // Copy python protobuf code from proto project. - from zipTree(configurations.swift.asPath) - into './Sources/SwiftyCar' -} \ No newline at end of file diff --git a/car-rs/src/lib.rs b/car-rs/src/lib.rs index 16f1781..3058605 100644 --- a/car-rs/src/lib.rs +++ b/car-rs/src/lib.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use serialport::SerialPort; // TODO: Should be returning results in these traits @@ -89,14 +91,14 @@ pub mod rppal { } pub struct Esp32SerialPwmServo { - serial_port: T, + serial_port: Arc>, value: f64, channel: u8, pin: u8, } impl Esp32SerialPwmServo { - pub fn new(serial_port: T, channel: u8, pin: u8) -> Esp32SerialPwmServo { + pub fn new(serial_port: Arc>, channel: u8, pin: u8) -> Esp32SerialPwmServo { Esp32SerialPwmServo { serial_port, value: 0., @@ -108,7 +110,11 @@ impl Esp32SerialPwmServo { impl Esp32SerialPwmServo { fn init_pwm(&mut self) { - let bytes_written = self.serial_port.write(&[0, 1, self.channel, self.pin]); + let bytes_written = self + .serial_port + .lock() + .unwrap() + .write(&[0, 1, self.channel, self.pin]); // TODO: Better error handling match bytes_written { Ok(size) => println!("{}", size), @@ -133,6 +139,8 @@ impl Servo for Esp32SerialPwmServo { self.value = temp_value; let bytes_written = self .serial_port + .lock() + .unwrap() .write(&[self.channel, ((value + 1.) / 2. * 255.) as u8]); // TODO: Better error handling match bytes_written { diff --git a/car-rs/src/main.rs b/car-rs/src/main.rs index b4da71f..1b5b4af 100644 --- a/car-rs/src/main.rs +++ b/car-rs/src/main.rs @@ -1,3 +1,5 @@ +use std::sync::{Arc, Mutex}; + use car_rs::{Esp32SerialPwmServo, ServoVehicle}; use grpcserver::{ motor_control_service::car_control_server::CarControlServer, MotorControlService, @@ -15,13 +17,11 @@ async fn main() -> Result<(), Box> { let serial_port = serialport::new("", 32400) .open_native() .expect("Could not open serial port"); - let throttle_port = serialport::new("", 32400) - .open_native() - .expect("Could not open serial port"); - let servo = Esp32SerialPwmServo::new(serial_port, 1, 12); - let throttle_servo = Esp32SerialPwmServo::new(throttle_port, 2, 18); + let serial_servo = Arc::new(Mutex::new(serial_port)); + let steering_servo = Esp32SerialPwmServo::new(serial_servo.clone(), 1, 12); + let throttle_servo = Esp32SerialPwmServo::new(serial_servo.clone(), 2, 18); - let motor_control = MotorControlService::new(ServoVehicle::new(servo, throttle_servo)); + let motor_control = MotorControlService::new(ServoVehicle::new(steering_servo, throttle_servo)); let svc = CarControlServer::new(motor_control); Server::builder().add_service(svc).serve(addr).await?;