use std::{ sync::Arc, time::{Duration, SystemTime}, }; use arci::{ gamepad::GamepadEvent, BaseVelocity, DummyGamepad, DummyJointTrajectoryClient, DummyLocalization, DummyMoveBase, DummyNavigation, DummySpeaker, DummyTransformResolver, Gamepad, Isometry2, JointTrajectoryClient, Localization, MoveBase, Navigation, Speaker, TrajectoryPoint, TransformResolver, Vector2, }; use assert_approx_eq::assert_approx_eq; use openrr_plugin::{ GamepadProxy, JointTrajectoryClientProxy, LocalizationProxy, MoveBaseProxy, NavigationProxy, SpeakerProxy, TransformResolverProxy, }; #[tokio::test] async fn joint_trajectory_client() { let client = Arc::new(DummyJointTrajectoryClient::new(vec![ "a".to_owned(), "b".to_owned(), ])); let proxy = JointTrajectoryClientProxy::new(client.clone()); assert_eq!(proxy.joint_names(), vec!["a", "b"]); let pos = client.current_joint_positions().unwrap(); assert_eq!(pos.len(), 2); assert_approx_eq!(pos[0], 0.0); assert_approx_eq!(pos[1], 0.0); let pos = proxy.current_joint_positions().unwrap(); assert_eq!(pos.len(), 2); assert_approx_eq!(pos[0], 0.0); assert_approx_eq!(pos[1], 0.0); proxy .send_joint_positions(vec![1.0, 2.0], Duration::from_secs(1)) .unwrap() .await .unwrap(); let pos2 = client.current_joint_positions().unwrap(); assert_eq!(pos2.len(), 2); assert_approx_eq!(pos2[0], 1.0); assert_approx_eq!(pos2[1], 2.0); let pos2 = proxy.current_joint_positions().unwrap(); assert_eq!(pos2.len(), 2); assert_approx_eq!(pos2[0], 1.0); assert_approx_eq!(pos2[1], 2.0); proxy .send_joint_trajectory(vec![ TrajectoryPoint::new(vec![1.0, -1.0], Duration::from_secs(1)), TrajectoryPoint::new(vec![2.0, -3.0], Duration::from_secs(2)), ]) .unwrap() .await .unwrap(); assert_eq!(client.last_trajectory.lock().len(), 2); let pos = client.current_joint_positions().unwrap(); assert_eq!(pos.len(), 2); assert_approx_eq!(pos[0], 2.0); assert_approx_eq!(pos[1], -3.0); let pos = proxy.current_joint_positions().unwrap(); assert_eq!(pos.len(), 2); assert_approx_eq!(pos[0], 2.0); assert_approx_eq!(pos[1], -3.0); } #[tokio::test] async fn speaker() { let speaker = Arc::new(DummySpeaker::new()); let proxy = SpeakerProxy::new(speaker.clone()); assert_eq!(speaker.current_message(), ""); proxy.speak("abc").unwrap().await.unwrap(); assert_eq!(speaker.current_message(), "abc"); } #[tokio::test] async fn move_base() { let base = Arc::new(DummyMoveBase::new()); let proxy = MoveBaseProxy::new(base.clone()); let vel1 = base.current_velocity().unwrap(); assert_approx_eq!(vel1.x, 0.0); assert_approx_eq!(vel1.y, 0.0); assert_approx_eq!(vel1.theta, 0.0); let vel1 = proxy.current_velocity().unwrap(); assert_approx_eq!(vel1.x, 0.0); assert_approx_eq!(vel1.y, 0.0); assert_approx_eq!(vel1.theta, 0.0); proxy .send_velocity(&BaseVelocity::new(0.1, 0.2, -3.0)) .unwrap(); let vel2 = base.current_velocity().unwrap(); assert_approx_eq!(vel2.x, 0.1); assert_approx_eq!(vel2.y, 0.2); assert_approx_eq!(vel2.theta, -3.0); let vel2 = proxy.current_velocity().unwrap(); assert_approx_eq!(vel2.x, 0.1); assert_approx_eq!(vel2.y, 0.2); assert_approx_eq!(vel2.theta, -3.0); } #[tokio::test] async fn navigation() { let nav = Arc::new(DummyNavigation::new()); let proxy = NavigationProxy::new(nav.clone()); proxy .send_goal_pose( Isometry2::new(Vector2::new(1.0, 2.0), 3.0), "", Duration::default(), ) .unwrap() .await .unwrap(); let pose = nav.current_goal_pose().unwrap(); assert_approx_eq!(pose.translation.x, 1.0); assert_approx_eq!(pose.translation.y, 2.0); assert_approx_eq!(pose.rotation.angle(), 3.0); proxy.cancel().unwrap(); assert!(nav.is_canceled()); } #[tokio::test] async fn localization() { let loc = Arc::new(DummyLocalization::new()); let proxy = LocalizationProxy::new(loc); let pose = proxy.current_pose("").unwrap(); assert_eq!(pose, pose.inverse()); // only identity mapping satisfies this } #[tokio::test] async fn transform_resolver() { let resolver = Arc::new(DummyTransformResolver::default()); let proxy = TransformResolverProxy::new(resolver); let transformation = proxy .resolve_transformation("", "", SystemTime::UNIX_EPOCH) .unwrap(); assert_eq!(transformation, transformation.inverse()) } #[tokio::test] async fn gamepad() { let gamepad = Arc::new(DummyGamepad::with_all_events()); let proxy = GamepadProxy::new(gamepad.clone()); for expected in &gamepad.events { match (expected, proxy.next_event().await) { (GamepadEvent::ButtonPressed(expected), GamepadEvent::ButtonPressed(actual)) => { assert_eq!(*expected, actual); } (GamepadEvent::ButtonReleased(expected), GamepadEvent::ButtonReleased(actual)) => { assert_eq!(*expected, actual); } ( GamepadEvent::AxisChanged(expected_axis, expected_val), GamepadEvent::AxisChanged(actual_axis, actual_val), ) => { assert_eq!(*expected_axis, actual_axis); assert_approx_eq!(*expected_val, actual_val); } (GamepadEvent::Unknown, GamepadEvent::Unknown) => {} (expected, actual) => { panic!("event mismatch, expected: {expected:?}, actual: {actual:?}") } } } proxy.stop(); assert!(gamepad.is_stopped()); }