Converting units in boost.units from angular_velocity to degrees_per_second
Asked Answered
A

2

10

I need to make a conversion from a general angular_velocity to degrees/second.

To illustrate this problem the example boostUnits.cpp:

#include <boost/units/systems/si.hpp>
#include <boost/units/systems/angle/revolutions.hpp>
#include <boost/units/systems/angle/degrees.hpp>
#include <boost/units/conversion.hpp>
#include <boost/units/pow.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

int main()
{
  boost::units::quantity< boost::units::si::angular_velocity> m_speed(
    (30.0*boost::units::si::radians_per_second)
  );
  std::cout << "m_speed: " << m_speed << std::endl;

  uint32_t result = static_cast<uint32_t>(
    boost::units::quantity<boost::units::si::angular_velocity,uint32_t>(
      m_speed*boost::units::degree::degrees/boost::units::si::seconds
    ).value()
  );
  std::cout << " result: "<< result << std::endl;

  return(0);
}

Produces this compiler output:

g++ boostUnits.cpp
/usr/local/include/boost/units/detail/conversion_impl.hpp: In static member function ‘static boost::units::quantity<Unit2, T2> boost::units::conversion_helper<boost::units::quantity<Unit1, T1>, boost::units::quantity<Unit2, T2> >::convert(const boost::units::quantity<Unit1, T1>&) [with Unit1 = boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<2l, 1l> >, boost::units::dimensionless_type> >, boost::units::heterogeneous_system<boost::units::heterogeneous_system_impl<boost::units::list<boost::units::heterogeneous_system_dim<boost::units::angle::degree_base_unit, boost::units::static_rational<1l, 1l> >, boost::units::list<boost::units::heterogeneous_system_dim<boost::units::si::second_base_unit, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::heterogeneous_system_dim<boost::units::angle::radian_base_unit, boost::units::static_rational<1l, 1l> >, boost::units::dimensionless_type> > >, boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<2l, 1l> >, boost::units::dimensionless_type> >, boost::units::dimensionless_type> >, void>, T1 = double, Unit2 = boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000001l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<1l, 1l> >, boost::units::dimensionless_type> >, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10l, boost::units::static_rational<3l, 1l> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > >, void>, T2 = unsigned int]’:
/usr/local/include/boost/units/quantity.hpp:193:   instantiated from ‘boost::units::quantity<Unit, Y>::quantity(const boost::units::quantity<Unit2, YY>&, typename boost::disable_if<boost::mpl::and_<typename boost::units::is_implicitly_convertible<Unit2, Unit>::type, boost::units::detail::is_non_narrowing_conversion<YY, Y>, mpl_::bool_<true>, mpl_::bool_<true>, mpl_::bool_<true> >, typename boost::units::detail::disable_if_is_same<Unit, Unit2>::type>::type*) [with Unit2 = boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<2l, 1l> >, boost::units::dimensionless_type> >, boost::units::heterogeneous_system<boost::units::heterogeneous_system_impl<boost::units::list<boost::units::heterogeneous_system_dim<boost::units::angle::degree_base_unit, boost::units::static_rational<1l, 1l> >, boost::units::list<boost::units::heterogeneous_system_dim<boost::units::si::second_base_unit, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::heterogeneous_system_dim<boost::units::angle::radian_base_unit, boost::units::static_rational<1l, 1l> >, boost::units::dimensionless_type> > >, boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<2l, 1l> >, boost::units::dimensionless_type> >, boost::units::dimensionless_type> >, void>, YY = double, Unit = boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000001l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<1l, 1l> >, boost::units::dimensionless_type> >, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10l, boost::units::static_rational<3l, 1l> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > >, void>, Y = unsigned int]’
boostUnits.cpp:16:   instantiated from here
/usr/local/include/boost/units/detail/conversion_impl.hpp:345: error: no matching function for call to ‘conversion_factor(boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<2l, 1l> >, boost::units::dimensionless_type> >, boost::units::heterogeneous_system<boost::units::heterogeneous_system_impl<boost::units::list<boost::units::heterogeneous_system_dim<boost::units::angle::degree_base_unit, boost::units::static_rational<1l, 1l> >, boost::units::list<boost::units::heterogeneous_system_dim<boost::units::si::second_base_unit, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::heterogeneous_system_dim<boost::units::angle::radian_base_unit, boost::units::static_rational<1l, 1l> >, boost::units::dimensionless_type> > >, boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000002l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<2l, 1l> >, boost::units::dimensionless_type> >, boost::units::dimensionless_type> >, void>&, boost::units::unit<boost::units::list<boost::units::dim<boost::units::time_base_dimension, boost::units::static_rational<-0x000000001l, 1l> >, boost::units::list<boost::units::dim<boost::units::plane_angle_base_dimension, boost::units::static_rational<1l, 1l> >, boost::units::dimensionless_type> >, boost::units::homogeneous_system<boost::units::list<boost::units::si::meter_base_unit, boost::units::list<boost::units::scaled_base_unit<boost::units::cgs::gram_base_unit, boost::units::scale<10l, boost::units::static_rational<3l, 1l> > >, boost::units::list<boost::units::si::second_base_unit, boost::units::list<boost::units::si::ampere_base_unit, boost::units::list<boost::units::si::kelvin_base_unit, boost::units::list<boost::units::si::mole_base_unit, boost::units::list<boost::units::si::candela_base_unit, boost::units::list<boost::units::angle::radian_base_unit, boost::units::list<boost::units::angle::steradian_base_unit, boost::units::dimensionless_type> > > > > > > > > >, void>&)’

