Remove swift source, update esp32 usb servo to share serial port
This commit is contained in:
@@ -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"]
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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"]),
|
|
||||||
]
|
|
||||||
)
|
|
||||||
@@ -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<Google_Protobuf_Empty> {
|
|
||||||
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
func stop_tracking(request: Google_Protobuf_Empty, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
|
|
||||||
shouldScan = false
|
|
||||||
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
func start_tracking(request: Google_Protobuf_Empty, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
|
|
||||||
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
func record(request: Google_Protobuf_BoolValue, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
|
|
||||||
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
func save_lidar(request: MotorControl_SaveRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
|
|
||||||
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
func lidar_stream(request: Persontracking_StreamMessage, context: StreamingResponseCallContext<Persontracking_PointScan>) -> EventLoopFuture<GRPCStatus> {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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<MotorControl_ThrottleResponse> {
|
|
||||||
self.vehicle.throttle = request.throttle
|
|
||||||
return context.eventLoop.makeSucceededFuture(.with{ throttle in
|
|
||||||
throttle.throttleSet = true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func set_steering(request: MotorControl_SteeringRequest, context: StatusOnlyCallContext) -> EventLoopFuture<MotorControl_SteeringResponse> {
|
|
||||||
self.vehicle.steering = request.steering
|
|
||||||
return context.eventLoop.makeSucceededFuture(.with{
|
|
||||||
$0.steeringSet = true
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func stream_vehicle_2d(context: UnaryResponseCallContext<Google_Protobuf_Empty>) -> EventLoopFuture<(StreamEvent<MotorControl_Vehicle2DRequest>) -> 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<Google_Protobuf_Empty> {
|
|
||||||
// TODO: Recording...
|
|
||||||
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
|
|
||||||
}
|
|
||||||
|
|
||||||
func save_recorded_data(request: MotorControl_SaveRequest, context: StatusOnlyCallContext) -> EventLoopFuture<Google_Protobuf_Empty> {
|
|
||||||
// TODO Recording...
|
|
||||||
return context.eventLoop.makeSucceededFuture(Google_Protobuf_Empty())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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()
|
|
||||||
}
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import XCTest
|
|
||||||
|
|
||||||
import SwiftyCarTests
|
|
||||||
|
|
||||||
var tests = [XCTestCaseEntry]()
|
|
||||||
tests += SwiftyCarTests.allTests()
|
|
||||||
XCTMain(tests)
|
|
||||||
@@ -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),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
import XCTest
|
|
||||||
|
|
||||||
#if !canImport(ObjectiveC)
|
|
||||||
public func allTests() -> [XCTestCaseEntry] {
|
|
||||||
return [
|
|
||||||
testCase(SwiftyCarTests.allTests),
|
|
||||||
]
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -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'
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use serialport::SerialPort;
|
use serialport::SerialPort;
|
||||||
|
|
||||||
// TODO: Should be returning results in these traits
|
// TODO: Should be returning results in these traits
|
||||||
@@ -89,14 +91,14 @@ pub mod rppal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Esp32SerialPwmServo<T: SerialPort> {
|
pub struct Esp32SerialPwmServo<T: SerialPort> {
|
||||||
serial_port: T,
|
serial_port: Arc<Mutex<T>>,
|
||||||
value: f64,
|
value: f64,
|
||||||
channel: u8,
|
channel: u8,
|
||||||
pin: u8,
|
pin: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: SerialPort> Esp32SerialPwmServo<T> {
|
impl<T: SerialPort> Esp32SerialPwmServo<T> {
|
||||||
pub fn new(serial_port: T, channel: u8, pin: u8) -> Esp32SerialPwmServo<T> {
|
pub fn new(serial_port: Arc<Mutex<T>>, channel: u8, pin: u8) -> Esp32SerialPwmServo<T> {
|
||||||
Esp32SerialPwmServo {
|
Esp32SerialPwmServo {
|
||||||
serial_port,
|
serial_port,
|
||||||
value: 0.,
|
value: 0.,
|
||||||
@@ -108,7 +110,11 @@ impl<T: SerialPort> Esp32SerialPwmServo<T> {
|
|||||||
|
|
||||||
impl<T: SerialPort> Esp32SerialPwmServo<T> {
|
impl<T: SerialPort> Esp32SerialPwmServo<T> {
|
||||||
fn init_pwm(&mut self) {
|
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
|
// TODO: Better error handling
|
||||||
match bytes_written {
|
match bytes_written {
|
||||||
Ok(size) => println!("{}", size),
|
Ok(size) => println!("{}", size),
|
||||||
@@ -133,6 +139,8 @@ impl<T: SerialPort> Servo for Esp32SerialPwmServo<T> {
|
|||||||
self.value = temp_value;
|
self.value = temp_value;
|
||||||
let bytes_written = self
|
let bytes_written = self
|
||||||
.serial_port
|
.serial_port
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
.write(&[self.channel, ((value + 1.) / 2. * 255.) as u8]);
|
.write(&[self.channel, ((value + 1.) / 2. * 255.) as u8]);
|
||||||
// TODO: Better error handling
|
// TODO: Better error handling
|
||||||
match bytes_written {
|
match bytes_written {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use car_rs::{Esp32SerialPwmServo, ServoVehicle};
|
use car_rs::{Esp32SerialPwmServo, ServoVehicle};
|
||||||
use grpcserver::{
|
use grpcserver::{
|
||||||
motor_control_service::car_control_server::CarControlServer, MotorControlService,
|
motor_control_service::car_control_server::CarControlServer, MotorControlService,
|
||||||
@@ -15,13 +17,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let serial_port = serialport::new("", 32400)
|
let serial_port = serialport::new("", 32400)
|
||||||
.open_native()
|
.open_native()
|
||||||
.expect("Could not open serial port");
|
.expect("Could not open serial port");
|
||||||
let throttle_port = serialport::new("", 32400)
|
let serial_servo = Arc::new(Mutex::new(serial_port));
|
||||||
.open_native()
|
let steering_servo = Esp32SerialPwmServo::new(serial_servo.clone(), 1, 12);
|
||||||
.expect("Could not open serial port");
|
let throttle_servo = Esp32SerialPwmServo::new(serial_servo.clone(), 2, 18);
|
||||||
let servo = Esp32SerialPwmServo::new(serial_port, 1, 12);
|
|
||||||
let throttle_servo = Esp32SerialPwmServo::new(throttle_port, 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);
|
let svc = CarControlServer::new(motor_control);
|
||||||
Server::builder().add_service(svc).serve(addr).await?;
|
Server::builder().add_service(svc).serve(addr).await?;
|
||||||
|
|||||||
Reference in New Issue
Block a user