Depend on external car wrapper library

This commit is contained in:
Piv
2020-09-02 21:17:03 +09:30
parent 2bd46e6901
commit f0bf033e0f
3 changed files with 39 additions and 155 deletions

View File

@@ -14,14 +14,15 @@ let package = Package(
.package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.12"), .package(url: "https://github.com/grpc/grpc-swift.git", from: "1.0.0-alpha.12"),
.package(url: "https://github.com/uraimo/SwiftyGPIO.git", from: "1.0.0"), .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/swiftrplidar.git", .branch("master")),
.package(url: "https://vato.ddns.net/gitlab/vato007/SwiftSerial.git", .branch("dtr_support")) .package(url: "https://vato.ddns.net/gitlab/vato007/SwiftSerial.git", .branch("dtr_support")),
.package(url: "https://vato.ddns.net/gitlab/vato007/swift2dcar.git", .branch("master"))
], ],
targets: [ targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite. // 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. // Targets can depend on other targets in this package, and on products in packages which this package depends on.
.target( .target(
name: "SwiftyCar", name: "SwiftyCar",
dependencies: ["SwiftyGPIO", .product(name: "GRPC", package: "grpc-swift"), "SwiftRPLidar"]), dependencies: ["SwiftyGPIO", .product(name: "GRPC", package: "grpc-swift"), "SwiftRPLidar", "Swift2dCar"]),
.testTarget( .testTarget(
name: "SwiftyCarTests", name: "SwiftyCarTests",
dependencies: ["SwiftyCar"]), dependencies: ["SwiftyCar"]),

View File

@@ -1,104 +0,0 @@
//
// PwmWrappers.swift
//
// Simple wrappers for PwmOutput I'll create as I go along, to match gpioZero's implementation I'm currently using.
// See gpiozero code here: https://github.com/gpiozero/gpiozero/blob/master/gpiozero/output_devices.py
//
// Created by Michael Pivato on 9/5/20.
//
import Foundation
import SwiftyGPIO
enum ServoError: Error{
case invalidMinPulseWidth
case invalidMaxPulseWidth
}
class Servo{
private (set) var frameWidth : Float
private var minDc: Float
private var dcRange: Float
private var minValue: Float
private var valueRange: Float
private var internalValue: Float
// TODO: Use a factory to provide the correct pwm rather than passing the pin in.
private var device: PWMOutput
private var currentPulseWIdth: Float
var minPulseWidth: Float {
get{
return self.minDc * self.frameWidth
}
}
var maxPulseWidth: Float{
get{
return (self.dcRange * self.frameWidth) + self.minPulseWidth
}
}
// TODO: Also store the pulse width (needs to be within this class)
// var pulseWidth: Float{
// get{
// return self.device//self.pwm_device.pin.state * self.frame_width
// }
// set (value){
//
// }
// }
var value: Float{
get{
internalValue
}
set(newValue){
self.internalValue = newValue
self.device.startPWM(period: Int(self.frameWidth),
// Multiple by 100 to get into percentage. I don't like that...
duty: self.minDc + self.dcRange * ((internalValue - self.minValue) / self.valueRange) * 100)
}
}
// TODO: Change this to nanoseconds to match PWMOutput
init?(forPin pin: PWMOutput, startingAt initialValue: Float = 0, withMinPulseWidth minPulseWidth: Float = 1000000,
withMaxPulseWidth maxPulseWidth: Float = 2000000, withFrameWidth frameWidth: Float = 20000000) throws {
if(minPulseWidth >= maxPulseWidth){
throw ServoError.invalidMinPulseWidth
}
if(maxPulseWidth >= frameWidth){
throw ServoError.invalidMaxPulseWidth
}
self.frameWidth = frameWidth
self.minDc = minPulseWidth / frameWidth
self.dcRange = (maxPulseWidth - minPulseWidth) / frameWidth
self.minValue = -1
self.valueRange = 2
self.currentPulseWIdth = 0
// Initialise pin immediately.
self.device = pin
self.device.initPWM()
self.internalValue = initialValue
self.device.startPWM(period: Int(self.frameWidth), duty: self.minDc + self.dcRange * ((internalValue - self.minValue) / self.valueRange) * 100)
}
func min(){
self.value = -1
}
func mid(){
self.value = 0
}
func max() {
self.value = 1
}
func detach(){
self.device.stopPWM()
}
}

View File

@@ -6,60 +6,47 @@
// //
import Foundation import Foundation
import SwiftyGPIO import Swift2dCar
protocol Vehicle{ public typealias ThrottleHandler = (_ magnitude: Float) -> Float
mutating func move2D(magnitude: Float, angle: 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
} }
protocol Vehicle2D: Vehicle{ /**
var throttle: Float {get set} Move the car by the given magnitude and angle, depending on how the is known to move with apriori throttle/steering.
var steering: Float {get set} */
}
class MockVehicle: Vehicle2D{
var throttle: Float = 0
var steering: Float = 0
func move2D(magnitude: Float, angle: Float) { 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)
} }
} }
class RPiVehicle2D: Vehicle2D{ /**
public let pwmThrottle: Servo Move to the coordinates relative to the car. You must first calibrate the car. A bicycle model is assumed.
public let pwmSteering: Servo */
func moveRelativeTo2D(x: Float, y: Float) {
var throttle: Float{ // TODO: This function, has a lot of edge cases. Also is really
get{
return pwmThrottle.value
}
set(value){
pwmThrottle.value = value
} }
} }
var steering: Float{
get{
return pwmSteering.value
}
set(value){
pwmSteering.value = value
}
}
init(withThrottlePin: Servo, withSteeringPin: Servo){
pwmThrottle = withThrottlePin
pwmSteering = withSteeringPin
}
func move2D(magnitude: Float, angle: Float) {
}
func stop(){
pwmThrottle.detach()
pwmSteering.detach()
}
}