I would like to find the minimum distance and normal vector between a robot (franka panda) and an obstacle via MoveIt and ROS. The collision_detection::CollisionEnv::distanceRobot method from MoveIt (documentation) provides exactly the info I want but unfortunately is not available in the Python API. So, I would like some help on how to call this function since I am not familiar with C++.
This is my attempt so far:
#include <ros/ros.h>
// MoveIt
#include <moveit/robot_model_loader/robot_model_loader.h>
#include <moveit/planning_scene/planning_scene.h>
#include <moveit/collision_detection/collision_env.h>
#include <moveit_msgs/CollisionObject.h>
#include <moveit/move_group_interface/move_group_interface.h>
#include <moveit/planning_scene_interface/planning_scene_interface.h>
int main(int argc, char** argv)
{
ros::init(argc, argv, "panda_coll_detection");
ros::AsyncSpinner spinner(1);
spinner.start();
// ---------------------------------------------------------------------------
// Define interfaces
// ---------------------------------------------------------------------------
// Define move_group_interface & planning_scene_interface
static const std::string PLANNING_GROUP = "panda_arm";
moveit::planning_interface::MoveGroupInterface move_group_interface(PLANNING_GROUP);
moveit::planning_interface::PlanningSceneInterface planning_scene_interface;
// Define planning_scene
robot_model_loader::RobotModelLoader robot_model_loader("robot_description");
const moveit::core::RobotModelPtr& kinematic_model = robot_model_loader.getModel();
planning_scene::PlanningScene planning_scene(kinematic_model);
// ---------------------------------------------------------------------------
// Add a collision object
// ---------------------------------------------------------------------------
// Define a collision object ROS message for the robot to avoid
moveit_msgs::CollisionObject collision_object;
collision_object.header.frame_id = move_group_interface.getPlanningFrame();
collision_object.id = "box1";
// Define a box to add to the world
shape_msgs::SolidPrimitive primitive;
primitive.type = primitive.BOX;
primitive.dimensions.resize(3);
primitive.dimensions[primitive.BOX_X] = 0.4;
primitive.dimensions[primitive.BOX_Y] = 0.02;
primitive.dimensions[primitive.BOX_Z] = 0.02;
// Define a pose for the box (specified relative to frame_id)
geometry_msgs::Pose box_pose;
box_pose.orientation.w = 1.0;
box_pose.position.x = 0.5;
box_pose.position.y = 0.0;
box_pose.position.z = 0.35;
// Add box to collision_object
collision_object.primitives.push_back(primitive);
collision_object.primitive_poses.push_back(box_pose);
collision_object.operation = collision_object.ADD;
// Define a vector of collision objects that could contain additional objects
std::vector<moveit_msgs::CollisionObject> collision_objects;
collision_objects.push_back(collision_object);
// Add the collision object into the world
planning_scene_interface.applyCollisionObjects(collision_objects);
// ---------------------------------------------------------------------------
// Min distance & Collision Checking
// ---------------------------------------------------------------------------
// Define collision request & result
auto distance_request = collision_detection::DistanceRequest();
auto distance_result = collision_detection::DistanceResult();
// Get robot state & model
moveit::core::RobotState copied_state = planning_scene.getCurrentState();
const moveit::core::RobotModelConstPtr kinematic_model_cnstPtr = robot_model_loader.getModel();
// Call distanceRobot()
collision_detection::CollisionEnv collision_env(kinematic_model_cnstPtr, 0.0, 1.0);
collision_env.distanceRobot(distance_request, distance_result, copied_state);
// Show result
ROS_INFO_STREAM("Collision="<<distance_result.collision); // ToDo: Get all results
ros::shutdown();
return 0;
}
To be precise, my question is:
How to properly declare collision_env and call distanceRobot()?
Currently, I am getting this error: "cannot declare variable ‘collision_env’ to be of abstract type ‘collision_detection::CollisionEnv’".
Additionally,
The CollisionEnv constructor has multiple versions (doc). One requires model,padding,scale as inputs and another requires model,world,padding,scale. What is the difference and which one should I use?
In the MoveIt tutorials is stated that the PlanningSceneMonitor is the recommended method to create and maintain the current planning scene and not instantiating a PlanningScene class directly. However, they do not provide any examples using the PlanningSceneMonitor. If my current approach is not the recommended one, where can I find examples on how to use the PlanningSceneMonitor?
UPDATE:
Based on andersonjwan's answer, I included this header file and made the following change:
#include <moveit/collision_detection_fcl/collision_env_fcl.h>
collision_detection::CollisionEnvFCL collision_env(kinematic_model_cnstPtr, 0.0, 1.0);
By just looking through your sample code, I will answer your explicit questions first and then provide some additional tips that you may find useful to you.
How to properly declare collision_env and call distanceRobot()?
The namespace collision_detection provides several class type definitions. For your case, the error you are receiving derives from trying to instantiate an abstract class (i.e., an interface).
Instead, you should be instantiating a concrete class (i.e., a class) that implements the interface (i.e., derived class). From briefly looking at the documentation, it seems you have several options:
CollisionEnvAllValid
CollisionEnvBullet
CollisionEnvDistanceField
CollisionEnvFCL
CollisionEnvHybrid.
From your application, it seems that the CollisionEnvDistanceField, CollisionEnvFCL, or CollisionEnvHybrid where FCL stands for the Flexible Collision Library would be most appropriate to use.
The CollisionEnv constructor has multiple versions (doc). One requires model,padding,scale as inputs and another requires model,world,padding,scale. What is the difference and which one should I use?
With respect to the first answer, I would review the constructors for the class you require based on your planned application. In most cases, it is better to start with less and add use the more verbose ones as needed.
In the MoveIt tutorials is stated that the PlanningSceneMonitor is the recommended method to create and maintain the current planning scene and not instantiating a PlanningScene class directly. However, they do not provide any examples using the PlanningSceneMonitor. If my current approach is not the recommended one, where can I find examples on how to use the PlanningSceneMonitor?
It seems more information of differentiating the PlanningScene from the PlanningSceneMonitor can be found here.
However, after briefly reading through, it seems that the PlanningScene is the wrapper to capture ROS-related scene events (e.g., objects in the world, robot state, etc), and the PlanningSceneMonitor encompasses the PlanningScene and more; so, it should be used in order to effectively retrieve more information from the ROS environment where the PlanningScene monitor provides minimum information.
Some Tips:
To reduce the length of the line, it may be useful to use the using directive to qualify namespaces, so you do not have to type out the entire namespace path.
For example, it is natural to qualify class types that have no conflicts with your own:
using moveit::planning_interface::MoveGroupInterface;
int main(int argc, char** argv) {
MoveGroupInterface move_group_interface(...);
}
Related
I am solving the following problem. I am working on an optimization program in C ++ which, depending on the initial settings of the user, uses various regulations (standards) to calculate the target function. Suppose we have a method A based on some norm and a method B based on another norm to calculate the target function. The user is setting the right standard before starting the program. The rest of the code is the same. During optimization, the target function is iteratively called over and over again. Of course, there is a simple solution: each time the target function is called, the IF condition is used to decide which standard to use. But because the program has to make decisions in every iteration, it seems to be ineffective. The second option is to create 2 independent codes and run only the one with the required standard. This, in turn, is ugly in terms of duplicate code.
I imagined that I would create 2 different classes and use the selected class using the IF condition when constructing the object. This would make the program decide only once when creating the object, but during the iteration itself the object would be clearly defined. Unfortunately, this does not work because objects cannot be created in IF conditions.
//-----------------------------------------------------------
// Create object sensor based on input
if(data.sensors_tipe == "Uniaxial_025") Sensor_Uniaxial_025 sensor(data);
else if (data.sensors_tipe == "T_rosette_05") Sensor_T_rosette_05 sensor(data);
else report.error("some error");
// rotation test
int element_index = 1;
double orientation_angle = 3.490658503988659;
sensor.rotate(element_index, orientation_angle);
Another way I would like is to set the correct method using a parameter in the constructor. Unfortunately, that probably isn't possible either.
I am a beginner and I did not find the answer anywhere. So maybe someone can help. Thanks
This is a good job for templates, which are "recipes" to generate code.
The end result will be duplicated machine code, but without the duplication in the source.
template<typename MethodT>
float optimize(const MethodT& method) {
float v = method();
// etc...
}
float methodA();
float methodB();
int main() {
auto a = optimize(methodA);
auto b = optimize(methodB);
}
First, the solution with if may be not that bad. It is branch on each function call, but the branch should be predicted well.
Second, if the functions that implement method A and method B are large enough to miss inlining, use function pointer.
Otherwise, use static polymorphism with templates, method A and method B may be passed via template parameter as functors.
In case, the user can change standard after programm compilation (for example, before each run) you can create interface and 2 child from it.
So, at startup you should create the instance (one of 2) you need through new. And then you can use it.
You can't use that algorithm with stack instances.
One way is to use inheritance.
class Sensor
{
public:
virtual void rotate(int, double) = 0;
};
class Sensor_Uniaxial_025 : public Sensor
{
public:
virtual void rotate(int, double) {/*stuff*/};
};
class Sensor_T_rosette_05 : public Sensor
{
public:
virtual void rotate(int, double) {/*stuff*/};
};
Sensor* sensorToUse;
//-----------------------------------------------------------
// Create object sensor based on input
if(data.sensors_tipe == "Uniaxial_025") sensorToUse = new Sensor_Uniaxial_025(data);
else if (data.sensors_tipe == "T_rosette_05") sensorToUse = new
Sensor_T_rosette_05(data);
else report.error("some error");
// rotation test
int element_index = 1;
double orientation_angle = 3.490658503988659;
sensorToUse->rotate(element_index, orientation_angle);
The example above, with new, comes with serious memory management issues. But if you pre-allocate the sensor for each type, in a single instance, and use a look-up instead it works well.
The alternative is with template. See other answers for these approaches.
I have looked for similar questions but haven't found them. I want to generate normally distributed random numbers. I used to code C and some C++98 but am now trying to go back and learn C++11.
I have a function to return a seeded RNG
auto seeded_rng () {
.... //do seeding.
std::default_random_engine Eng(/*seeds*/);
return Eng;
}
In my main function I bind the RNG to say a gaussian distribution
auto binded = std::bind(std::normal_distribution<double>{0,1.0},seeded_rng);
This function works fine. I can call "binded()" directly in main and it generates the numbers
I want to have a simulation object that needs random numbers to be created. My question related to how to pass in the "RNG_PART" below.
class sim
{
public:
sim( RNG_PART & rng, int_number_of sims ){ /* Do whatever */}
}
So if in main, I then want to create a simulation object
sim A(binded, 100);
it complains.
I tried declaring
sim::sim(std::default_random_engine &rng, int number_of_sims){}
but it is complaining. What type should I use to pass in the "binded" distribution to the constructor? Or am I going about this completely incorrectly. Should I just declare the RNG engine globally? I'd prefer not to do that.
Apologies if this is very basic!
The type of the argument to sim is not matching the type of binded. When you create binded, you avoid the issue by using auto instead of declaring the type, but you're going to need it later. How about the following in class sim instead of trying to figure out the type ahead of time. This also allows you to change the RNG or the random distribution without changing the sim class:
template<typename T>
class sim
{
public:
sim(T& rng, int_number_of sims ){ /* Do whatever */}
Note that the template definition must be visible to the place you use it, so you can't put it into a cpp file unless the only code that uses it is in that file. Typically, the template definition is in the same h file as where it was declared.
Then, you'd create sim as:
sim<decltype(binded)> A(binded,100);
the decltype(binded) is a way to tell the sim function template the type of binded.
Since binded can return different types depending upon the chosen random number distribution, obtaining the return type in the sim class template could be done with
using rnd_return_type = typename std::result_of<T()>::type; //in C++11, C++14
or
using rnd_return_type = std::invoke_result_t<T>; //C++17 and later
std::result_of is deprecated in C++17 and will be removed in C++20
This seems like a common problem. I've got two massive sets of code that need to be glued together: one that uses simple structs to hold data, the other has APIs that only expose getter/setter methods.
Is it possible to use Boost.Proto to define a mapping that could then be used to auto-generate the code that invokes the getters/setters? Conceptually, the piece that seems most difficult is the synthesis of the function names to call, as that would involve compile-time string concatenation. Other challenges involve mapping enum types from one to the other and custom initialization or conversion code.
Having a drop-in-place Proto-based solution that solves this problem would be a huge benefit to a wide variety of people.
E.g., I have an API with types such as this:
// These classes use getters/setters.
class Wheel
{
int number_of_lugnuts_;
public:
void initialize_wheel(bool);
void set_number_of_lugnuts(int);
int get_number_of_lugnuts();
};
class Engine
{
public:
enum Gas_type_t {
Unleaded,
Premium
};
private:
Gas_type_t gas_type_;
public:
void initialize_engine(bool);
void set_gas_type(Gas_type_t);
Gas_type_t get_gas_type();
};
While I also have millions of lines of code with the same data in simple directly-accessed structs:
// This code has simple data structures.
struct Car
{
// These POD members are used by a large body of existing code.
int lugnut_count;
enum FUEL_TYPES {
NORMAL_FUEL,
HI_OCTANE
};
FUEL_TYPES fuelType;
};
Now the old-fashioned way is to add a lot of converters:
// The manual way to accomplish this for only the Wheel API.
// This has to be repeated similarly for the Engine API.
void convert_to_wheel(Wheel& w)
{
w.initialize_wheel(true); // how can initialization be handled?
w.set_number_of_lugnuts(lugnut_count);
}
void convert_from_wheel(Wheel& w)
{
lugnut_count = w.get_number_of_lugnuts();
}
But, in the style of Boost.Spirit, I would like to use Proto to create an EDSL allowing me to specify the mapping, and have the compiler generate the repetitive code for me.
I can define enough Proto terminals to get this constructor to compile:
Car()
{
// So can we define an API mapping like this?
// Would strings be the only way to accomplish this?
// This appears structurally similar to how Spirit grammars are defined.
// This is a very rough attempt because it's unclear if this is possible.
define_api_mapping<Wheel>
(initialization_code((_dest_ ->* &Wheel::initialize_wheel)(true)))
(map_member(lugnut_count) = map_getset("number_of_lugnuts"))
;
define_api_mapping<Engine>
(initialization_code((_dest_ ->* &Engine::initialize_engine)(true)))
(map_member(fuelType) = map_getset("gas_type"))
;
define_enum_mapping<FUEL_TYPES>
(enum_value(NORMAL_FUEL) = enum_value(Engine::Unleaded))
(enum_value(HI_OCTANE) = enum_value(Engine::Premium))
;
}
Conversion could conceptually be a simple function call:
// Declare some objects.
Car c;
Engine e;
Wheel w1, w2;
// Set some values.
c.lugnut_count = 20;
// Convert the old fashioned way.
c.convert_to_wheel(w1);
// Convert the new way.
convert(c, w2);
It's an ugly start, but I'm now baffled by how to mangle the names to generate the calls to the getters and setters.
Is this possible? What would the solution look like?
I wrote a C++ DLL using VS 2010 which is used to wrap some program that does boolean operations on polygons.Its structure is as follows: There is a main header and .cpp whose methods are exposed by marks :
__declspec(dllexport)
Then inside one of those method I execute a call of one of the methods of my polygon program which is contained in a different c++ class which is a part of the library.I should note that in addition to calling that method I also create(in the main dll .cpp file) variables which are defined in that polygons program.Those variables are of types required to pass and receive numeric data from the polygon program.
Now ,what is wrong.When I run the an application that uses this dll I do two identical calls to the same method of the library -the one I explained above that calls a function of the polygon program.When I do those calls I pass some numeric data into the method and expect to get back a new data based on some calculations in the polygons program.First call returns the correct data but the second one returns kind of mix of the data from the first call and the second input data.I am not DLL expert but I took a look at this thread :
How do I use extern to share variables between source files?
And I wonder if that may be the source of the problem? As I mentioned I use some variables which are part of the polygon calculation class and I instantiate them in the main .cpp of the dll. Two of those variables take the input data from the user and get it into the method that calculates the result and the third variable is filled with the result returned by that function.
Any help will be greatly appreciated as I am really stuck with it at the moment.
EDIT: The variables I use from the polygon source class are defined in its header as follows:
typedef std::vector< IntPoint > Polygon;
typedef std::vector< Polygon > Polygons;
DLL Test program
#include "stdafx.h"
#include "Clipper_lib.h"
int _tmain(int argc, _TCHAR* argv[])
{
int subj[]={100,100,200,100,200,200,100,200};
int clip[]={100,100,200,100,200,200,100,200};
vector<vector<int>> solution;
vector<vector<int>> solution1;
Execute(subj,clip,solution);
Execute(subj,clip,solution1);
return 0;
}
DLL header :
#include "clipper.hpp" /// this is the working C++ class of polygons operations
#include <vector>
using namespace ClipperLib;
using namespace std;
extern Polygon subj;
extern Polygon clip;
extern Polygons solution;
extern "C"
{
__declspec(dllexport) void Execute(int subj[],int clip[],vector<vector<int>> &solution);
}
DLL .cpp
// Clipper_lib.cpp : Defines the exported functions for the DLL application.
//
#include "Clipper_lib.h"
Clipper clipper;
void Execute(int subj[],int clip[],vector<vector<int>> &solution){
Polygon *subjP=new Polygon();
Polygon *clipP=new Polygon();
Polygons *solutionP=new Polygons();
for(int i=0; i<8;i+=2){
subjP->push_back(IntPoint(subj[i],subj[i+1]));
}
for(int b=0;b<8;b+=2){
clipP->push_back(IntPoint(clip[b],clip[b+1]));
}
clipper.Clear();
clipper.AddPolygon(*subjP,ptSubject);
clipper.AddPolygon(*clipP,ptClip);
clipper.Execute(ctIntersection,*solutionP);
for( vector<Polygon>::size_type d=0;d!=solutionP->size();++d){
vector<int> poly;
solution.push_back(poly);
for(vector<IntPoint>::size_type k=0;k!=solutionP[d].size();++k){
for(vector<IntPoint>::size_type s=0;s!=solutionP[d][k].size();++s){
int numX=(int)solutionP[d][k][s].X;
int numY=(int)solutionP[d][k][s].Y;
solution[d].push_back(numX);
solution[d].push_back(numY);
}
}
}
delete solutionP;
delete subjP;
delete clipP;
}
Well .Figured it out.Because the wrapper of this source was C based API I had to embrace all the C++ methods in the DLL with extern "C" .This way it works fine.Thanks for all the comments anyways .
The easier thing to do: after you used data from Polygons call clear() on it. clear() it's a fast method that keep allocated memory (in case you fear for efficiency) but mark the content as unavailable. So you can fill Polygons with new data without problems. Inner vectors, i.e. objects of type Polygon, will clear on request, you can ignore these.
Can you not debug your library call?
Eg. step through it in a debugger and try and see where the invalid values are getting set. Many IDE's let you set breakpoints that fire when data at a particular memory location changes. You could set a breakpoint on a value that you know gets set incorrectly on the second call, and it will show you what is changing it.
Typically, the way I'd define a true global constant (lets say, pi) would be to place an extern const in a header file, and define the constant in a .cpp file:
constants.h:
extern const pi;
constants.cpp:
#include "constants.h"
#include <cmath>
const pi=std::acos(-1.0);
This works great for true constants such as pi. However, I am looking for a best practice when it comes to defining a "constant" in that it will remain constant from program run to program run, but may change, depending on an input file. An example of this would be the gravitational constant, which is dependent on the units used. g is defined in the input file, and I would like it to be a global value that any object can use. I've always heard it is bad practice to have non-constant globals, so currently I have g stored in a system object, which is then passed on to all of the objects it generates. However this seems a bit clunky and hard to maintain as the number of objects grow.
Thoughts?
It all depends on your application size. If you are truly absolutely sure that a particular constant will have a single value shared by all threads and branches in your code for a single run, and that is unlikely to change in the future, then a global variable matches the intended semantics most closely, so it's best to just use that. It's also something that's trivial to refactor later on if needed, especially if you use distinctive prefixes for globals (such as g_) so that they never clash with locals - which is a good idea in general.
In general, I prefer to stick to YAGNI, and don't try to blindly placate various coding style guides. Instead, I first look if their rationale applies to a particular case (if a coding style guide doesn't have a rationale, it is a bad one), and if it clearly doesn't, then there is no reason to apply that guide to that case.
I can understand the predicament you're in, but I am afraid that you are unfortunately not doing this right.
The units should not affect the program, if you try to handle multiple different units in the heart of your program, you're going to get hurt badly.
Conceptually, you should do something like this:
Parse Input
|
Convert into SI metric
|
Run Program
|
Convert into original metric
|
Produce Output
This ensure that your program is nicely isolated from the various metrics that exist. Thus if one day you somehow add support to the French metric system of the 16th century, you'll just add to configure the Convert steps (Adapters) correctly, and perhaps a bit of the input/output (to recognize them and print them correctly), but the heart of the program, ie the computation unit, would remain unaffected by the new functionality.
Now, if you are to use a constant that is not so constant (for example the acceleration of gravity on earth which depends on the latitude, longitude and altitude), then you can simply pass it as arguments, grouped with the other constants.
class Constants
{
public:
Constants(double g, ....);
double g() const;
/// ...
private:
double mG;
/// ...
};
This could be made a Singleton, but that goes against the (controversed) Dependency Injection idiom. Personally I stray away from Singleton as much as I can, I usually use some Context class that I pass in each method, makes it much easier to test the methods independently from one another.
A legitimate use of singletons!
A singleton class constants() with a method to set the units?
You can use a variant of your latter approach, make a "GlobalState" class that holds all those variables and pass that around to all objects:
struct GlobalState {
float get_x() const;
float get_y() const;
...
};
struct MyClass {
MyClass(GlobalState &s)
{
// get data from s here
... = s.get_x();
}
};
It avoids globals, if you don't like them, and it grows gracefully as more variables are needed.
It's bad to have globals which change value during the lifetime of the run.
A value that is set once upon startup (and remains "constant" thereafter) is a perfectly acceptable use for a global.
Why is your current solution going to be hard to maintain? You can split the object up into multiple classes as it grows (one object for simulation parameters such as your gravitational constant, one object for general configuration, and so on)
My typical idiom for programs with configurable items is to create a singleton class named "configuration". Inside configuration go things that might be read from parsed configuration files, the registry, environment variables, etc.
Generally I'm against making get() methods, but this is my major exception. You can't typically make your configuration items consts if they have to be read from somewhere at startup, but you can make them private and use const get() methods to make the client view of them const.
This actually brings to mind the C++ Template Metaprogramming book by Abrahams & Gurtovoy - Is there a better way to manage your data so that you don't get poor conversions from yards to meters or from volume to length, and maybe that class knows about gravity being a form acceleration.
Also you already have a nice example here, pi = the result of some function...
const pi=std::acos(-1.0);
So why not make gravity the result of some function, which just happens to read that from file?
const gravity=configGravity();
configGravity() {
// open some file
// read the data
// return result
}
The problem is that because the global is managed prior to main being called you cannot provide input into the function - what config file, what if the file is missing or doesn't have g in it.
So if you want error handling you need to go for a later initialization, singletons fit that better.
Let's spell out some specs. So, you want:
(1) the file holding the global info (gravity, etc.) to outlive your runs of the executable using them;
(2) the global info to be visible in all your units (source files);
(3) your program to not be allowed to change the global info, once read from the file;
Well,
(1) Suggests a wrapper around the global info whose constructor takes an ifstream or file name string reference (hence, the file must exist before the constructor is called and it will still be there after the destructor is invoked);
(2) Suggests a global variable of the wrapper. You may, additionally, make sure that that is the only instance of this wrapper, in which case you need to make it a singleton as was suggested. Then again, you may not need this (you may be okay with having multiple copies of the same info, as long as it is read-only info!).
(3) Suggests a const getter from the wrapper. So, a sample may look like this:
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>//for EXIT_FAILURE
using namespace std;
class GlobalsFromFiles
{
public:
GlobalsFromFiles(const string& file_name)
{
//...process file:
std::ifstream ginfo_file(file_name.c_str());
if( !ginfo_file )
{
//throw SomeException(some_message);//not recommended to throw from constructors
//(definitely *NOT* from destructors)
//but you can... the problem would be: where do you place the catcher?
//so better just display an error message and exit
cerr<<"Uh-oh...file "<<file_name<<" not found"<<endl;
exit(EXIT_FAILURE);
}
//...read data...
ginfo_file>>gravity_;
//...
}
double g_(void) const
{
return gravity_;
}
private:
double gravity_;
};
GlobalsFromFiles Gs("globals.dat");
int main(void)
{
cout<<Gs.g_()<<endl;
return 0;
}
Globals aren't evil
Had to get that off my chest first :)
I'd stick the constants into a struct, and make a global instance of that:
struct Constants
{
double g;
// ...
};
extern Constants C = { ... };
double Grav(double m1, double m2, double r) { return C.g * m1 * m2 / (r*r); }
(Short names are ok, too, all scientists and engineers do that.....)
I've used the fact that local variables (i.e. members, parameters, function-locals, ..) take precedence over the global in a few cases as "apects for the poor":
You could easily change the method to
double Grav(double m1, double m2, double r, Constants const & C = ::C)
{ return C.g * m1 * m2 / (r*r); } // same code!
You could create an
struct AlternateUniverse
{
Constants C;
AlternateUniverse()
{
PostulateWildly(C); // initialize C to better values
double Grav(double m1, double m2, double r) { /* same code! */ }
}
}
The idea is to write code with least overhead in the default case, and preserving the implementation even if the universal constants should change.
Call Scope vs. Source Scope
Alternatively, if you/your devs are more into procedural rather thsn OO style, you could use call scope instead of source scope, with a global stack of values, roughly:
std::deque<Constants> g_constants;
void InAnAlternateUniverse()
{
PostulateWildly(C); //
g_constants.push_front(C);
CalculateCoreTemp();
g_constants.pop_front();
}
void CalculateCoreTemp()
{
Constants const & C= g_constants.front();
// ...
}
Everything in the call tree gets to use the "most current" constants. OYu can call the same tree of coutines - no matter how deeply nested - with an alternate set of constants. Of course it should be encapsulated better, made exception safe, and for multithreading you need thread local storage (so each thread gets it's own "stack")
Calculation vs. User Interface
We approach your original problem differently: All internal representation, all persistent data uses SI base units. Conversion takes place at input and output (e.g. even though the typical size is millimeter, it's always stored as meter).
I can't really compare, but worksd very well for us.
Dimensional Analysis
Other replies have at least hinted at Dimensional Analysis, such as the respective Boost Library. It can enforce dimensional correctness, and can automate the input / output conversions.