Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platoon: Leader App #84

Merged
merged 13 commits into from
Jan 29, 2024
28 changes: 28 additions & 0 deletions data/config/follower_1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"robotName": "follower_1",
"wifi": {
"ssid": "TheForce",
"pswd": "hanshotfirst"
},
"mqtt": {
"host": "localhost",
"port": 1883
},
"ap": {
"ssid": "DCS_AP",
"pswd": "hanshotfirst"
},
"webServer": {
"user": "admin",
"pswd": "admin"
},
"platoon": {
"platoonId": "0",
"vehicleId": "1"
},
"initialPosition": {
"x": "0",
"y": "0",
"heading": "0"
}
}
28 changes: 28 additions & 0 deletions data/config/follower_2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"robotName": "follower_2",
"wifi": {
"ssid": "TheForce",
"pswd": "hanshotfirst"
},
"mqtt": {
"host": "localhost",
"port": 1883
},
"ap": {
"ssid": "DCS_AP",
"pswd": "hanshotfirst"
},
"webServer": {
"user": "admin",
"pswd": "admin"
},
"platoon": {
"platoonId": "0",
"vehicleId": "2"
},
"initialPosition": {
"x": "0",
"y": "0",
"heading": "0"
}
}
28 changes: 28 additions & 0 deletions data/config/leader.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"robotName": "leader",
"wifi": {
"ssid": "TheForce",
"pswd": "hanshotfirst"
},
"mqtt": {
"host": "localhost",
"port": 1883
},
"ap": {
"ssid": "DCS_AP",
"pswd": "hanshotfirst"
},
"webServer": {
"user": "admin",
"pswd": "admin"
},
"platoon": {
"platoonId": "0",
"vehicleId": "0"
},
"initialPosition": {
"x": "0",
"y": "0",
"heading": "1588"
}
}
102 changes: 102 additions & 0 deletions doc/architecture/uml/LogicalView/Leader/Leader.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
@startuml DcsClassDiagram

Title DCS Class Diagram

class "Application" as app {
+ setup() : void
+ loop() : void
+ release() : void
- m_serialMuxProtServer : SMPServer
- m_systemStateMachine : StateMachine
- m_remoteControlHandler : RemoteControlHandler
- m_safetyMonitor : SafetyMonitor
}

note right of app
Callbacks for SerialMuxProtServer and MqttClient are defined here.
Uses the setters of each class or state to forward the data.
Uses the getters of each class or state to get the data that shall be sent to the RU or the V2V controller.
end note

class "V2V Controller" as v2v {
- m_mqttClient : MqttClient
- m_rxWaypointQueue : Queue
+ init(MqttConfig) : bool
+ process() : bool
+ sendWaypoint(const Waypoint&) : bool
+ getWaypoint(Waypoint&) : bool
}

class StateMachine <<control>> {
+ setState(state : IState*) : void
+ getState() : IState*
+ process() : void
}

class "RemoteCommandResponseHandler" as smpHandler {
+ processResponse(const CommandResponse&) : void
}

note right of smpHandler
This class is responsible for handling
the response from the remote command
sent to RU.
- Notifies StartupState of successful commands.
- Sets max speed in DrivingState.
end note

class "SafetyMonitor" as safety {
+ process(StateMachine& sm) : void
+ getPendingHeartbeat(const Hearbeat& hb) : bool
+ heartbeatCallback(const Hearbeat& hb) : void
}

interface IState {
+ {abstract} entry() : void
+ {abstract} process(sm : StateMachine&) : void
+ {abstract} exit() : void
}

class StartupState <<Singleton>>
{
+ getPendingCommand(Command& cmd) : bool
+ notify(Event event) : void
}

class IdleState <<Singleton>>

class DrivingState <<Singleton>> {
- m_longitudinalController : LongitudinalController
+ setMaxMotorSpeed(int16_t maxMotorSpeed) : void
+ calculateTopMotorSpeed(const Waypoint& currentVehicleData): int16_t
+ setLastFollowerFeedback(const Waypoint& feedback) : void
+ getLatestVehicleData(Waypoint& vehicleData) : bool
}

protocol "SerialMuxChannels" as smpch {
+ typedef SerialMuxProtServer<MAX_CHANNELS> SMPServer
+ struct Command
+ struct CommandReponse
+ struct SpeedData
+ struct VehicleData
}

