nautilus27
Posts: 72
Joined: Fri May 22, 2015 9:38 pm

Python equivalent of map function in Arduino

Wed May 25, 2016 12:18 pm

Since I mostly work with Arduinos, I'm very new to Python and would like to know if there are any functions in Python that takes minimum and maximum values of a float and convert it to another range of values. I know map doesn't do float but you get the point.

For instance my analog thumbstick reports "-1.0" on left "1.0" on right. It reports values like " 0.46537373737" in between those. And I need convert this to an integer with the minimum value of 0 and maximum value of 10. How can I do this in Python?

User avatar
DougieLawson
Posts: 37653
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK
Contact: Website Twitter

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 12:39 pm

For your example this code works

Code: Select all

int_val = int(round(float_val * 10))
Note: Any requirement to use a crystal ball or mind reading will result in me ignoring your question.

Any DMs sent on Twitter will be answered next month.
All non-medical doctors are on my foes list.

Massi
Posts: 1691
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 12:42 pm

DougieLawson wrote:For your example this code works

Code: Select all

int_val = int(round(float_val * 10))
if it has to be 0-10 for the whole interval, you should multiply by 5 (scale) and then sum 5 (translate) :)

like

Code: Select all

int_val = int(float_val * 5 + 5)
isn't "round" covered implicitly by "int"?

PiGraham
Posts: 3780
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 12:44 pm

The Arduino docs give the function definition, if you can't work it out:

Code: Select all

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


PiGraham
Posts: 3780
Joined: Fri Jun 07, 2013 12:37 pm
Location: Waterlooville

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 12:51 pm

Massi wrote:
DougieLawson wrote:For your example this code works

Code: Select all

int_val = int(round(float_val * 10))
if it has to be 0-10 for the whole interval, you should multiply by 5 (scale) and then sum 5 (translate) :)

like

Code: Select all

int_val = int(float_val * 5 + 5)
isn't "round" covered implicitly by "int"?
That will do it. Or the equivalent :

Code: Select all

int_val = int((float_val + 1.0) * 10)

User avatar
scruss
Posts: 2895
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 1:02 pm

Wiring/Arduino inherited the map() function from Processing. The old code from the processing PApplet.java looks like this:

Code: Select all

  static public final double map(double value,
                                 double istart, double istop,
                                 double ostart, double ostop) {
    return ostart + (ostop - ostart) * ((value - istart) / (istop - istart));
(I linked to the simpler old code, as the new code involves some exception handling in Java that is too long for here)

This would translate into Python as something like:

Code: Select all

def valmap(value, istart, istop, ostart, ostop):
  return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))

print '%-8s %-6s' % ('Input', 'Output')
for x in range(21):
    inval = float((x - 10) / 10.0)
    print '%8.3f %6.1f' % (inval, valmap(inval, -1.0, 1.0, 0.0, 10.0))
I used the name valmap, as map() is already a built-in function that does something completely different.

NB: I know you asked for integer results, but I kept as close to the original Processing floating-point function.
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 1:06 pm

So, based on the OPs question, and the maths from the gang, the solution is to create a python function called map() that does precisely what the OP requires (and it takes in floats, and gives back ints).

pMapTest.py

Code: Select all