What is the syntax to achieve the desired type specification and subsequent conversion? Do I need to specify a degrees_per_second unit, and if so, how?

Documentation: http://www.boost.org/doc/libs/1_37_0/doc/html/boost_units.html

Thank you in advance for your help.

Amann answered 1/12, 2010 at 7:30 Comment(6)
incomplete type typically means that you're a missing an include. You just don't give enough information for us to say whichRepudiation
I added a complete sample which should make the problem easier to diagnose. The error is slightly different from before.Amann
Sometimes it's easier to not use libraries like boost for any purpose. Converting an angular velocity doesn't seem to need boost or something similar. Why don't just use plain mathematics without having eight includes and two lines of unreadable code being longer than a window could ever cover? This is not a solution for the problem, I know, it's just a comment. Is a homework tag lacking?Timbal
Last time I checked, angular velocity (as in, radians per second) and degrees per second would differ by a factor of 180/Pi. Why involve boost? Also, you probably want floating-point numbers (datatype float) for these variables.Zeidman
@Timbal I couldn't include all the relevant source files in this small post, so I figured a concise example would be better than two lines of random code (which you can see in the revision history).Amann
@Seva Yes, just doing the math would be easier for this small sample. The problem occurs in the real code when another developer goes to fix an unrelated bug, and suddenly time X is being added to distance Y. Then the real life motor (who's interface requires an int) may damage itself, something else, or most critically someone else. That is why the extra time investment for compile time checking is worthwhile.Amann
A
10

Steven Wantabe provided the solution on the boost-users mailing list.
I implemented a working example below.

boostUnits.cpp:

#include <boost/units/systems/si.hpp>
#include <boost/units/systems/angle/revolutions.hpp>
#include <boost/units/systems/angle/degrees.hpp>
#include <boost/units/conversion.hpp>
#include <boost/units/pow.hpp>
#include <boost/units/io.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>

  typedef boost::units::divide_typeof_helper<
      boost::units::degree::plane_angle,
      boost::units::si::time
  >::type degrees_per_second;

int main()
{

  boost::units::quantity< boost::units::si::angular_velocity> m_speed(
    (30.0*boost::units::si::radians_per_second)
  );

  std::cout << "m_speed rad/sec: " << m_speed << std::endl;

  std::cout << "m_speed deg/sec: " << 
    static_cast<
      boost::units::quantity<degrees_per_second> 
    >(m_speed) << 
    std::endl;

  uint32_t result = static_cast<uint32_t>(
    static_cast<
      boost::units::quantity<degrees_per_second> 
    >(m_speed).value());

  std::cout << "int result: "<< result << std::endl;

  return(0);
}

Terminal Output:

g++ boostUnits.cpp
./a.out 
m_speed rad/sec: 30 s^-1 rad
m_speed deg/sec: 1718.87 deg s^-1
int result: 1718
Amann answered 1/12, 2010 at 21:41 Comment(0)
T
0

You don't need that much code. Natural algebra can get you there.

#include<boost/units/systems/si/io.hpp>
#include<boost/units/systems/cgs/io.hpp>
#include <boost/units/systems/angle/degrees.hpp>

#include<boost/units/cmath.hpp>
#include<iostream>

using std::cout;
using namespace boost::units;

int main(){

    quantity<si::angular_velocity> m_speed = 30.*si::radian/si::second ;
    cout 
        << m_speed << '\n'
        << m_speed/(degree::degree/si::second) << '\n'
        << quantity<si::dimensionless>(m_speed/(degree::degree/si::second))*(degree::degree/si::second) << '\n'
        << (quantity<si::dimensionless>(m_speed/(degree::degree/si::second))*(degree::degree/si::second)).value() << '\n'
        << int((quantity<si::dimensionless>(m_speed/(degree::degree/si::second))*(degree::degree/si::second)).value())
    ;   
}

Output:

30 s^-1 rad
30 deg^-1 rad
1718.87 deg s^-1
1718.87
1718
Tucana answered 12/4, 2016 at 23:20 Comment(3)
It is possible that this involves new features that became available since the original question was posted 5 years ago. Thanks for the update!Amann
Perhaps, but I doubt it. It uses only units conversion at constructor which was in Boost.Units from the beginning as far as I know. Sorry for being so late.Tucana
Thanks for the approach, looks nice!Amann

© 2022 - 2024 — McMap. All rights reserved.