Skip to content

Commit eceda80

Browse files
authored
Merge pull request ros2-rust#3 from fmrico/fix_change_state
Fix change state
2 parents 15d51b5 + 16bf636 commit eceda80

File tree

4 files changed

+121
-19
lines changed

4 files changed

+121
-19
lines changed

rclrs/src/lifecycle_node.rs

Lines changed: 98 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,44 @@ impl LifecycleNode {
142142
/// See [`LifecycleNodeBuilder::new()`] for documentation.
143143
#[allow(clippy::new_ret_no_self)]
144144
pub fn new(context: &Context, node_name: &str) -> Result<LifecycleNode, Box<dyn Error>> {
145-
Self::builder(context, node_name).build()
145+
146+
let mut node = Self::builder(context, node_name);
147+
148+
// `Activating` transition callback
149+
let on_activate_cb = |_: &State| Transition::TRANSITION_CALLBACK_SUCCESS;
150+
let on_activate: LifecycleCallback = Box::new(on_activate_cb);
151+
152+
// `Cleanup` transition callback
153+
let on_cleanup_cb = |_: &State| Transition::TRANSITION_CALLBACK_SUCCESS;
154+
let on_cleanup: LifecycleCallback = Box::new(on_cleanup_cb);
155+
156+
// `Configuring` transition callback
157+
let on_configure_cb = |_: &State| Transition::TRANSITION_CALLBACK_SUCCESS;
158+
let on_configure: LifecycleCallback = Box::new(on_configure_cb);
159+
160+
// `Deactivate` transition callback
161+
let on_deactivate_cb = |_: &State| Transition::TRANSITION_CALLBACK_SUCCESS;
162+
let on_deactivate: LifecycleCallback = Box::new(on_deactivate_cb);
163+
164+
// Error handling callback
165+
let on_error_cb = |_: &State| Transition::TRANSITION_CALLBACK_SUCCESS;
166+
let on_error: LifecycleCallback = Box::new(on_error_cb);
167+
168+
// `Shutdown` transition callback
169+
let on_shutdown_cb = |_: &State| Transition::TRANSITION_CALLBACK_SUCCESS;
170+
let on_shutdown: LifecycleCallback = Box::new(on_shutdown_cb);
171+
172+
node.on_activate = Some(on_activate);
173+
node.on_cleanup = Some(on_cleanup);
174+
node.on_configure = Some(on_configure);
175+
node.on_deactivate = Some(on_deactivate);
176+
node.on_error = Some(on_error);
177+
node.on_shutdown = Some(on_shutdown);
178+
179+
node.enable_communication_interface = true;
180+
181+
// Build node
182+
node.build()
146183
}
147184

148185
/// Returns the name of the lifecycle node.
@@ -157,7 +194,7 @@ impl LifecycleNode {
157194
///
158195
/// This returns the namespace after remapping, so it is not necessarily the same as the
159196
/// namespace that was used when creating the lifecycle node.
160-
pub fn namepsace(&self) -> String {
197+
pub fn namespace(&self) -> String {
161198
self.call_string_getter(rcl_node_get_namespace)
162199
}
163200

@@ -393,6 +430,53 @@ mod tests {
393430
// const NODE_GET_AVAILABLE_TRANSITIONS_TOPIC: &str = "/lc_talker/get_available_transitions";
394431
// const NODE_GET_TRANSITION_GRAPH_TOPIC: &str = "/lc_talker/get_transition_graph";
395432

433+
434+
#[test]
435+
fn empty_initializer() {
436+
let context = Context::new(vec![]).unwrap();
437+
let mut test_node = LifecycleNode::new(&context, "testnode").unwrap();
438+
439+
assert_eq!(test_node.name(), "testnode");
440+
assert_eq!(test_node.namespace(), "/");
441+
assert_eq!(test_node.fully_qualified_name(), "/testnode");
442+
}
443+
444+
#[test]
445+
fn trigger_transition() {
446+
let context = Context::new(vec![]).unwrap();
447+
let mut test_node = LifecycleNode::new(&context, "testnode").unwrap();
448+
449+
assert_eq!(
450+
lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED,
451+
test_node.state_machine.get_current_state().unwrap().id());
452+
453+
assert_eq!(
454+
lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE,
455+
test_node.state_machine.change_state(Transition::TRANSITION_CONFIGURE)
456+
.unwrap().id());
457+
458+
assert_eq!(
459+
lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE,
460+
test_node.state_machine.change_state(Transition::TRANSITION_ACTIVATE)
461+
.unwrap().id());
462+
463+
assert_eq!(
464+
lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE,
465+
test_node.state_machine.change_state(Transition::TRANSITION_DEACTIVATE)
466+
.unwrap().id());
467+
468+
assert_eq!(
469+
lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED,
470+
test_node.state_machine.change_state(Transition::TRANSITION_CLEANUP)
471+
.unwrap().id());
472+
473+
assert_eq!(
474+
lifecycle_msgs::msg::State::PRIMARY_STATE_FINALIZED,
475+
test_node.state_machine.change_state(Transition::TRANSITION_UNCONFIGURED_SHUTDOWN)
476+
.unwrap().id());
477+
}
478+
479+
396480
#[test]
397481
fn lifecycle_node_is_send_and_sync() {
398482
assert_send::<LifecycleNode>();
@@ -419,7 +503,7 @@ mod tests {
419503
// TODO(jhassold): Create tests to see if lifecycle node responds appropriately to messages for each type of state.
420504

421505
#[test]
422-
fn test_trigger_transition() {
506+
fn trigger_transition_built() {
423507
let context = Context::new(vec![]).unwrap();
424508
let mut test_node_builder = LifecycleNode::builder(&context, "test_node");
425509

@@ -457,12 +541,17 @@ mod tests {
457541
test_node_builder.enable_communication_interface = true;
458542

459543
let test_node = test_node_builder.build().unwrap();
460-
println!("{:?}", test_node);
461-
assert_eq!(Transition::TRANSITION_CALLBACK_SUCCESS, test_node.state_machine.change_state(Transition::TRANSITION_CONFIGURE).unwrap());
544+
assert_eq!(
545+
lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE,
546+
test_node.state_machine.change_state(Transition::TRANSITION_CONFIGURE).unwrap().id());
462547
let q = test_node.state_machine.get_current_state().unwrap();
463-
println!("{:?}", q);
464-
// assert_eq!(lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE, test_node.state_machine.change_state(Transition::TRANSITION_ACTIVATE).unwrap());
465-
// assert_eq!(lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE, test_node.state_machine.change_state(Transition::TRANSITION_DEACTIVATE).unwrap());
466-
// assert_eq!(lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED, test_node.state_machine.change_state(Transition::TRANSITION_CLEANUP).unwrap());
548+
assert_eq!(
549+
lifecycle_msgs::msg::State::PRIMARY_STATE_ACTIVE,
550+
test_node.state_machine.change_state(Transition::TRANSITION_ACTIVATE).unwrap().id());
551+
assert_eq!(
552+
lifecycle_msgs::msg::State::PRIMARY_STATE_INACTIVE,
553+
test_node.state_machine.change_state(Transition::TRANSITION_DEACTIVATE).unwrap().id());
554+
assert_eq!(lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED,
555+
test_node.state_machine.change_state(Transition::TRANSITION_CLEANUP).unwrap().id());
467556
}
468557
}

rclrs/src/lifecycle_node/state.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub struct State {
2727
label: String,
2828
allocator: rcutils_allocator_t,
2929
state_handle: Arc<Mutex<*mut rcl_lifecycle_state_t>>,
30+
from_raw: bool,
3031
}
3132

3233
impl Drop for State {
@@ -73,6 +74,7 @@ impl State {
7374
label: state_label.to_string_lossy().to_string(),
7475
allocator,
7576
state_handle: Arc::new(Mutex::new(state_handle)),
77+
from_raw: false,
7678
})
7779
}
7880
}
@@ -90,6 +92,7 @@ impl State {
9092
label: label.to_string_lossy().to_string(),
9193
allocator,
9294
state_handle: Arc::new(Mutex::new(rcl_lifecycle_state_handle)),
95+
from_raw: true,
9396
}
9497
}
9598

@@ -108,9 +111,11 @@ impl State {
108111
return Ok(());
109112
}
110113

111-
// SAFETY: By this point, we should have confirmed that state_handle still exists
112-
unsafe {
113-
rcl_lifecycle_state_fini(state_handle.as_mut().unwrap(), &self.allocator).ok()?;
114+
if !self.from_raw {
115+
// SAFETY: By this point, we should have confirmed that state_handle still exists
116+
unsafe {
117+
rcl_lifecycle_state_fini(state_handle.as_mut().unwrap(), &self.allocator).ok()?;
118+
}
114119
}
115120

116121
Ok(())

rclrs/src/lifecycle_node/state_machine.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ impl LifecycleMachine {
8989
};
9090

9191
let ret = self.change_state(transition_id).unwrap();
92-
resp.success = ret == lifecycle_msgs::msg::Transition::TRANSITION_CALLBACK_SUCCESS;
92+
resp.success = ret.id() == lifecycle_msgs::msg::State::PRIMARY_STATE_UNCONFIGURED;
9393

9494
resp
9595
}
@@ -403,7 +403,7 @@ impl LifecycleMachine {
403403
}
404404
}
405405

406-
pub(crate) fn change_state(&self, transition_id: u8) -> Result<u8, RclrsError> {
406+
pub(crate) fn change_state(&self, transition_id: u8) -> Result<State, RclrsError> {
407407
// Make sure that the state machine is initialized before doing anything
408408
let mut state_machine = self.state_machine.lock().unwrap();
409409
// SAFETY: No preconditions for this function
@@ -446,7 +446,10 @@ impl LifecycleMachine {
446446
.ok()?
447447
};
448448

449-
Ok(cb_return_code)
449+
let current_state =
450+
unsafe { State::from_raw(state_machine.current_state as *mut rcl_lifecycle_state_s) };
451+
452+
Ok(current_state)
450453
}
451454

452455
fn execute_callback(&self, cb_id: u8, previous_state: &State) -> u8 {

rclrs/src/lifecycle_node/transition.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub struct Transition {
3131
goal: Option<State>,
3232
allocator: rcutils_allocator_t,
3333
transition_handle: Arc<Mutex<*mut rcl_lifecycle_transition_t>>,
34+
from_raw: bool,
3435
}
3536

3637
impl Drop for Transition {
@@ -87,6 +88,7 @@ impl Transition {
8788
goal: None,
8889
allocator,
8990
transition_handle: Arc::new(Mutex::new(transition_handle)),
91+
from_raw: false,
9092
})
9193
}
9294
}
@@ -134,6 +136,7 @@ impl Transition {
134136
goal,
135137
allocator,
136138
transition_handle: Arc::new(Mutex::new(rcl_lifecycle_transition_handle)),
139+
from_raw: true,
137140
}
138141
}
139142

@@ -160,10 +163,12 @@ impl Transition {
160163
return Ok(());
161164
}
162165

163-
// SAFETY: By this point, we should have confirmed that transition_handle still exists
164-
unsafe {
165-
rcl_lifecycle_transition_fini(transition_handle.as_mut().unwrap(), &self.allocator)
166-
.ok()?;
166+
if !self.from_raw {
167+
// SAFETY: By this point, we should have confirmed that transition_handle still exists
168+
unsafe {
169+
rcl_lifecycle_transition_fini(transition_handle.as_mut().unwrap(), &self.allocator)
170+
.ok()?;
171+
}
167172
}
168173

169174
Ok(())

0 commit comments

Comments
 (0)