def map(x, in_min, in_max, out_min, out_max):
    return int((x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min)
run it...

Code: Select all

>>> from pMapTest import *
>>> map(.496, -1, 1, 0, 10)
7
>>> map(-1, -1, 1, 0, 10)
0
>>> map(1, -1, 1, 0, 10)
10
>>> 
>>> 
marcus
:ugeek:

Massi
Posts: 1691
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 1:52 pm

MarkHaysHarris777 wrote:So, based on the OPs question, and the maths from the gang, the solution is to create a python function called map() that does precisely what the OP requires (and it takes in floats, and gives back ints).
definitely no.

https://docs.python.org/2/library/functions.html#map

(as said above)

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 2:00 pm

Massi wrote:
MarkHaysHarris777 wrote:So, based on the OPs question, and the maths from the gang, the solution is to create a python function called map() that does precisely what the OP requires (and it takes in floats, and gives back ints).
definitely no.

https://docs.python.org/2/library/functions.html#map

(as said above)
Nope... incorrect paradigm ! Think out of the box. We're importing a special case that we only need to import for this one app. It depends on whether your app needs the built-in, and whether any of the imported cruft in the app also needs the built-in.

But, call it whatever you want to! The name is not important; its what it does that matters... a rose is a rose by any other name...

here:

Code: Select all

def my_map(x, in_min, in_max, out_min, out_max):
    return int((x-in_min) * (out_max-out_min) / (in_max-in_min) + out_min)
edit: ... and another thing, the fact that Python uses namespace(s) allows us to create all kinds of
map() functions by the same name, because we are going to import them into a different namespace. This is an important Python concept; a part of the zen of Python: to wit-- near the bottom:

Code: Select all

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!  
>>> 
marcus
:ugeek:

User avatar
scruss
Posts: 2895
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 4:26 pm

MarkHaysHarris777 wrote:allows us to create all kinds of
map() functions by the same name
So you can silently overwrite builtins? There's no way this will end badly …
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 4:31 pm

scruss wrote:
MarkHaysHarris777 wrote:allows us to create all kinds of
map() functions by the same name
So you can silently overwrite builtins? There's no way this will end badly …
No, no, no... not at all... you qualify the names into the namespaces where you'll be using them. For instance the map() function I wrote would be part of a module called (maybe) my_translations.py and would be pulled in with:

Code: Select all

import my_translations as XLATE
Then, I would use the map function like this:

Code: Select all

XLATE.map(.469, -1, 1, 0, 10)
This is no different than how you use the RPi.GPIO module; or any other module. Each module is free to have names that are 'like' because the module provides a new namespace!

edit: PS In the above example (not to be too pedantic about it) XLATE becomes a new namespace. The names common to XLATE (part of the my_translations.py module) will NOT conflict with any other names in other namespaces, including the primary namespace (built-ins).
marcus
:ugeek:

User avatar
scruss
Posts: 2895
Joined: Sat Jun 09, 2012 12:25 pm
Location: Toronto, ON
Contact: Website

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 6:58 pm

MarkHaysHarris777 wrote:No, no, no... not at all...

Code: Select all

#!/usr/bin/env python

a=[1,2,3]
b=map(lambda x: x+5, a)
print b					# builtin: gives [6, 7, 8]

def map(value, istart, istop, ostart, ostop):
  return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))

print map(5.0, 4.0, 6.0, 100.0, 200.0) 	# if redefined, prints 150.0

c=map(lambda x: x*5, a)
print c					# so what happens here?
Output:

Code: Select all

[6, 7, 8]
150.0
Traceback (most recent call last):
  File "./valmap-orly.py", line 12, in <module>
    c=map(lambda x: x*5, a)
TypeError: map() takes exactly 5 arguments (2 given)
So Python doesn't stop you from redefining a builtin.
‘Remember the Golden Rule of Selling: “Do not resort to violence.”’ — McGlashan.

User avatar
MarkHaysHarris777
Posts: 1820
Joined: Mon Mar 23, 2015 7:39 am
Location: Rochester, MN
Contact: Website

Re: Python equivalent of map function in Arduino

Wed May 25, 2016 7:14 pm

scruss wrote: So Python doesn't stop you from redefining a builtin ...
Of course not ...

... but why would you do that?

Well, these are some reasons; there are probably more...
1) the built-in might not be as robust as the function() you just invented
2) the built-in might be broken
3) the built-in might introduce a side-affect in your environment

edit: PS This is the primary reason for using namespaces... in Python we don't worry about reserved words (names) because our names are neatly tucked inside our namespaces where they won't conflict... unless of course we want them to !
marcus
:ugeek:

nautilus27
Posts: 72
Joined: Fri May 22, 2015 9:38 pm

Re: Python equivalent of map function in Arduino

Thu May 26, 2016 12:33 am

Thanks everybody, i learnt a lot about Python today.

Return to “Python”