GenericCommand
This commit is contained in:
parent
0723b5c6a4
commit
e3dbd8bdee
159
src/command.rs
159
src/command.rs
@ -11,6 +11,52 @@ impl CommandId for u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait WithCommandData {
|
||||||
|
fn command_data(&self) -> &CommandData;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CommandInfo: CommandId {
|
||||||
|
fn name(&self) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CommandData {
|
||||||
|
command_id: u64,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandData {
|
||||||
|
pub fn new<TName: Into<String>>(command_id: u64, name: TName) -> Self {
|
||||||
|
CommandData {
|
||||||
|
command_id,
|
||||||
|
name: name.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandId for CommandData {
|
||||||
|
fn command_id(&self) -> u64 {
|
||||||
|
self.command_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CommandInfo for CommandData {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
&self.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: WithCommandData> CommandId for T {
|
||||||
|
fn command_id(&self) -> u64 {
|
||||||
|
self.command_data().command_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: WithCommandData> CommandInfo for T {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
&self.command_data().name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
pub enum CommandResult {
|
pub enum CommandResult {
|
||||||
Continue,
|
Continue,
|
||||||
@ -18,108 +64,106 @@ pub enum CommandResult {
|
|||||||
Cancel,
|
Cancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Command {
|
pub trait Command: WithCommandData {
|
||||||
fn init(&mut self);
|
fn init(&mut self);
|
||||||
fn step(&mut self) -> CommandResult;
|
fn step(&mut self) -> CommandResult;
|
||||||
fn finish(&mut self, result: CommandResult);
|
fn finish(&mut self, result: CommandResult);
|
||||||
fn command_data(&self) -> &CommandData;
|
}
|
||||||
|
|
||||||
|
pub struct GenericCommand<TConfig, TState> {
|
||||||
|
command_data: CommandData,
|
||||||
|
pub config: TConfig,
|
||||||
|
pub state: TState,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TConfig, TState> GenericCommand<TConfig, TState>
|
||||||
|
where
|
||||||
|
TConfig: 'static,
|
||||||
|
GenericCommand<TConfig, TState>: Command,
|
||||||
|
TState: Default + 'static,
|
||||||
|
{
|
||||||
|
pub fn new(command_data: CommandData, config: TConfig) -> Self {
|
||||||
|
Self {
|
||||||
|
command_data,
|
||||||
|
config,
|
||||||
|
state: TState::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_ref(command_data: CommandData, config: TConfig) -> CommandRef {
|
||||||
|
Rc::new(RefCell::new(Self::new(command_data, config)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TConfig, TState> WithCommandData for GenericCommand<TConfig, TState> {
|
||||||
|
fn command_data(&self) -> &CommandData {
|
||||||
|
&self.command_data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! command_impl {
|
macro_rules! command_impl {
|
||||||
(
|
(
|
||||||
$command_st:ident . $command_data:ident;
|
$command:ident<$tconfig:ty,$tstate:ty>;
|
||||||
$init_self:ident => $init:block;
|
$init_self:ident => $init:block;
|
||||||
$step_self:ident => $step:block;
|
$step_self:ident => $step:block;
|
||||||
$finish_self:ident, $finish_result:ident => $finish:block
|
$finish_self:ident, $finish_result:ident => $finish:block
|
||||||
) => {
|
) => {
|
||||||
impl $crate::command::Command for $command_st {
|
pub type $command = GenericCommand<$tconfig, $tstate>;
|
||||||
|
|
||||||
|
impl $crate::command::Command for $command {
|
||||||
fn init(&mut $init_self) {
|
fn init(&mut $init_self) {
|
||||||
|
use $crate::command::CommandInfo;
|
||||||
debug!(
|
debug!(
|
||||||
"{}({}) init",
|
"{}({}) init",
|
||||||
stringify!($command_st),
|
stringify!($command_st),
|
||||||
$init_self.command_data().name()
|
$init_self.name()
|
||||||
);
|
);
|
||||||
$init;
|
$init;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut $step_self) -> $crate::command::CommandResult {
|
fn step(&mut $step_self) -> $crate::command::CommandResult {
|
||||||
|
use $crate::command::CommandInfo;
|
||||||
debug!(
|
debug!(
|
||||||
"{}({}) step",
|
"{}({}) step",
|
||||||
stringify!($command_st),
|
stringify!($command_st),
|
||||||
$step_self.command_data().name()
|
$step_self.name()
|
||||||
);
|
);
|
||||||
$step
|
$step
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&mut $finish_self, $finish_result: $crate::command::CommandResult) {
|
fn finish(&mut $finish_self, $finish_result: $crate::command::CommandResult) {
|
||||||
|
use $crate::command::CommandInfo;
|
||||||
debug!(
|
debug!(
|
||||||
"{}({}) finish({:?}",
|
"{}({}) finish({:?}",
|
||||||
stringify!($command_st),
|
stringify!($command_st),
|
||||||
$finish_self.command_data().name(),
|
$finish_self.name(),
|
||||||
$finish_result,
|
$finish_result,
|
||||||
);
|
);
|
||||||
$finish;
|
$finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_data(&self) -> &$crate::command::CommandData {
|
|
||||||
&self.command_data
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
$command_st:ident . $command_data:ident;
|
$command:ident<$tconfig:ty,$tstate:ty>;
|
||||||
$init_self:ident => $init:block;
|
$init_self:ident => $init:block;
|
||||||
$step_self:ident => $step:block;
|
$step_self:ident => $step:block;
|
||||||
$finish_self:ident => $finish:block
|
$finish_self:ident => $finish:block
|
||||||
) => {
|
) => {
|
||||||
command_impl! { $command_st.$command_data;
|
command_impl! { $command<$tconfig,$tstate>;
|
||||||
$init_self => $init; $step_self => $step; $finish_self, res => {} }
|
$init_self => $init; $step_self => $step; $finish_self, res => {} }
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
$command_st:ident . $command_data:ident;
|
$command:ident<$tconfig:ty>;
|
||||||
$init_self:ident => $init:block
|
$init_self:ident => $init:block
|
||||||
) => {
|
) => {
|
||||||
command_impl! { $command_st.$command_data;
|
command_impl! { $command<$tconfig,()>;
|
||||||
$init_self => $init; self => { $crate::command::CommandResult::Done }; self => {} }
|
$init_self => $init; self => { $crate::command::CommandResult::Done }; self => {} }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandData {
|
|
||||||
id: u64,
|
|
||||||
name: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CommandData {
|
|
||||||
pub fn new<TName: Into<String>>(id: u64, name: TName) -> Self {
|
|
||||||
CommandData {
|
|
||||||
id,
|
|
||||||
name: name.into(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn id(&self) -> u64 {
|
|
||||||
self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(&self) -> &str {
|
|
||||||
&self.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CommandId for CommandData {
|
|
||||||
fn command_id(&self) -> u64 {
|
|
||||||
self.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type CommandRef = Rc<RefCell<dyn Command>>;
|
pub type CommandRef = Rc<RefCell<dyn Command>>;
|
||||||
|
|
||||||
impl CommandId for CommandRef {
|
|
||||||
fn command_id(&self) -> u64 {
|
|
||||||
self.borrow().command_data().id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CommandGroup {
|
pub struct CommandGroup {
|
||||||
commands: Vec<CommandRef>,
|
commands: Vec<CommandRef>,
|
||||||
command_data: CommandData,
|
command_data: CommandData,
|
||||||
@ -143,6 +187,12 @@ impl CommandGroup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WithCommandData for CommandGroup {
|
||||||
|
fn command_data(&self) -> &CommandData {
|
||||||
|
&self.command_data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Command for CommandGroup {
|
impl Command for CommandGroup {
|
||||||
fn init(&mut self) {
|
fn init(&mut self) {
|
||||||
if self.current_idx.is_some() {
|
if self.current_idx.is_some() {
|
||||||
@ -220,10 +270,6 @@ impl Command for CommandGroup {
|
|||||||
}
|
}
|
||||||
self.current_idx = None;
|
self.current_idx = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_data(&self) -> &CommandData {
|
|
||||||
&self.command_data
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandRun {
|
pub struct CommandRun {
|
||||||
@ -234,7 +280,7 @@ pub struct CommandRun {
|
|||||||
|
|
||||||
impl CommandId for CommandRun {
|
impl CommandId for CommandRun {
|
||||||
fn command_id(&self) -> u64 {
|
fn command_id(&self) -> u64 {
|
||||||
self.command.command_id()
|
self.command.borrow().command_data().command_id()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +343,7 @@ impl CommandScheduler {
|
|||||||
* Returns true if the command was started, false if it was not started because it was already running
|
* Returns true if the command was started, false if it was not started because it was already running
|
||||||
*/
|
*/
|
||||||
pub fn start(&mut self, command: CommandRef) -> bool {
|
pub fn start(&mut self, command: CommandRef) -> bool {
|
||||||
if self.is_running(command.command_id()) {
|
if self.is_running(command.borrow().command_data().command_id()) {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
self.running_commands.push(CommandRun {
|
self.running_commands.push(CommandRun {
|
||||||
@ -322,9 +368,10 @@ impl CommandScheduler {
|
|||||||
if !command_run.initialized && !command_run.cancelled {
|
if !command_run.initialized && !command_run.cancelled {
|
||||||
{
|
{
|
||||||
let command_data = command.command_data();
|
let command_data = command.command_data();
|
||||||
info!(
|
debug!(
|
||||||
"initialzing command {} (id {})",
|
"initialzing command {} (id {})",
|
||||||
command_data.name, command_data.id
|
command_data.name(),
|
||||||
|
command_data.command_id()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
command.init();
|
command.init();
|
||||||
|
71
src/robot.rs
71
src/robot.rs
@ -7,48 +7,46 @@ use command::{CommandData, CommandGroup, CommandRef, CommandScheduler};
|
|||||||
use drive::{Drive, DriveRef};
|
use drive::{Drive, DriveRef};
|
||||||
|
|
||||||
mod cmds {
|
mod cmds {
|
||||||
use command::{CommandData, CommandResult};
|
use command::{Command, CommandResult, GenericCommand};
|
||||||
use drive::DriveRef;
|
use drive::DriveRef;
|
||||||
|
use self::CommandResult::*;
|
||||||
|
|
||||||
pub struct DriveCommand {
|
pub struct DriveCommandConfig {
|
||||||
command_data: CommandData,
|
pub drive: DriveRef,
|
||||||
iterations: u64,
|
|
||||||
drive: DriveRef,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DriveCommand {
|
pub struct DriveCommandState {
|
||||||
pub fn new(command_data: CommandData, drive: DriveRef) -> Self {
|
iterations: u64,
|
||||||
Self {
|
}
|
||||||
command_data,
|
|
||||||
iterations: 0,
|
impl Default for DriveCommandState {
|
||||||
drive,
|
fn default() -> Self {
|
||||||
}
|
DriveCommandState { iterations: 0 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
command_impl! { DriveCommand.command_data;
|
pub type DriveCommand = GenericCommand<DriveCommandConfig, DriveCommandState>;
|
||||||
self => {
|
|
||||||
self.iterations = 0;
|
|
||||||
|
|
||||||
}; self =>{
|
impl Command for DriveCommand {
|
||||||
self.drive.borrow_mut().drive_powers(1.0, 1.0);
|
fn init(&mut self) {
|
||||||
self.iterations += 1;
|
self.state = DriveCommandState::default();
|
||||||
if self.iterations >= 10 {
|
}
|
||||||
CommandResult::Done
|
fn step(&mut self) -> CommandResult {
|
||||||
|
self.config.drive.borrow_mut().drive_powers(1.0, 1.0);
|
||||||
|
self.state.iterations += 1;
|
||||||
|
if self.state.iterations >= 10 {
|
||||||
|
Done
|
||||||
} else {
|
} else {
|
||||||
CommandResult::Continue
|
Continue
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}; self, res => {
|
fn finish(&mut self, res: CommandResult) {
|
||||||
self.drive.borrow_mut().drive_powers(0.0,0.0);
|
self.config.drive.borrow_mut().drive_powers(0.0, 0.0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
pub struct LogCmd {
|
|
||||||
pub command_data: crate::command::CommandData,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
command_impl! {
|
command_impl! {
|
||||||
LogCmd.command_data; self => { info!("{}", "LogCmd") }
|
LogCmd<()>; self => { info!("{}", "LogCmd") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,15 +68,16 @@ impl Robot {
|
|||||||
pub fn run(mut self) {
|
pub fn run(mut self) {
|
||||||
warn!("Starting RobotRS");
|
warn!("Starting RobotRS");
|
||||||
|
|
||||||
let command = cmds::DriveCommand::new(CommandData::new(0, "DriveCommand"), self.drive.clone());
|
let command = cmds::DriveCommand::new_ref(
|
||||||
let command_ref: CommandRef = Rc::new(RefCell::new(command));
|
CommandData::new(0, "DriveCommand"),
|
||||||
let log_command = cmds::LogCmd {
|
cmds::DriveCommandConfig {
|
||||||
command_data: CommandData::new(2, "LogCommand"),
|
drive: self.drive.clone(),
|
||||||
};
|
},
|
||||||
let log_command_ref: CommandRef = Rc::new(RefCell::new(log_command));
|
);
|
||||||
|
let log_command = cmds::LogCmd::new_ref(CommandData::new(2, "LogCommand"), ());
|
||||||
let command_group = CommandGroup::new(
|
let command_group = CommandGroup::new(
|
||||||
CommandData::new(1, "Group"),
|
CommandData::new(1, "Group"),
|
||||||
vec![command_ref, log_command_ref],
|
vec![command, log_command],
|
||||||
);
|
);
|
||||||
let command_ref: CommandRef = Rc::new(RefCell::new(command_group));
|
let command_ref: CommandRef = Rc::new(RefCell::new(command_group));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user