Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: working with nalgebra #65

Open
wellcaffeinated opened this issue Jun 13, 2019 · 7 comments
Open

Question: working with nalgebra #65

wellcaffeinated opened this issue Jun 13, 2019 · 7 comments

Comments

@wellcaffeinated
Copy link

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
Copy link
Owner

paholg commented Jun 16, 2019

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
Copy link
Owner

paholg commented Jun 16, 2019

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
Copy link
Contributor

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
Copy link
Author

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
Copy link
Contributor

droundy commented Jun 20, 2019

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
Copy link
Owner

paholg commented Jun 20, 2019

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

That would be great!

@v-morlock
Copy link

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...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants