even better command stuff
This commit is contained in:
parent
fc141339f9
commit
f5c520816e
376
src/command.rs
376
src/command.rs
@ -11,154 +11,246 @@ impl CommandId for u64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WithCommandData {
|
pub trait WithCommandInfo {
|
||||||
fn command_data(&self) -> &CommandData;
|
fn command_info(&self) -> &CommandInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CommandInfo: CommandId {
|
pub trait GetCommandInfo: CommandId {
|
||||||
fn name(&self) -> &str;
|
fn name(&self) -> &str;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandData {
|
pub struct CommandInfo {
|
||||||
command_id: u64,
|
command_id: u64,
|
||||||
name: String,
|
name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandData {
|
impl CommandInfo {
|
||||||
pub fn new<TName: Into<String>>(command_id: u64, name: TName) -> Self {
|
pub fn new<TName: Into<String>>(command_id: u64, name: TName) -> Self {
|
||||||
CommandData {
|
Self {
|
||||||
command_id,
|
command_id,
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandId for CommandData {
|
impl CommandId for CommandInfo {
|
||||||
fn command_id(&self) -> u64 {
|
fn command_id(&self) -> u64 {
|
||||||
self.command_id
|
self.command_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandInfo for CommandData {
|
impl GetCommandInfo for CommandInfo {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
&self.name
|
&self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: WithCommandData> CommandId for T {
|
impl<T: WithCommandInfo> CommandId for T {
|
||||||
fn command_id(&self) -> u64 {
|
fn command_id(&self) -> u64 {
|
||||||
self.command_data().command_id
|
self.command_info().command_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: WithCommandData> CommandInfo for T {
|
impl<T: WithCommandInfo> GetCommandInfo for T {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
&self.command_data().name
|
&self.command_info().name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
pub enum CommandResult {
|
pub enum CommandResult {
|
||||||
Continue,
|
Continue,
|
||||||
Done,
|
Done,
|
||||||
Cancel,
|
Cancel,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Command: WithCommandData {
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||||
fn init(&mut self);
|
pub enum CommandStatus {
|
||||||
fn step(&mut self) -> CommandResult;
|
Stopped,
|
||||||
fn finish(&mut self, result: CommandResult);
|
Running,
|
||||||
|
Ended,
|
||||||
|
Cancelling,
|
||||||
|
Cancelled,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GenericCommand<TConfig, TState> {
|
pub struct CommandContext<T>
|
||||||
command_data: CommandData,
|
|
||||||
pub config: TConfig,
|
|
||||||
pub state: TState,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<TConfig, TState> GenericCommand<TConfig, TState>
|
|
||||||
where
|
where
|
||||||
TConfig: 'static,
|
T: CommandImp,
|
||||||
GenericCommand<TConfig, TState>: Command,
|
|
||||||
TState: Default + 'static,
|
|
||||||
{
|
{
|
||||||
pub fn new(command_data: CommandData, config: TConfig) -> Self {
|
info: CommandInfo,
|
||||||
|
status: CommandStatus,
|
||||||
|
state: <T as CommandImp>::State,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: CommandImp> CommandContext<T> {
|
||||||
|
pub fn status(&self) -> CommandStatus {
|
||||||
|
self.status
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn state(&mut self) -> &mut T::State {
|
||||||
|
&mut self.state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: CommandImp> WithCommandInfo for CommandContext<T> {
|
||||||
|
fn command_info(&self) -> &CommandInfo {
|
||||||
|
&self.info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CommandImp {
|
||||||
|
type State: Default;
|
||||||
|
|
||||||
|
fn init(&self, ctx: &mut CommandContext<Self>)
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn step(&self, ctx: &mut CommandContext<Self>) -> CommandResult
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
fn finish(&self, ctx: &mut CommandContext<Self>)
|
||||||
|
where
|
||||||
|
Self: Sized;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Command: WithCommandInfo {
|
||||||
|
fn reset(&mut self);
|
||||||
|
fn status(&self) -> CommandStatus;
|
||||||
|
fn execute(&mut self) -> CommandStatus;
|
||||||
|
fn cancel(&mut self);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct GenericCommand<T: CommandImp> {
|
||||||
|
context: CommandContext<T>,
|
||||||
|
imp: T,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: CommandImp + 'static> GenericCommand<T> {
|
||||||
|
pub fn new(info: CommandInfo, imp: T) -> Self {
|
||||||
Self {
|
Self {
|
||||||
command_data,
|
context: CommandContext {
|
||||||
config,
|
info,
|
||||||
state: TState::default(),
|
status: CommandStatus::Stopped,
|
||||||
|
state: T::State::default(),
|
||||||
|
},
|
||||||
|
imp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_ref(command_data: CommandData, config: TConfig) -> CommandRef {
|
pub fn new_ref(info: CommandInfo, imp: T) -> CommandRef {
|
||||||
Rc::new(RefCell::new(Self::new(command_data, config)))
|
Rc::new(RefCell::new(Self::new(info, imp)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<TConfig, TState> WithCommandData for GenericCommand<TConfig, TState> {
|
impl<T: CommandImp> WithCommandInfo for GenericCommand<T> {
|
||||||
fn command_data(&self) -> &CommandData {
|
fn command_info(&self) -> &CommandInfo {
|
||||||
&self.command_data
|
&self.context.info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: CommandImp> Command for GenericCommand<T> {
|
||||||
|
fn status(&self) -> CommandStatus {
|
||||||
|
self.context.status
|
||||||
|
}
|
||||||
|
|
||||||
|
fn execute(&mut self) -> CommandStatus {
|
||||||
|
use self::CommandResult::*;
|
||||||
|
use self::CommandStatus::*;
|
||||||
|
let do_cancel = |me: &mut Self| {
|
||||||
|
me.context.status = Cancelling;
|
||||||
|
me.imp.finish(&mut me.context);
|
||||||
|
Cancelled
|
||||||
|
};
|
||||||
|
let do_step = |me: &mut Self| {
|
||||||
|
let result = me.imp.step(&mut me.context);
|
||||||
|
match result {
|
||||||
|
Continue => Running,
|
||||||
|
Done => {
|
||||||
|
me.imp.finish(&mut me.context);
|
||||||
|
Ended
|
||||||
|
}
|
||||||
|
Cancel => do_cancel(me),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let new_status = match self.status() {
|
||||||
|
Stopped => {
|
||||||
|
self.imp.init(&mut self.context);
|
||||||
|
do_step(self)
|
||||||
|
}
|
||||||
|
Running => do_step(self),
|
||||||
|
Ended => Ended,
|
||||||
|
Cancelling => do_cancel(self),
|
||||||
|
Cancelled => Cancelled,
|
||||||
|
};
|
||||||
|
self.context.status = new_status;
|
||||||
|
new_status
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&mut self) {
|
||||||
|
self.context.status = CommandStatus::Stopped;
|
||||||
|
}
|
||||||
|
fn cancel(&mut self) {
|
||||||
|
self.context.status = CommandStatus::Cancelling;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! command_impl {
|
macro_rules! command_impl {
|
||||||
(
|
(
|
||||||
$command:ident<$tconfig:ty,$tstate:ty>;
|
$command:ident<$tconfig:ty,$tstate:ty>;
|
||||||
$init_self:ident => $init:block;
|
$slf:ident, $ctx:ident => $init:block;
|
||||||
$step_self:ident => $step:block;
|
$step:block;
|
||||||
$finish_self:ident, $finish_result:ident => $finish:block
|
$finish:block
|
||||||
) => {
|
) => {
|
||||||
pub type $command = GenericCommand<$tconfig, $tstate>;
|
impl $crate::command::CommandImp for $tconfig {
|
||||||
|
type State = $tstate;
|
||||||
|
|
||||||
impl $crate::command::Command for $command {
|
fn init(&$slf, $ctx: &mut $crate::command::CommandContext<Self>) {
|
||||||
fn init(&mut $init_self) {
|
use $crate::command::GetCommandInfo;
|
||||||
use $crate::command::CommandInfo;
|
|
||||||
debug!(
|
debug!(
|
||||||
"{}({}) init",
|
"{}({}) init",
|
||||||
stringify!($command_st),
|
stringify!($command),
|
||||||
$init_self.name()
|
$ctx.name()
|
||||||
);
|
);
|
||||||
$init;
|
$init;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut $step_self) -> $crate::command::CommandResult {
|
fn step(&$slf, $ctx: &mut $crate::command::CommandContext<Self>) -> $crate::command::CommandResult {
|
||||||
use $crate::command::CommandInfo;
|
use $crate::command::GetCommandInfo;
|
||||||
debug!(
|
debug!(
|
||||||
"{}({}) step",
|
"{}({}) step",
|
||||||
stringify!($command_st),
|
stringify!($command),
|
||||||
$step_self.name()
|
$ctx.name()
|
||||||
);
|
);
|
||||||
$step
|
$step
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&mut $finish_self, $finish_result: $crate::command::CommandResult) {
|
fn finish(&$slf, $ctx: &mut $crate::command::CommandContext<Self>) {
|
||||||
use $crate::command::CommandInfo;
|
use $crate::command::GetCommandInfo;
|
||||||
debug!(
|
debug!(
|
||||||
"{}({}) finish({:?}",
|
"{}({}) finish({:?})",
|
||||||
stringify!($command_st),
|
stringify!($command),
|
||||||
$finish_self.name(),
|
$ctx.name(),
|
||||||
$finish_result,
|
$ctx.status(),
|
||||||
);
|
);
|
||||||
$finish;
|
$finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
pub type $command = $crate::command::GenericCommand<$tconfig>;
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
$command:ident<$tconfig:ty,$tstate:ty>;
|
$command:ident<$tconfig:ty,$tstate:ty>;
|
||||||
$init_self:ident => $init:block;
|
$slf:ident => $init:block;
|
||||||
$step_self:ident => $step:block;
|
$step:block;
|
||||||
$finish_self:ident => $finish:block
|
$finish:block
|
||||||
) => {
|
) => {
|
||||||
command_impl! { $command<$tconfig,$tstate>;
|
command_impl! { $command<$tconfig,$tstate>;
|
||||||
$init_self => $init; $step_self => $step; $finish_self, res => {} }
|
$init_self, cts => $init; $step; $finish }
|
||||||
};
|
};
|
||||||
(
|
(
|
||||||
$command:ident<$tconfig:ty>;
|
$command:ident<$tconfig:ty>;
|
||||||
$init_self:ident => $init:block
|
$slf:ident => $init:block
|
||||||
) => {
|
) => {
|
||||||
command_impl! { $command<$tconfig,()>;
|
command_impl! { $command<$tconfig,()>;
|
||||||
$init_self => $init; self => { $crate::command::CommandResult::Done }; self => {} }
|
$slf, ctx => $init; { $crate::command::CommandResult::Done }; {} }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,134 +267,84 @@ impl CommandGroupConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandGroupState {
|
pub struct CommandGroupState {
|
||||||
current_idx: Option<usize>,
|
current_idx: usize,
|
||||||
has_initialized: bool,
|
|
||||||
has_cancelled: bool,
|
has_cancelled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CommandGroupState {
|
impl Default for CommandGroupState {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
CommandGroupState {
|
CommandGroupState {
|
||||||
current_idx: None,
|
current_idx: 0,
|
||||||
has_initialized: false,
|
|
||||||
has_cancelled: false,
|
has_cancelled: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CommandGroup = GenericCommand<CommandGroupConfig, CommandGroupState>;
|
pub type CommandGroup = GenericCommand<CommandGroupConfig>;
|
||||||
|
|
||||||
impl Command for CommandGroup {
|
impl CommandImp for CommandGroupConfig {
|
||||||
fn init(&mut self) {
|
type State = CommandGroupState;
|
||||||
if self.state.current_idx.is_some() {
|
|
||||||
error!("CommandGroup init called twice");
|
fn init(&self, ctx: &mut CommandContext<Self>) {
|
||||||
}
|
*ctx.state() = Default::default();
|
||||||
self.state.current_idx = Some(0);
|
debug!("CommandGroup {} init", ctx.name());
|
||||||
self.state.has_initialized = false;
|
|
||||||
self.state.has_cancelled = false;
|
|
||||||
debug!("CommandGroup {} init", self.command_data().name());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn step(&mut self) -> CommandResult {
|
fn step(&self, ctx: &mut CommandContext<Self>) -> CommandResult {
|
||||||
use self::CommandResult::*;
|
use self::CommandResult::*;
|
||||||
let state = &mut self.state;
|
use self::CommandStatus::*;
|
||||||
let commands = &self.config.commands;
|
let state = ctx.state();
|
||||||
|
let commands = &self.commands;
|
||||||
if state.has_cancelled {
|
if state.has_cancelled {
|
||||||
debug!("CommandGroup step called after cancelled");
|
debug!("CommandGroup step called after cancelled");
|
||||||
return CommandResult::Cancel;
|
return CommandResult::Cancel;
|
||||||
}
|
}
|
||||||
let mut current_idx = if let Some(c) = state.current_idx {
|
let current_idx = &mut state.current_idx;
|
||||||
c
|
|
||||||
} else {
|
|
||||||
error!("CommandGroup step called before init");
|
|
||||||
state.has_cancelled = true;
|
|
||||||
return CommandResult::Cancel;
|
|
||||||
};
|
|
||||||
let mut result: CommandResult;
|
|
||||||
loop {
|
loop {
|
||||||
if current_idx >= commands.len() {
|
if *current_idx >= commands.len() {
|
||||||
debug!("CommandGroup out of commands");
|
debug!("CommandGroup out of commands");
|
||||||
return CommandResult::Done;
|
return CommandResult::Done;
|
||||||
}
|
}
|
||||||
let mut command = commands[current_idx].borrow_mut();
|
let mut command = commands[*current_idx].borrow_mut();
|
||||||
if !state.has_initialized {
|
let status = command.execute();
|
||||||
debug!(
|
match status {
|
||||||
"CommandGroup init {0} ({1})",
|
Ended => {
|
||||||
current_idx,
|
command.reset();
|
||||||
command.command_data().name()
|
*current_idx += 1;
|
||||||
);
|
|
||||||
command.init();
|
|
||||||
state.has_initialized = true;
|
|
||||||
}
|
|
||||||
result = command.step();
|
|
||||||
if result != Continue {
|
|
||||||
debug!(
|
|
||||||
"CommandGroup {2:?} {0} ({1}) ",
|
|
||||||
current_idx,
|
|
||||||
command.command_data().name(),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
command.finish(result)
|
|
||||||
}
|
|
||||||
match result {
|
|
||||||
Done => {
|
|
||||||
current_idx += 1;
|
|
||||||
state.has_initialized = false;
|
|
||||||
}
|
}
|
||||||
Cancel => {
|
Cancelled => {
|
||||||
|
command.reset();
|
||||||
state.has_cancelled = true;
|
state.has_cancelled = true;
|
||||||
break;
|
return Cancel;
|
||||||
|
}
|
||||||
|
Running => return Continue,
|
||||||
|
other => {
|
||||||
|
warn!("CommandGroup unhandled status {:?}", other);
|
||||||
|
return Continue;
|
||||||
}
|
}
|
||||||
_ => break,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.current_idx = Some(current_idx);
|
|
||||||
CommandResult::Continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&mut self, result: CommandResult) {
|
fn finish(&self, ctx: &mut CommandContext<Self>) {
|
||||||
let state = &mut self.state;
|
let commands = &self.commands;
|
||||||
let commands = &mut self.config.commands;
|
if ctx.status() == CommandStatus::Cancelling {
|
||||||
if result == CommandResult::Cancel {
|
if let Some(command) = commands.get(ctx.state().current_idx) {
|
||||||
if let Some(command) = state
|
let mut command = command.borrow_mut();
|
||||||
.current_idx
|
command.cancel();
|
||||||
.and_then(|current_idx| commands.get(current_idx))
|
command.execute();
|
||||||
{
|
|
||||||
command.borrow_mut().finish(result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.current_idx = None;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CommandRun {
|
pub struct CommandRun {
|
||||||
initialized: bool,
|
|
||||||
cancelled: bool,
|
|
||||||
command: CommandRef,
|
command: CommandRef,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommandId for CommandRun {
|
impl CommandId for CommandRun {
|
||||||
fn command_id(&self) -> u64 {
|
fn command_id(&self) -> u64 {
|
||||||
self.command.borrow().command_data().command_id()
|
self.command.borrow().command_info().command_id()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CommandRun {
|
|
||||||
pub fn initialized(&self) -> bool {
|
|
||||||
self.initialized
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cancelled(&self) -> bool {
|
|
||||||
self.cancelled
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cancel(&mut self) -> bool {
|
|
||||||
if self.cancelled {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
self.cancelled = true;
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,50 +388,28 @@ 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.borrow().command_data().command_id()) {
|
if self.is_running(command.borrow().command_info().command_id()) {
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
self.running_commands.push(CommandRun {
|
self.running_commands.push(CommandRun { command });
|
||||||
initialized: false,
|
|
||||||
cancelled: false,
|
|
||||||
command,
|
|
||||||
});
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cancel<T: CommandId>(&mut self, id: T) -> bool {
|
pub fn cancel<T: CommandId>(&mut self, id: T) -> bool {
|
||||||
self.get_command_run_mut(id).map_or(false, |command_run| {
|
self.get_command_run_mut(id).map_or(false, |command_run| {
|
||||||
command_run.cancelled = true;
|
command_run.command.borrow_mut().cancel();
|
||||||
true
|
true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn execute(&mut self) {
|
pub fn execute(&mut self) {
|
||||||
|
use self::CommandStatus::*;
|
||||||
self.running_commands.drain_filter(|command_run| {
|
self.running_commands.drain_filter(|command_run| {
|
||||||
let mut command = command_run.command.borrow_mut();
|
let mut command = command_run.command.borrow_mut();
|
||||||
if !command_run.initialized && !command_run.cancelled {
|
match command.execute() {
|
||||||
{
|
Ended | Cancelled => true,
|
||||||
let command_data = command.command_data();
|
Stopped | Running | Cancelling => false,
|
||||||
debug!(
|
|
||||||
"initialzing command {} (id {})",
|
|
||||||
command_data.name(),
|
|
||||||
command_data.command_id()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
command.init();
|
|
||||||
command_run.initialized = true;
|
|
||||||
}
|
|
||||||
let result = if command_run.initialized {
|
|
||||||
command.step()
|
|
||||||
} else {
|
|
||||||
CommandResult::Cancel
|
|
||||||
};
|
|
||||||
if result != CommandResult::Continue {
|
|
||||||
command.finish(result);
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
43
src/robot.rs
43
src/robot.rs
@ -3,13 +3,13 @@ use std::rc::Rc;
|
|||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use command::{CommandData, CommandGroup, CommandGroupConfig, CommandRef, CommandScheduler};
|
use command::{CommandGroup, CommandGroupConfig, CommandInfo, CommandRef, CommandScheduler};
|
||||||
use drive::{Drive, DriveRef};
|
use drive::{Drive, DriveRef};
|
||||||
|
|
||||||
mod cmds {
|
mod cmds {
|
||||||
use command::{Command, CommandResult, GenericCommand};
|
|
||||||
use drive::DriveRef;
|
|
||||||
use self::CommandResult::*;
|
use self::CommandResult::*;
|
||||||
|
use command::CommandResult;
|
||||||
|
use drive::DriveRef;
|
||||||
|
|
||||||
pub struct DriveCommandConfig {
|
pub struct DriveCommandConfig {
|
||||||
pub drive: DriveRef,
|
pub drive: DriveRef,
|
||||||
@ -25,28 +25,28 @@ mod cmds {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DriveCommand = GenericCommand<DriveCommandConfig, DriveCommandState>;
|
command_impl! (
|
||||||
|
DriveCommand<DriveCommandConfig, DriveCommandState>;
|
||||||
impl Command for DriveCommand {
|
self, ctx => {
|
||||||
fn init(&mut self) {
|
*ctx.state() = DriveCommandState::default();
|
||||||
self.state = DriveCommandState::default();
|
}; {
|
||||||
}
|
let state = ctx.state();
|
||||||
fn step(&mut self) -> CommandResult {
|
self.drive.borrow_mut().drive_powers(1.0, 1.0);
|
||||||
self.config.drive.borrow_mut().drive_powers(1.0, 1.0);
|
state.iterations += 1;
|
||||||
self.state.iterations += 1;
|
if state.iterations >= 10 {
|
||||||
if self.state.iterations >= 10 {
|
|
||||||
Done
|
Done
|
||||||
} else {
|
} else {
|
||||||
Continue
|
Continue
|
||||||
}
|
}
|
||||||
|
}; {
|
||||||
|
self.drive.borrow_mut().drive_powers(0.0, 0.0);
|
||||||
}
|
}
|
||||||
fn finish(&mut self, res: CommandResult) {
|
);
|
||||||
self.config.drive.borrow_mut().drive_powers(0.0, 0.0);
|
|
||||||
}
|
pub struct LogCommandConfig;
|
||||||
}
|
|
||||||
|
|
||||||
command_impl! {
|
command_impl! {
|
||||||
LogCmd<()>; self => { info!("{}", "LogCmd") }
|
LogCmd<LogCommandConfig>; self => { info!("{}", "LogCmd") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,14 +69,15 @@ impl Robot {
|
|||||||
warn!("Starting RobotRS");
|
warn!("Starting RobotRS");
|
||||||
|
|
||||||
let command = cmds::DriveCommand::new_ref(
|
let command = cmds::DriveCommand::new_ref(
|
||||||
CommandData::new(0, "DriveCommand"),
|
CommandInfo::new(0, "DriveCommand"),
|
||||||
cmds::DriveCommandConfig {
|
cmds::DriveCommandConfig {
|
||||||
drive: self.drive.clone(),
|
drive: self.drive.clone(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let log_command = cmds::LogCmd::new_ref(CommandData::new(2, "LogCommand"), ());
|
let log_command =
|
||||||
|
cmds::LogCmd::new_ref(CommandInfo::new(2, "LogCommand"), cmds::LogCommandConfig);
|
||||||
let command_group = CommandGroup::new(
|
let command_group = CommandGroup::new(
|
||||||
CommandData::new(1, "Group"),
|
CommandInfo::new(1, "Group"),
|
||||||
CommandGroupConfig::new(vec![command, log_command]),
|
CommandGroupConfig::new(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