paholg / dimensioned

Compile-time dimensional analysis for various unit systems using Rust's type system.
https://crates.io/crates/dimensioned
MIT License
300 stars 23 forks source link

Question: working with nalgebra #65

Open wellcaffeinated opened 5 years ago

wellcaffeinated commented 5 years ago

I feel so inept at this. I appreciate the help.

I'm trying to create a helper function that will take an array slice and create a dimensioned nalgebra::Vector3 out of it... but i'm failing. This is what I've got so far:

fn dim_vector3<L, R>( unit_const :L, arr :[R ;3] ) ->
  na::Vector3<dim::typenum::Prod<L, R>>
where
  L: std::ops::Mul<R>
{
  na::Vector3::new( 
    unit_const * arr[0], 
    unit_const * arr[1], 
    unit_const * arr[2]
  )
}

any insight appreciated :)

paholg commented 5 years ago

I would recommend that you read through the hard sphere section of dimensioned-examples. It covers using dimensioned with vectors -- if you find anything confusing or lacking there, please open a ticket. I would be happy to try to make it more clear!

It is likely that you will have more luck by placing units on the outside of na::Vector3, not the inside. (Which is discussed in the above mentioned examples).

That said, you can make that code compile by adding some trait bounds. The compiler tells you you need Debug, Copy, and PartialEq for the output type (which together form na::Scalar). Then, it will still give you some lifetime errors. These messages are less helpful, but can be resolved by bounding L and R by Copy.

This code compiles:

fn dim_vector3<L, R>(unit_const: L, arr: [R; 3]) -> na::Vector3<dim::typenum::Prod<L, R>>
where
    L: std::ops::Mul<R> + Copy,
    R: Copy,
    dim::typenum::Prod<L, R>: na::Scalar,
{
  na::Vector3::new(
    unit_const * arr[0],
    unit_const * arr[1],
    unit_const * arr[2],
  )
}
paholg commented 5 years ago

And, for fun, you can clean it up a bit with the op! macro:

#[macro_use] extern crate typenum;

fn dim_vector3<L, R>(unit_const: L, arr: [R; 3]) -> na::Vector3<op!(L*R)>
where
    L: std::ops::Mul<R> + Copy,
    R: Copy,
    op!(L*R): na::Scalar,
{
  na::Vector3::new(
    unit_const * arr[0],
    unit_const * arr[1],
    unit_const * arr[2],
  )
}

This reminds me that I need to make that macro 2018 edition compatible....

adeschamps commented 5 years ago

One of the things that makes combining dimensioned and nalgebra hard is that there are cases where the units of matrices are non-homogeneous. For example, if you have a 2D Point2<Meter<f64>> and you wanted to translate and rotate it, you'd multiply an augmented vector by a 3x3 matrix. The units would look like this:

[   1    1  m ]   [ m ]
[   1    1  m ] X [ m ]
[ 1/m  1/m  1 ]   [ 1 ]

I've struggled in the past trying to put units inside nalgebra types, like na::Point2<si::Meter<f64>>, so in most of my code I only use dimensioned for 1D problems. That said, I just tried putting units on the outside and the following worked. Maybe I'll revisit using nalgebra and dimensioned together in the future.

use dimensioned::si;
use nalgebra as na;

fn main() {
    let position = si::Meter::new(na::Point2::new(2.0, 0.0));
    let velocity = si::MeterPerSecond::new(na::Vector2::new(3.0, 1.0));
    let time = 12.0 * si::S;
    let rotation = si::Unitless::new(na::Rotation2::new(std::f64::consts::FRAC_PI_2));

    println!("Position: {}", position);
    println!("Velocity: {}", velocity);
    println!("Time: {}", time);
    println!("Rotation: {}", rotation);

    println!("End position: {}", position + rotation * velocity * time);
}
wellcaffeinated commented 5 years ago

Thank you both! This was so helpful. I feel like I'm missing out on some of the implementation details surrounding dimensioned. I read through the examples, but found them a bit hard to follow. Perhaps once i understand this all better I can contribute some more docs for total newbies like me.

droundy commented 5 years ago

BTW if you just want a 3D vector type that works well with dimensioned, you could try

https://crates.io/crates/vector3d

Which I created for that purpose.

paholg commented 5 years ago

Perhaps once i understand this all better I can contribute some more docs for total newbies like me.

That would be great!

v-morlock commented 11 months ago

Thanks a lot for the guidance on using dimensioned with nalgebra. Did someone figure out how to use a "Isometry3" with dimensioned? I think the challenge here is that it consists of a rotation and a translation so simply wrapping it in sth like "Meter" breaks as soon as i want to multiply the Isometry with sth else...