airsim_client/clients/car_client.rs
1use async_std::net::ToSocketAddrs;
2use msgpack_rpc::Utf8String;
3use rmpv::Value;
4
5use crate::error::NetworkResult;
6
7use super::airsim_client::AirsimClient;
8
9pub struct CarClient {
10 airsim_client: AirsimClient,
11 vehicle_name: &'static str,
12}
13
14impl CarClient {
15 pub async fn connect(addrs: impl ToSocketAddrs, vehicle_name: &'static str) -> NetworkResult<Self> {
16 let airsim_client = AirsimClient::connect(addrs, vehicle_name).await?;
17 Ok(Self {
18 airsim_client,
19 vehicle_name,
20 })
21 }
22
23 /// Reset the vehicle to its original starting state
24 ///
25 /// Note that you must call `enable_ap, Some(vehicle_name)i_control` and `arm_disarm` again after the call to reset
26 #[inline(always)]
27 pub async fn reset(&self) -> NetworkResult<bool> {
28 self.airsim_client.reset().await
29 }
30
31 /// If connection is established then this call will return `True` otherwise
32 /// the request will be blocked until timeout (default value)
33 #[inline(always)]
34 pub async fn ping(&self) -> NetworkResult<bool> {
35 self.airsim_client.ping().await
36 }
37
38 #[inline(always)]
39 pub async fn confirm_connection(&self) -> NetworkResult<bool> {
40 self.airsim_client.confirm_connection().await
41 }
42
43 /// Enables or disables API control for vehicle corresponding to vehicle_name
44 ///
45 /// args:
46 /// is_enabled (bool): True to enable, False to disable API control
47 /// vehicle_name (Option<String>): Name of the vehicle to send this command to
48 #[inline(always)]
49 pub async fn enable_api_control(&self, is_enabled: bool) -> NetworkResult<bool> {
50 self.airsim_client
51 .enable_api_control(is_enabled, Some(self.vehicle_name))
52 .await
53 }
54
55 /// Returns true if API control is established.
56 ///
57 /// If false (which is default) then API calls would be ignored. After a successful call
58 /// to `enableApiControl`, `isApiControlEnabled` should return true.
59 ///
60 /// args:
61 /// vehicle_name (Option<String>): Name of the vehicle to send this command to
62 #[inline(always)]
63 pub async fn is_api_control_enabled(&self, is_enabled: bool) -> NetworkResult<bool> {
64 self.airsim_client
65 .is_api_control_enabled(is_enabled, Some(self.vehicle_name))
66 .await
67 }
68
69 /// Returns true if API control is established.
70 ///
71 /// If false (which is default) then API calls would be ignored. After a successful call
72 /// to `enableApiControl`, `isApiControlEnabled` should return true.
73 ///
74 /// args:
75 /// arm (bool): True to arm, False to disarm the vehicle
76 /// vehicle_name (Option<String>): Name of the vehicle to send this command to
77 #[inline(always)]
78 pub async fn arm_disarm(&self, arm: bool) -> NetworkResult<bool> {
79 self.airsim_client.arm_disarm(arm, Some(self.vehicle_name)).await
80 }
81
82 /// Takeoff vehicle to 3m above ground. Vehicle should not be moving when this API is used
83 ///
84 /// Args:
85 /// timeout_sec (Option<u64>): Timeout for the vehicle to reach desired altitude
86 /// vehicle_name (Option<String>): Name of the vehicle to send this command to
87 pub async fn take_off_async(&self, timeout_sec: u64) -> NetworkResult<bool> {
88 let vehicle_name: Utf8String = self.vehicle_name.into();
89
90 self.airsim_client
91 .unary_rpc(
92 "takeoff".into(),
93 Some(vec![Value::Integer(timeout_sec.into()), Value::String(vehicle_name)]),
94 )
95 .await
96 .map(|response| response.result.is_ok() && response.result.unwrap().as_bool() == Some(true))
97 }
98}