app *--> v2v
app *--> StateMachine
app *--> smpHandler
app *--> safety
app ..> DrivingState: <<use>>
app ..> StartupState: <<use>>
app ..> smpch: <<use>>

StateMachine o--> "0..1" IState

IState <|.. StartupState: <<realize>>
IState <|.. IdleState: <<realize>>
IState <|.. DrivingState: <<realize>>
IState <|.. ErrorState: <<realize>>

smpHandler ..> StartupState: <<use>>
smpHandler ..> DrivingState: <<use>>

@enduml
110 changes: 110 additions & 0 deletions doc/architecture/uml/ProcessView/Leader/AppSequence.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
@startuml LeaderAppSequenceDiagram

autoactivate on

Title Leader App Sequence Diagram

participant "App" as App
participant "State Machine" as SM
participant "SMP Server" as Smp
participant "V2V Client" as Mqtt
participant "Remote Command Response Handler" as RCRH
participant "Startup State" as StartupState
participant "Idle State" as IdleState
participant "Driving State" as DrivingState
participant "Safety Monitor" as SafetyMonitor

entity "RadonUlzer" as RU

== State Machine: Startup State ==

group Startup Commands [Repeats for each pending command]
App -> StartupState : getPendingCommand
return pendingCommand

App -> Smp : sendCommand(pendingCommand)
Smp -> RU : send
deactivate
return command sent

RU -->> Smp : response

App -> Smp : process()
Smp -> App : CMD_RSP callback
App -> RCRH : handleCommandResponse(rsp)
alt OK
RCRH -> StartupState : notify(Event event)
return
end
alt max speed received
RCRH -> DrivingState : setMaxSpeed(speed)
return
end
alt error received
RCRH -> SM : setState(ErrorState)
return
end
return
return
return
end group

== State Machine: Idle State ==

group Wait for release
App -> Mqtt : process()
Mqtt -> App : release command
App -> IdleState : release()
return
return
return

end group

== State Machine: Driving State ==
group Driving
App -> Smp : process()
Smp -> App : CurrentVehicleData
App -> DrivingState : CurrentVehicleData
return top speed
App -> Smp : sendSpeed(topSpeed)
Smp -> RU : send
deactivate
return
return
return

App -> Mqtt : process()
Mqtt -> App : lastFollowerFeedbackCallback()
App -> DrivingState : setLastFollowerFeedback(const Waypoint& feedback)
return
return
return

App -> DrivingState : getLatestVehicleData(Waypoint& vehicleData)
return vehicle data is valid

App -> Mqtt : sendWaypoint(const Waypoint& vehicleData)
return

end group

== Stateless ==

loop
App -> Smp : process()
Smp -> App : Heartbeat callback
App -> SafetyMonitor : heartbeatCallback()
return
return
return

App -> SafetyMonitor : process()
SafetyMonitor -> SafetyMonitor : checkHeartbeat()
return false
SafetyMonitor -> SM : setState(ErrorState)
return
return
end loop

@enduml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
@startuml CommSequence

Title Sequence Diagram RU and DCS

autoactivate on

participant "RU" as RU
participant "DCS" as DCS

note across: Possible STATUS = {STARTUP, OK, ERROR}

group State-Independent Messages
RU --> DCS: STATUS: RU_STATE
DCS --> RU: STATUS: DCS_STATE
end

group StateLessSetup
RU --> DCS: Subscribe: STATUS
RU --> DCS: Subscribe: CMD
RU --> DCS: Subscribe: SPEED_SETPOINT
DCS --> RU: Subscribe: STATUS
DCS --> RU: Subscribe: CMD_RSP
DCS --> RU: Subscribe: CURRENT_VEHICLE_DATA
end

group StatupState
DCS -> RU: CMD: GetMaxSpeed
RU -->> DCS: CMD_RSP:OK + maxSpeed
DCS -> RU: CMD: SetInitialPosition
RU -->> DCS: CMD_RSP:OK
end

group LineSensorsCalibrationState

end

group IdleState
DCS -> RU: CMD: Release
RU -->> DCS: CMD_RSP:OK
end

group DrivingState
RU ->> DCS: CURRENT_VEHICLE_DATA:Data
DCS -> DCS: CalculateSpeed
return
DCS --> RU: SPEED_SETPOINT: Top Center Speed
end

group ErrorState

end

@enduml
Loading
Loading