Problem with user defined Boost Units system
I am using Boost 1.45 and trying to use Boost Units to map the types of astrodynamic equation variables. I am getting an error with the following equation. The error is saying that the lvalue type for k2_divded_by_semi_major is wrong. The questions I have are: Q1: Did I defined my system correctly? (System file is attached - types.hpp) Q2: How do I define ratio in the system? For example I have some constants that define a conversion (1 earth radii = 6378 km). Q3: How do I define a variable type if its a fraction (e.g. radii / radian )? ---- EQUATION ---- sgp4::types::radii_t k2_divided_by_semi_major = m_k2 / pow<2> ( semi_major ); The types of variables are: m_k2 sgp4::types::radii_t semi_major sgp4::types::radian_t ---- ERROR ---- 1> [ 1> Unit=boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension,boost::units::static_rational<-1>>,boost::units::detail::merge_dimensions_impl<0,0>::apply<boost::units::dimensionless_type,boost::units::dimensionless_type>::type>,boost::units::homogeneous_system<boost::units::list<sgp4::types::radii_base_unit,boost::units::list<sgp4::types::radian_base_unit,boost::units::dimensionless_type>>>>, 1> Y=double 1> ] 1> and 1> [ 1> Unit=sgp4::types::sgp4_length_t, 1> Y=double 1> ] 1> Constructor for class 'boost::units::quantity<Unit,Y>' is declared 'explicit' 1> with 1> [ 1> Unit=sgp4::types::sgp4_length_t, 1> Y=double 1> ] Regards, Stephen
When I got exposure to boost::units, or Units of Measure in general, it is best to think of Dimensions first, line Length (L), Time (T), and so forth. Then think of your units second. After that, values and calculations are of a certain quantity. I might recommend you use the built-in velocity, or acceleration, as a template for your radii / radian dimension. You will end up with something like this in your dimension type definition, and forgive me the names aren't exact, //... typedef boost::units:dimension<radii_dimension,1,radian_dimension,-1> radii_radian_dimension; //... quantity<radii_t> my_radii; quantity<radian_t> my_radian; quantity<radii_radian_dimension> result = my_radii / my_radian; //... I think what you're missing are the quantity<>'s involved. In other words, you can't just go from unit (or dimension) to value; you have to run that through quantity<> to do anything useful with it. The kitchen sink examples are pretty good to learn from. After that, however, I find the compile-time safety to be quite attractive. HTH On Wed, Nov 30, 2011 at 9:49 AM, Stephen Torri <stephen.torri@gmail.com>wrote:
I am using Boost 1.45 and trying to use Boost Units to map the types of astrodynamic equation variables. I am getting an error with the following equation. The error is saying that the lvalue type for k2_divded_by_semi_major is wrong.
The questions I have are:
Q1: Did I defined my system correctly? (System file is attached - types.hpp)
Q2: How do I define ratio in the system? For example I have some constants that define a conversion (1 earth radii = 6378 km).
Q3: How do I define a variable type if its a fraction (e.g. radii / radian )?
---- EQUATION ----
sgp4::types::radii_t k2_divided_by_semi_major = m_k2 / pow<2> ( semi_major );
The types of variables are:
m_k2 sgp4::types::radii_t semi_major sgp4::types::radian_t
---- ERROR ----
1> [ 1> Unit=boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension,boost::units::static_rational<-1>>,boost::units::detail::merge_dimensions_impl<0,0>::apply<boost::units::dimensionless_type,boost::units::dimensionless_type>::type>,boost::units::homogeneous_system<boost::units::list<sgp4::types::radii_base_unit,boost::units::list<sgp4::types::radian_base_unit,boost::units::dimensionless_type>>>>, 1> Y=double 1> ] 1> and 1> [ 1> Unit=sgp4::types::sgp4_length_t, 1> Y=double 1> ] 1> Constructor for class 'boost::units::quantity<Unit,Y>' is declared 'explicit' 1> with 1> [ 1> Unit=sgp4::types::sgp4_length_t, 1> Y=double 1> ]
Regards,
Stephen
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Michael, Thanks for responding. I agree that your logical step-wise progression is the correct way to go but it is not quite clear to me how to do it. Starting with dimensions I see I have the following: radii -> length radians -> angle minute -> time km -> length If we start with radii I was thinking what I did in my attachment, types.hpp, was correct for dimensions. Radii is a length so I used the length physical dimension class. Can you make changes to types.hpp for radii to show me what you mean in a step-by-step detail? I usually do very well if I have one example to work off when going on my own. Stephen On 11/30/11, Michael Powell <mwpowellnm@gmail.com> wrote:
When I got exposure to boost::units, or Units of Measure in general, it is best to think of Dimensions first, line Length (L), Time (T), and so forth. Then think of your units second. After that, values and calculations are of a certain quantity.
I might recommend you use the built-in velocity, or acceleration, as a template for your radii / radian dimension.
You will end up with something like this in your dimension type definition, and forgive me the names aren't exact,
//... typedef boost::units:dimension<radii_dimension,1,radian_dimension,-1> radii_radian_dimension; //... quantity<radii_t> my_radii; quantity<radian_t> my_radian; quantity<radii_radian_dimension> result = my_radii / my_radian; //...
I think what you're missing are the quantity<>'s involved. In other words, you can't just go from unit (or dimension) to value; you have to run that through quantity<> to do anything useful with it.
The kitchen sink examples are pretty good to learn from.
After that, however, I find the compile-time safety to be quite attractive.
HTH
On Wed, Nov 30, 2011 at 9:49 AM, Stephen Torri <stephen.torri@gmail.com>wrote:
I am using Boost 1.45 and trying to use Boost Units to map the types of astrodynamic equation variables. I am getting an error with the following equation. The error is saying that the lvalue type for k2_divded_by_semi_major is wrong.
The questions I have are:
Q1: Did I defined my system correctly? (System file is attached - types.hpp)
Q2: How do I define ratio in the system? For example I have some constants that define a conversion (1 earth radii = 6378 km).
Q3: How do I define a variable type if its a fraction (e.g. radii / radian )?
---- EQUATION ----
sgp4::types::radii_t k2_divided_by_semi_major = m_k2 / pow<2> ( semi_major );
The types of variables are:
m_k2 sgp4::types::radii_t semi_major sgp4::types::radian_t
---- ERROR ----
1> [ 1>
Unit=boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension,boost::units::static_rational<-1>>,boost::units::detail::merge_dimensions_impl<0,0>::apply<boost::units::dimensionless_type,boost::units::dimensionless_type>::type>,boost::units::homogeneous_system<boost::units::list<sgp4::types::radii_base_unit,boost::units::list<sgp4::types::radian_base_unit,boost::units::dimensionless_type>>>>, 1> Y=double 1> ] 1> and 1> [ 1> Unit=sgp4::types::sgp4_length_t, 1> Y=double 1> ] 1> Constructor for class 'boost::units::quantity<Unit,Y>' is declared 'explicit' 1> with 1> [ 1> Unit=sgp4::types::sgp4_length_t, 1> Y=double 1> ]
Regards,
Stephen
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
Sorry, yes. My kernel of knowledge; the kitchen sink examples in the boost::units documentation provides some good examples you can glean from. Also, review the boost::units code itself. If you've got the boost library, then you've got this code to review as well. That'd be my starting point, anyway. HTH On Wed, Nov 30, 2011 at 12:32 PM, Stephen Torri <stephen.torri@gmail.com>wrote:
Michael,
Thanks for responding. I agree that your logical step-wise progression is the correct way to go but it is not quite clear to me how to do it. Starting with dimensions I see I have the following:
radii -> length radians -> angle minute -> time km -> length
If we start with radii I was thinking what I did in my attachment, types.hpp, was correct for dimensions. Radii is a length so I used the length physical dimension class.
Can you make changes to types.hpp for radii to show me what you mean in a step-by-step detail? I usually do very well if I have one example to work off when going on my own.
Stephen
On 11/30/11, Michael Powell <mwpowellnm@gmail.com> wrote:
When I got exposure to boost::units, or Units of Measure in general, it is best to think of Dimensions first, line Length (L), Time (T), and so forth. Then think of your units second. After that, values and calculations are of a certain quantity.
I might recommend you use the built-in velocity, or acceleration, as a template for your radii / radian dimension.
You will end up with something like this in your dimension type definition, and forgive me the names aren't exact,
//... typedef boost::units:dimension<radii_dimension,1,radian_dimension,-1> radii_radian_dimension; //... quantity<radii_t> my_radii; quantity<radian_t> my_radian; quantity<radii_radian_dimension> result = my_radii / my_radian; //...
I think what you're missing are the quantity<>'s involved. In other words, you can't just go from unit (or dimension) to value; you have to run that through quantity<> to do anything useful with it.
The kitchen sink examples are pretty good to learn from.
After that, however, I find the compile-time safety to be quite attractive.
HTH
On Wed, Nov 30, 2011 at 9:49 AM, Stephen Torri <stephen.torri@gmail.com>wrote:
I am using Boost 1.45 and trying to use Boost Units to map the types of astrodynamic equation variables. I am getting an error with the following equation. The error is saying that the lvalue type for k2_divded_by_semi_major is wrong.
The questions I have are:
Q1: Did I defined my system correctly? (System file is attached - types.hpp)
Q2: How do I define ratio in the system? For example I have some constants that define a conversion (1 earth radii = 6378 km).
Q3: How do I define a variable type if its a fraction (e.g. radii / radian )?
---- EQUATION ----
sgp4::types::radii_t k2_divided_by_semi_major = m_k2 / pow<2> ( semi_major );
The types of variables are:
m_k2 sgp4::types::radii_t semi_major sgp4::types::radian_t
---- ERROR ----
1> [ 1>
Unit=boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension,boost::units::static_rational<-1>>,boost::units::detail::merge_dimensions_impl<0,0>::apply<boost::units::dimensionless_type,boost::units::dimensionless_type>::type>,boost::units::homogeneous_system<boost::units::list<sgp4::types::radii_base_unit,boost::units::list<sgp4::types::radian_base_unit,boost::units::dimensionless_type>>>>,
1> Y=double 1> ] 1> and 1> [ 1> Unit=sgp4::types::sgp4_length_t, 1> Y=double 1> ] 1> Constructor for class 'boost::units::quantity<Unit,Y>' is declared 'explicit' 1> with 1> [ 1> Unit=sgp4::types::sgp4_length_t, 1> Y=double 1> ]
Regards,
Stephen
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I am using Boost 1.45 and trying to use Boost Units to map the types of astrodynamic equation variables. I am getting an error with the following equation. The error is saying that the lvalue type for k2_divded_by_semi_major is wrong.
This is the library doing what it is supposed to do : your equation is dimensionally incorrect...
The questions I have are:
Q1: Did I defined my system correctly? (System file is attached - types.hpp)
Q2: How do I define ratio in the system? For example I have some constants that define a conversion (1 earth radii = 6378 km).
Look at <boost/units/base_units/us/yard.hpp> for an example defining a new base unit of length with conversion to metric. You can look at the macro details to see how it is implemented.
Q3: How do I define a variable type if its a fraction (e.g. radii / radian )?
typedef derived_dimension<length_base_dimension,1,plane_angle_base_dimension,-1>::type length_over_angle_dimension; typedef unit<length_over_angle_dimension,my_system> length_over_angle;
sgp4::types::radii_t k2_divided_by_semi_major = m_k2 / pow<2> ( semi_major );
The types of variables are:
m_k2 sgp4::types::radii_t semi_major sgp4::types::radian_t
You are trying to assign a [length]/[plane_angle^2] to a [length] which is clearly dimensionally incorrect. Depending on your perspective, one of the upsides/downsides of Boost.Units is that it requires that you be precise in formulation of equations... Matthias
Thanks, Matthias. IMHO, this is one of the greatest things about boost::units, compile time unit safety. If your dimensions aren't correct then, there's no point in proceeding until they are. Runtimes are another question, though; but, for compile time, I like that about it. On Wed, Nov 30, 2011 at 1:08 PM, Matthias Schabel <boost@schabel-family.org>wrote:
I am using Boost 1.45 and trying to use Boost Units to map the types of astrodynamic equation variables. I am getting an error with the following equation. The error is saying that the lvalue type for k2_divded_by_semi_major is wrong.
This is the library doing what it is supposed to do : your equation is dimensionally incorrect...
The questions I have are:
Q1: Did I defined my system correctly? (System file is attached - types.hpp)
Q2: How do I define ratio in the system? For example I have some constants that define a conversion (1 earth radii = 6378 km).
Look at <boost/units/base_units/us/yard.hpp> for an example defining a new base unit of length with conversion to metric. You can look at the macro details to see how it is implemented.
Q3: How do I define a variable type if its a fraction (e.g. radii / radian )?
typedef derived_dimension<length_base_dimension,1,plane_angle_base_dimension,-1>::type length_over_angle_dimension; typedef unit<length_over_angle_dimension,my_system> length_over_angle;
sgp4::types::radii_t k2_divided_by_semi_major = m_k2 / pow<2> ( semi_major );
The types of variables are:
m_k2 sgp4::types::radii_t semi_major sgp4::types::radian_t
You are trying to assign a [length]/[plane_angle^2] to a [length] which is clearly dimensionally incorrect. Depending on your perspective, one of the upsides/downsides of Boost.Units is that it requires that you be precise in formulation of equations...
Matthias
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I am trying to understand the dimensionality of the following two equations. --- first equation --- example::types::radii_t val1 = 5 * example::types::radii; example::types::radii_t val2 = 4 * example::types::radii; example::types::radii_t L1 = 1 / ( val1 - va2 ); If I was doing the dimensional analysis by hand I would see 1 / ( radii - radii ) Such that the end type would be radii^-1 Given that end type here is the second equation: example::types::radii_t val3 = 5 * example::types::radii; example::types::dimensionless_t val4 = 10; example::types::dimensionless_t L2 = L1 * val4 * val3; Doing the dimensional analysis by hand I think I should see: L2 = radii * (nothing) * radii^-1 = (nothing) or dimensionless What Boost Units is reporting is that L2 is actually units in radii_t. --------- QUESTIONS -------------- Q1: How do you print out the types at compile time? Q2: How can you confirm you have the correc power for a type? For example radii is indeed raised to the -1 power. Stephen On 11/30/11, Michael Powell <mwpowellnm@gmail.com> wrote:
Thanks, Matthias. IMHO, this is one of the greatest things about boost::units, compile time unit safety. If your dimensions aren't correct then, there's no point in proceeding until they are. Runtimes are another question, though; but, for compile time, I like that about it.
On Wed, Nov 30, 2011 at 1:08 PM, Matthias Schabel <boost@schabel-family.org>wrote:
I am using Boost 1.45 and trying to use Boost Units to map the types of astrodynamic equation variables. I am getting an error with the following equation. The error is saying that the lvalue type for k2_divded_by_semi_major is wrong.
This is the library doing what it is supposed to do : your equation is dimensionally incorrect...
The questions I have are:
Q1: Did I defined my system correctly? (System file is attached - types.hpp)
Q2: How do I define ratio in the system? For example I have some constants that define a conversion (1 earth radii = 6378 km).
Look at <boost/units/base_units/us/yard.hpp> for an example defining a new base unit of length with conversion to metric. You can look at the macro details to see how it is implemented.
Q3: How do I define a variable type if its a fraction (e.g. radii / radian )?
typedef derived_dimension<length_base_dimension,1,plane_angle_base_dimension,-1>::type length_over_angle_dimension; typedef unit<length_over_angle_dimension,my_system> length_over_angle;
sgp4::types::radii_t k2_divided_by_semi_major = m_k2 / pow<2> ( semi_major );
The types of variables are:
m_k2 sgp4::types::radii_t semi_major sgp4::types::radian_t
You are trying to assign a [length]/[plane_angle^2] to a [length] which is clearly dimensionally incorrect. Depending on your perspective, one of the upsides/downsides of Boost.Units is that it requires that you be precise in formulation of equations...
Matthias
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
I am trying to understand the dimensionality of the following two equations.
--- first equation --- example::types::radii_t val1 = 5 * example::types::radii; example::types::radii_t val2 = 4 * example::types::radii;
example::types::radii_t L1 = 1 / ( val1 - va2 );
va2->val2 This should give you a compile error anyway, since you are trying to assign a length to an inverse length...
If I was doing the dimensional analysis by hand I would see
1 / ( radii - radii )
Such that the end type would be
radii^-1
Given that end type here is the second equation:
example::types::radii_t val3 = 5 * example::types::radii; example::types::dimensionless_t val4 = 10; example::types::dimensionless_t L2 = L1 * val4 * val3;
Doing the dimensional analysis by hand I think I should see:
L2 = radii * (nothing) * radii^-1 = (nothing) or dimensionless
What Boost Units is reporting is that L2 is actually units in radii_t.
I'm not sure I believe you; the code you pasted is not compilable...did you actually compile anything?
--------- QUESTIONS --------------
Q1: How do you print out the types at compile time?
Q2: How can you confirm you have the correc power for a type? For example radii is indeed raised to the -1 power.
Using your earlier header : #include "types.hpp" #include <iostream> #include <boost/units/io.hpp> using namespace myproject::types; int main() { radii_t val1(5*radii), val2(4*radii); //auto L1 = 1/(val1-val2); // compile time error due to failed dimensional consistency radii_t val3(5*radii); dimensionless_t val4 = 10; dimensionless_t L2(val3*val4/(val1-val2)); std::cout << val1 << std::endl << val2 << std::endl << val3 << std::endl << val4 << std::endl << L2 << std::endl; return 0; } gives 5 r 4 r 5 r 10 dimensionless 50 dimensionless
Matthias, I appreciate your response. Yes I did not compile my example. I should have done that. I took your example and then trimmed down the header file so I can reproduce the error. I am not sure what is wrong here. I get an error not because the destination type is incorrect. It does not even reach that point. I get an error that there is no division operator: [storri@fedora Source]$ g++ -o boost_units boost_units.cpp boost_units.cpp: In function int main(int, char**): boost_units.cpp:44:39: error: no match for operator/ in 1 / boost::units::operator-(const boost::units::quantity<Unit1, X>&, const boost::units::quantity<Unit2, Y>&) [with Unit1 = boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<myproject::types::radii_base_unit, boost::units::list<myproject::types::minute_base_unit, boost::units::dimensionless_type> > > > >, Unit2 = boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<myproject::types::radii_base_unit, boost::units::list<myproject::types::minute_base_unit, boost::units::dimensionless_type> > > > >, X = double, Y = double, typename boost::units::subtract_typeof_helper<boost::units::quantity<Unit1, X>, boost::units::quantity<Unit2, Y> >::type = boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<myproject::types::radii_base_unit, boost::units::list<myproject::types::minute_base_unit, boost::units::dimensionless_type> > > > >, double>]((*(const boost::units::quantity<boost::units::unit<boost::units::list<boost::units::dim<boost::units::length_base_dimension, boost::units::static_rational<1l> >, boost::units::dimensionless_type>, boost::units::homogeneous_system<boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<myproject::types::radii_base_unit, boost::units::list<myproject::types::minute_base_unit, boost::units::dimensionless_type> > > > >, double>*)(& val2))) If I remove the "radii_t result =" from the following code and comment out the IO statement I get the same error as previously quoted above. Below is the code I used. I appreciate your patience as I learn Boost Units. Q1: What is the reason for this error? What in the error output helped you to figure that out. Q2: Even if the above error did not exist you mentioned that it would fail the dimensional analysis. I think we both agree the type would be radii^-1. How do you declare a type to be raised to the correct power? Stephen ------------------------- #include <boost/units/base_unit.hpp> #include <boost/units/base_units/angle/radian.hpp> #include <boost/units/io.hpp> #include <boost/units/make_system.hpp> #include <boost/units/physical_dimensions/length.hpp> #include <boost/units/physical_dimensions/time.hpp> #include <boost/units/static_constant.hpp> #include <iostream> namespace myproject { namespace types { struct radii_base_unit : public boost::units::base_unit<radii_base_unit, boost::units::length_dimension, 1> { static std::string name() { return("radii"); } static std::string symbol() { return("r"); } }; struct minute_base_unit : public boost::units::base_unit<minute_base_unit, boost::units::time_dimension,3> { static std::string name() { return ("minute"); } static std::string symbol() { return ("min"); } }; typedef boost::units::make_system<radii_base_unit, minute_base_unit, boost::units::angle::radian_base_unit >::type myproject_system_t; typedef boost::units::unit<boost::units::length_dimension,myproject_system_t> myproject_length; typedef boost::units::quantity<myproject_length, double> radii_t; BOOST_UNITS_STATIC_CONSTANT(radii,myproject_length); } } int main ( int, char** ) { using namespace myproject::types; radii_t val1 ( 5 * radii ); radii_t val2 ( 3 * radii ); radii_t result = 1.0 / ( val1 - val2 ); std::cout << result << std::endl; return 0; } On 12/1/11, Matthias Schabel <boost@schabel-family.org> wrote:
I am trying to understand the dimensionality of the following two equations.
--- first equation --- example::types::radii_t val1 = 5 * example::types::radii; example::types::radii_t val2 = 4 * example::types::radii;
example::types::radii_t L1 = 1 / ( val1 - va2 );
va2->val2
This should give you a compile error anyway, since you are trying to assign a length to an inverse length...
If I was doing the dimensional analysis by hand I would see
1 / ( radii - radii )
Such that the end type would be
radii^-1
Given that end type here is the second equation:
example::types::radii_t val3 = 5 * example::types::radii; example::types::dimensionless_t val4 = 10; example::types::dimensionless_t L2 = L1 * val4 * val3;
Doing the dimensional analysis by hand I think I should see:
L2 = radii * (nothing) * radii^-1 = (nothing) or dimensionless
What Boost Units is reporting is that L2 is actually units in radii_t.
I'm not sure I believe you; the code you pasted is not compilable...did you actually compile anything?
--------- QUESTIONS --------------
Q1: How do you print out the types at compile time?
Q2: How can you confirm you have the correc power for a type? For example radii is indeed raised to the -1 power.
Using your earlier header :
#include "types.hpp"
#include <iostream> #include <boost/units/io.hpp>
using namespace myproject::types;
int main() { radii_t val1(5*radii), val2(4*radii);
//auto L1 = 1/(val1-val2); // compile time error due to failed dimensional consistency
radii_t val3(5*radii);
dimensionless_t val4 = 10; dimensionless_t L2(val3*val4/(val1-val2));
std::cout << val1 << std::endl << val2 << std::endl << val3 << std::endl << val4 << std::endl << L2 << std::endl;
return 0; }
gives
5 r 4 r 5 r 10 dimensionless 50 dimensionless
participants (3)
-
Matthias Schabel
-
Michael Powell
-
Stephen Torri