Return List from ROS subscriber - python

I have a ROS subscriber that passes data into a callback function, which then prints out all passed-on data. I would like to append all values that are printed out into a list, and to use that list outside of ROS.
I first thought about appending all data to the list in the callback function, and return the list. But when I tried to call and print the subscriber, which would not give me the list I wanted.

ROS callbacks do not return anything so you cannot rely on a return statement. The way this should be done is via setting a class attribute list. Take the following for example:
class mock_class:
def __init__(self):
rospy.init_node('my_node')
self.my_list = []
rospy.Subscriber('/some_topic', String, self.my_cb)
def my_cb(self, msg):
self.my_list.append(msg.data)
def get_data(self):
return self.my_list
Here every time the callback is called it will append the current data to a list that's stored as a class attribute. This keeps the data persistent and able to be retrieved at a later time.

Related

How to iteratively use a method of an iteratively created object in Python

I'm trying to create object iteratively by using a class method inside the class that the objects belong to. So everytime I call that class method it creates an object, and ads it to a dictionary with its proper idex (both are class variables). My problem comes when I want to call the same method of every object, but iteratively and with a random attribute each time. My code is large so here I coded a another program with exactly what I'm looking for so it's easier to understand.
class new_class:
objects = {} #this dictionary stores all objects of this class
i = 0 #used to iterate the dictionary and define every object separately
def __init__(self):
pass
def method(self, random): #<-- here goes the random elements that the method should be called with
return random #sample usage of the random value
#classmethod
def object_creator(cls):
cls.i += 1
cls.objects[cls.i] = cls() <-- this creates a new object of its own class and adds it to the dictionary with the key of the also iterated "i" variable
while True:
new_class.object_creator()
#Here I want to call for the method of evey existing object with random attributes
Calling the object this way, with the dictionary and its index doesn't work because it just calls the last created object, since the current index belongs to him.
while True:
new_class.object_creator()
new_class.objects[new_class.i].method()
I'm not sure if this is even possible because I would have to essentialy "create new code" for each created object. The only pseudo-solution I've found is to make another loop and make iterate through the length of the dictionary, and call the method of the object whose index is the loop's one, but that calls each method at a time and not all of them at the same time.
By default, your code is executed sequentially by a single thread, so the calls to the method will be done one after another. But it may be very quick to call all your objects' method because computers are fast. And from the point of view of the programming language, calling call_my_method_for_all_my_objects is no different than calling int("14").
If you really really (really) want to have code executed in parallel, you can have a look at multi-threading and multi-processing, but these are not easy topics. Don't bother with them if you don't actually want your program to execute faster or really need to have multiple code execution at the same time.
Using a dict instead of a list is not a real issue.
The problem with
while True:
new_class.object_creator()
new_class.objects[new_class.i].method()
is that at each iteration of the loop, it will create a new object (which increments i), then call the i-th object (newly created) method. It means that each object will have its method called only once, and in the creation order which is also i-ascending.
As for a solution, I recommand you to create a function or a method that will call for each of your objects. I decided to implement it as a static method of the class :
class new_class:
objects = {}
i = 0
def __init__(self):
pass
def method(self, random):
return random
#classmethod
def object_creator(cls):
cls.i += 1
cls.objects[cls.i] = cls()
#staticmethod # static
def call_each():
for i, obj in new_class.objects.items(): # iterate over the objects
print(obj.method(i)) # call each one's method, for example with its index
I used it like that :
# let's create 3 items for demonstration purposes
new_class.object_creator(); new_class.object_creator(); new_class.object_creator()
print(new_class.objects) # {1: <__main__.new_class object at 0x0000022B26285470>,
# 2: <__main__.new_class object at 0x0000022B262855C0>,
# 3: <__main__.new_class object at 0x0000022B262854A8>}
new_class.call_each() # prints 1 2 3
If you want to provide a random value for each call, add import random to your script and change the call_each method to :
#staticmethod
def call_each():
for obj in new_class.objects.values():
print(obj.method(random.random()))
so that
new_class.call_each() # prints 0.35280749626847374
# 0.22163283338299222
# 0.7368657784332368
If this does not answer your question, please please try to be extra clear in what you ask.

