Skip to content

Commit

Permalink
RSDK-3833 Dial takes type and payload as parameters (viamrobotics#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
jckras committed Jul 10, 2023
1 parent 67bec6b commit 94001b6
Show file tree
Hide file tree
Showing 10 changed files with 380 additions and 351 deletions.
2 changes: 1 addition & 1 deletion examples/src/ffi/cpp/ffi_echo.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ using proto::rpc::examples::echo::v1::EchoService;
extern "C" void *init_rust_runtime();
extern "C" int free_rust_runtime(void *ptr);
extern "C" void free_string(char* s);
extern "C" char *dial(const char *uri, const char *payload,
extern "C" char *dial(const char *uri, const char *type, const char *payload,
bool allow_insecure, void *ptr);

class EchoServiceClient {
Expand Down
4 changes: 2 additions & 2 deletions examples/src/ffi/cpp/ffi_robot.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ using viam::robot::v1::ResourceNamesResponse;
extern "C" void *init_rust_runtime();
extern "C" int free_rust_runtime(void *ptr);
extern "C" void free_string(char* s);
extern "C" char *dial(const char *uri, const char *payload,
extern "C" char *dial(const char *uri, const char *type, const char *payload,
bool allow_insecure, void *ptr);

class RobotServiceClient {
Expand Down Expand Up @@ -51,7 +51,7 @@ class RobotServiceClient {
int main(int argc, char *argv[]) {

void *ptr = init_rust_runtime();
char *path = dial("<your robot's uri>", "<your robot's credentials>", false, ptr);
char *path = dial("<your robot's uri>", "<your authentication type>", "<your authentication payload>", false, ptr);
if(path == NULL){
free_rust_runtime(ptr);
return 1;
Expand Down
60 changes: 37 additions & 23 deletions src/ffi/dial_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,12 @@ fn dial_without_cred(

fn dial_with_cred(
uri: String,
r#type: &str,
payload: &str,
allow_insec: bool,
disable_webrtc: bool,
) -> Result<DialBuilder<WithCredentials>> {
let creds = RPCCredentials::new(
None,
String::from("robot-location-secret"),
String::from(payload),
);
let creds = RPCCredentials::new(None, String::from(r#type), String::from(payload));
let c = DialOptions::builder().uri(&uri).with_credentials(creds);
let c = if disable_webrtc {
c.disable_webrtc()
Expand All @@ -113,12 +110,14 @@ fn dial_with_cred(
/// When falling to dial it will return a NULL pointer
/// # Arguments
/// * `c_uri` a C-style string representing the address of robot you want to connect to
/// * `c_type` a C-style string representing the type of robot's secret you want to use, set to NULL if you don't need authentication
/// * `c_payload` a C-style string that is the robot's secret, set to NULL if you don't need authentication
/// * `c_allow_insecure` a bool, set to true when allowing insecure connection to your robot
/// * `rt_ptr` a pointer to a rust runtime previously obtained with init_rust_runtime
#[no_mangle]
pub unsafe extern "C" fn dial(
c_uri: *const c_char,
c_type: *const c_char,
c_payload: *const c_char,
c_allow_insec: bool,
rt_ptr: Option<&mut DialFfi>,
Expand All @@ -130,19 +129,13 @@ pub unsafe extern "C" fn dial(
let ur = match Uri::from_maybe_shared(CStr::from_ptr(c_uri).to_bytes()) {
Ok(ur) => ur,
Err(e) => {
println!("Sorry {e:?} is not a valid URI");
log::error!("Sorry {e:?} is not a valid URI");
return ptr::null_mut();
}
};
ur
};
let allow_insec = c_allow_insec;
let payload = {
match c_payload.is_null() {
true => None,
false => Some(CStr::from_ptr(c_payload)),
}
};
let ctx = match rt_ptr {
Some(rt) => rt,
None => {
Expand All @@ -158,38 +151,59 @@ pub unsafe extern "C" fn dial(
let conn = match runtime.block_on(async { proxy::uds::UDSConnector::new_random() }) {
Ok(conn) => conn,
Err(e) => {
println!("Error creating the UDS proxy {e:?}");
log::error!("Error creating the UDS proxy {e:?}");
return ptr::null_mut();
}
};
let path = match CString::new(conn.get_path()) {
Ok(s) => s,
Err(e) => {
println!("Error getting the path {e:?}");
log::error!("Error getting the path {e:?}");
return ptr::null_mut();
}
};
let (tx, rx) = oneshot::channel::<()>();
let uri_str = uri.to_string();

// if the uri is local then we can connect directly.
let disable_webrtc;
if let Some(host) = uri.host() {
disable_webrtc = host.contains(".local") || host.contains("localhost");
} else {
disable_webrtc = uri_str.contains(".local") || uri_str.contains("localhost");
}
let r#type = {
match c_type.is_null() {
true => None,
false => Some(CStr::from_ptr(c_type)),
}
};
let payload = {
match c_payload.is_null() {
true => None,
false => Some(CStr::from_ptr(c_payload)),
}
};
let (server, channel) = match runtime.block_on(async move {
let channel = match payload {
Some(p) => {
dial_with_cred(uri_str, p.to_str()?, allow_insec, disable_webrtc)?
.connect()
.await?
let channel = match (r#type, payload) {
(Some(t), Some(p)) => {
dial_with_cred(
uri_str,
t.to_str()?,
p.to_str()?,
allow_insec,
disable_webrtc,
)?
.connect()
.await
}
None => {
(None, None) => {
let c = dial_without_cred(uri_str, allow_insec, disable_webrtc)?;
c.connect().await?
c.connect().await
}
};
(None, Some(_)) => Err(anyhow::anyhow!("Error missing credential: type")),
(Some(_), None) => Err(anyhow::anyhow!("Error missing credential: payload")),
}?;
let dial = channel.clone();
let g = GRPCProxy::new(dial, uri);
let service = ServiceBuilder::new()
Expand All @@ -211,7 +225,7 @@ pub unsafe extern "C" fn dial(
}) {
Ok(s) => s,
Err(e) => {
println!("Error building GRPC proxy reason : {e:?}");
log::error!("Error building GRPC proxy reason : {e:?}");
return ptr::null_mut();
}
};
Expand Down
24 changes: 12 additions & 12 deletions src/ffi/spatialmath/axis_angle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ffi_helpers::null_pointer_check;
use nalgebra::{Quaternion};
use nalgebra::Quaternion;

use crate::spatialmath::utils::AxisAngle;

Expand All @@ -15,10 +15,10 @@ fn to_raw_pointer(aa: &AxisAngle) -> *mut AxisAngle {
}

/// Free memory at the address of the axis angle pointer.
///
///
/// # Safety
///
/// Outer processes that work with axis angles via the FFI interface MUST remember
///
/// Outer processes that work with axis angles via the FFI interface MUST remember
/// to call this function when finished with an axis angle instance
#[no_mangle]
pub unsafe extern "C" fn free_axis_angles_memory(ptr: *mut AxisAngle) {
Expand All @@ -30,11 +30,11 @@ pub unsafe extern "C" fn free_axis_angles_memory(ptr: *mut AxisAngle) {

/// Initialize axis angle from raw components and retrieve the C pointer
/// to its address.
///
///
/// # Safety
///
///
/// When finished with the underlying axis angle initialized by this function
/// the caller must remember to free the axis angle memory using the
/// the caller must remember to free the axis angle memory using the
/// free_axis_angles_memory FFI function
#[no_mangle]
pub extern "C" fn new_axis_angle(x: f64, y: f64, z: f64, theta: f64) -> *mut AxisAngle {
Expand All @@ -46,21 +46,21 @@ pub extern "C" fn new_axis_angle(x: f64, y: f64, z: f64, theta: f64) -> *mut Axi
/// and theta is the rotation about the axis in radians. A zero quaternion returns
/// a zero axis angle. In the event of an error from the nalgebra crate, a zero
/// axis angle is also returned.
///
///
/// # Safety
///
///
/// When finished with the underlying quaternion passed to this function
/// the caller must remember to free the quaternion memory using the
/// the caller must remember to free the quaternion memory using the
/// free_quaternion_memory FFI function and the axis angle memory using
/// the free_array_memory function
#[no_mangle]
pub unsafe extern "C" fn axis_angle_from_quaternion(
quat: *const Quaternion<f64>
quat: *const Quaternion<f64>,
) -> *mut AxisAngle {
null_pointer_check!(quat);
let axis_angle = match (*quat).try_into() {
Ok(aa) => aa,
Err(_err) => AxisAngle::new(0.0, 0.0, 0.0, 0.0)
Err(_err) => AxisAngle::new(0.0, 0.0, 0.0, 0.0),
};
to_raw_pointer(&axis_angle)
}
32 changes: 17 additions & 15 deletions src/ffi/spatialmath/euler_angles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use nalgebra::Quaternion;
use crate::spatialmath::utils::EulerAngles;

/// The FFI interface for initializing euler angles. Our euler angles
/// follow the Tait-Bryan formalism and are applied in the Z-Y'-X" order
/// follow the Tait-Bryan formalism and are applied in the Z-Y'-X" order
/// (where Z -> yaw, Y -> pitch, X -> roll).
///
///
/// It is highly recommended not to attempt any mathematics with the euler
/// angles directly and to convert to quaternions via the FFI interface instead

Expand All @@ -16,11 +16,11 @@ fn to_raw_pointer(ea: &EulerAngles) -> *mut EulerAngles {
Box::into_raw(Box::new(*ea))
}

/// Free memory at the address of the euler angles pointer.
///
/// Free memory at the address of the euler angles pointer.
///
/// # Safety
///
/// Outer processes that work with EulerAngles via the FFI interface MUST remember
///
/// Outer processes that work with EulerAngles via the FFI interface MUST remember
/// to call this function when finished with a euler angles instance
#[no_mangle]
pub unsafe extern "C" fn free_euler_angles_memory(ptr: *mut EulerAngles) {
Expand All @@ -32,29 +32,31 @@ pub unsafe extern "C" fn free_euler_angles_memory(ptr: *mut EulerAngles) {

/// Initialize euler angles from raw components and retrieve the C pointer
/// to its address.
///
///
/// # Safety
///
///
/// When finished with the underlying euler angles initialized by this function
/// the caller must remember to free the euler angles memory using the
/// the caller must remember to free the euler angles memory using the
/// free_euler_angles_memory FFI function
#[no_mangle]
pub extern "C" fn new_euler_angles(roll: f64, pitch: f64, yaw: f64) -> *mut EulerAngles {
to_raw_pointer(&EulerAngles::new(roll, pitch, yaw))
}

/// Converts a quaternion into euler angles (in radians). The euler angles are
/// represented according to the Tait-Bryan formalism and applied
/// Converts a quaternion into euler angles (in radians). The euler angles are
/// represented according to the Tait-Bryan formalism and applied
/// in the Z-Y'-X" order (where Z -> yaw, Y -> pitch, X -> roll).
///
///
/// # Safety
///
///
/// When finished with the underlying quaternion passed to this function
/// the caller must remember to free the quaternion memory using the
/// the caller must remember to free the quaternion memory using the
/// free_quaternion_memory FFI function and the euler angles memory using
/// the free_euler_angles_memory function
#[no_mangle]
pub unsafe extern "C" fn euler_angles_from_quaternion(quat_ptr: *const Quaternion<f64>) -> *mut EulerAngles {
pub unsafe extern "C" fn euler_angles_from_quaternion(
quat_ptr: *const Quaternion<f64>,
) -> *mut EulerAngles {
null_pointer_check!(quat_ptr);
let euler_angles: EulerAngles = (*quat_ptr).into();
to_raw_pointer(&euler_angles)
Expand Down
2 changes: 1 addition & 1 deletion src/ffi/spatialmath/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
pub mod axis_angle;
pub mod euler_angles;
pub mod orientation_vector;
pub mod rotation_matrix;
pub mod quaternion;
pub mod rotation_matrix;
pub mod vector3;
Loading

0 comments on commit 94001b6

Please sign in to comment.