python: how to get result from a call functions in real time?

What I want to do is get result from call functions in real time.
For example, I want to get the result of i in class model in real time.However, if I use return,I can only get the result of i once.
import threading
class model(object):
"""docstring for model"""
def __init__(self):
pass
def func(self):
for i in range(1000):
print('i',i)
return i
class WorkThread(threading.Thread):
# trigger = pyqtSignal()
def __int__(self):
super(WorkThread,self).__init__()
def run(self):
model1=model()
result = model1.func() #I want to get `i` from class model in real time,however return can only get once.
print('result',result)
if __name__ == '__main__':
WorkThread=WorkThread()
WorkThread.start()
for j in range(1000,2000):
print('j',j)
Anyone has a good idea? Hopefully for help.
You have several options; you could:
Use a generator function, to produce the results as you iterate. This requires that the model1.func() call loops over the generator returned by the model1.func() call. Use this if you don't need access to the data from another thread.
Use a queue; push i results into the queue as you produce them, and another thread can receive them from the queue.

A Python class calculating the mean value of numbers being passed one by one to the class

I defined class Average as follows and it gives me the average of numbers.
class Average:
#lisst=[]
def __init__(self, value):
self.value=value
#Average.lisst.append(self)
def add(self, other,k):
return Average(self.value +(other.value-self.value)/float(k))
This is the question without any changes:
First: Write a Python class calculating the mean value of numbers being passed one by one to the class. It should have a put(x) method that feeds it a number and a get() method returning the mean value of the numbers passed so far.
Second: Write a framework class that has an append(o) method that takes an object like the ones above (i.e. ones that have a put method to process data and a get method to retrieve a result). It should itself have a put(x) method, which will pass the x on to all the objects o passed to it via append and a get method which will return a list containing the results of the get calls of all the contained
objects.
I don't actually understand what is want. I just need a hint to continue. Thanks.
PS This is not a mandatory class assignment and I do not get any point for it. Just to clarify that I am NOT cheating.
First and foremost, you should direct this question to the Powers That Be of your course: the instructor, teaching assistant, etc.
Second, do you have the original assignment wording? What you've written is inconsistent or incomplete in several respects.
However, to get you going in the meantime ...
an object like the ones above (i.e. ones that have a put method to
process data and a get method to retrieve a result)
Your Average class has neither at the moment; you have to add them. It appears that add might be the processing method.
It should itself have a put(x) method, which will pass the x on to all
the objects o passed to it via append
I'm confused here. append can construct a list, but it does not pass on objects. Were I designing the system, I'd take this as a hint that my user program should collect the Average objects in a list, and pass that list to the framework's put method.
a get method which will return a list containing the results of the
get calls of all the contained objects.
The framework needs to maintain a list of objects for which it is responsible. framework.get simply iterates through the Average.get for each object, returning a list of results.
In code terms, I'm seeing something like this:
class Average:
# stuff to add
def put(self, new_value):
...
def get(self):
return self.value
class Avg_FW:
def __init__(self, avg_list):
# maintain the list of all Average objects
def put(self, new_value):
# Invoke Average.put on each average in your list
def get(self):
# Invoke Average.get on each average in your list
# Return a list of the results
Does that clarify the structure enough to continue?
Does it match what you know about the course?
Create a class with a list variable (which you have already done).
You can use the default constructor.
The add/append/put function appends the input number to the list. You could also check to verify that the input is a number (int or float/double).
The average function returns the average of the numbers in the list.
The actual implementation is left to the reader as an exercise.

Python - Appending to a list of an object declared inside a for loop

I'm having a very specific problem that I could not find the answer to anywhere on the web. I'm new to python code (C++ is my first language), so I'm assuming this is just a semantic problem. My question is regarding objects that are declared inside the scope of a for loop.
The objective of this code is to create a new temporary object inside the for loop, add some items to it's list, then put the object into a list outside of the for loop. At each iteration of the for loop, I wish to create a NEW, SEPARATE object to populate with items. However, each time the for loop executes, the object's list is already populated with the items from the previous iteration.
I have a bigger program that is having the same problem, but instead of including a massive program, I wrote up a small example which has the same semantic problem:
#Test
class Example:
items = []
objList = []
for x in xrange(5):
Object = Example()
Object.items.append("Foo")
Object.items.append("Bar")
print Object.items
objList.append(Object)
print "Final lists: "
for x in objList:
print x.items
By the end of the program, every item in objList (even the ones from the first iterations) contains
["Foo","Bar","Foo","Bar","Foo","Bar","Foo","Bar","Foo","Bar"]`
This leads me to believe the Example (called Object in this case) is not recreated in each iteration, but instead maintained throughout each iteration, and accessed every time the for loop continues.
My simple question; in python, how to I change this?
Change your class definition to:
class Example:
def __init__(self):
self.items = []
The problem is that items is not being bound to the instance of each object, it is a part of the class definition. Because items is a class variable, it is shared between the instances of Example.
Your class Example is using a class variable Example.items to store the strings. Class variables are shared across all instances of the objects which is why you're getting them all together and thinking it's the same object when in fact, it is not.
You should create the items variable and assign it to self in your __init__ function
class Example(object):
def __init__(self):
self.items = []
This will ensure that each instance of Example has its own items list to work with.
Also, as you're using Python 2.x, you really should subclass object as I have there.

Extending a python list class to perform additional functions on its contents?

I want to create an object which will hold other objects, and call a method on each of the objects it holds. The end goal is to generate a script for a program. Each object contains a command that can be printed with printCommand(), eventually into a file. My original solution was this:
a = ObjectList()
a.appendObject(Object())
b = ObjectList()
b.appendObject(Object())
listOfObjects = [a, b]
for Object in listOfObjects:
Object.printCommand()
I create a list variable, add objects to thw list, then loop over it issuing the command. While this works, I am primarily doing this excersize to teach myself programming, so I want to know if there is a more elegant solution than writing code to append, pop, etc. items to a list in an object. Since list already contains these functions, i was thinking the correct thing to do would be to extend list:
class Object:
def __init__(self):
self.Command = "Script Command"
def printCommand(self):
print(self.Command)
class ObjectList(list):
def printCommand(self):
for Object in self.LISTCONTENTS:
Object.printCommand()
However, I am at a loss as to how I would tell it to iterate over its own contents. What belongs at self.LISTCONTENTS? Where does a list object store its contents, and how do you access them from a method?
You can just iterate over self:
The superclass methods (i.e., __iter__()) are all present. Saying self in the context of a for statement will cause the appropriate methods to be invoked.
class Object:
def __init__(self):
self.Command = "Script Command"
def printCommand(self):
print(self.Command)
class ObjectList(list):
def printCommand(self):
for Object in self:
Object.printCommand()
lst = ObjectList()
lst.append(Object())
lst.append(Object())
lst.printCommand()
The way this works is list implements __iter__ which is called behind the scenes when iterating over an object:
>>> for e in [1,2,3].__iter__():
... print(e)
...
1
2
3
>>> for e in [1,2,3]:
... print(e)
...
1
2
3
(a) Don't ever create a class called Object, that's far too close to object.
(b) There is absolutely no need to inherit from list, and frankly I doubt the need to use your own class at all.
(c) The normal way to invoke a function on every element of a list is to use map. If you need to map with the same function repeatedly, you can use partial to bind that function to map's first argument.
Now go look at the documentation.

Categories

Resources