Tutorial primitives

There is something I don’t understand with the primitives, for example :

from pypot.primitive import Primitive
class DancePrimitive(Primitive):
    def run(self, amp=30, freq=0.5):
        # self.elapsed_time gives you the time (in s) since the primitive has been running
        while self.elapsed_time < 1:
            x = amp * numpy.sin(2 * numpy.pi * freq * self.elapsed_time)
           
            self.robot.head_z.goal_position = x
            self.robot.head_y.goal_position = -x

            time.sleep(0.05) 

My question is, how is it possible to change amp when starting the primitive.

dance = DancePrimitive()
dance.start(amp=60)

The code above doesn’t work because the start method doesn’t accept any argument… I can overwrite the init method with an amp argument but in this case, I don’t need to define amp in the run method… So if someone can help the beginner I am with primitive I will be very grateful.

The error is because the start function does indeed not accept an argument. What the start function does is it starts a thread and the thread will use the run function
Start function of the primitive.py file:

def start(self):
        if not self.robot._primitive_manager.running:
            raise RuntimeError('Cannot run a primitive when the sync is stopped!')

        StoppableThread.start(self)
        self.wait_to_start()

        logger.info("Primitive %s started.", self)

I don’t know how you are supposed to change the amplitude with this code.
What you should do (I think) is to add an amplitude field in the DancePrimitive object:

from pypot.primitive import Primitive
class DancePrimitive(Primitive):
    def __init__(self, amp=30, freq=0.5):
        Primitive.__init__(self)
        self.amp = amp
        self.freq=freq

def run(self):
    # self.elapsed_time gives you the time (in s) since the primitive has been running
    while self.elapsed_time < 1:
        x = self.amp * numpy.sin(2 * numpy.pi * self.freq * self.elapsed_time)
       
        self.robot.head_z.goal_position = x
        self.robot.head_y.goal_position = -x

        time.sleep(0.05)

And then create your dance object:

dance = DancePrimitive(amp=60)
dance.start()

Warning, I didn’t test the code

Hi,
@Pierre should answer your better, but as far as I know (and looking Primitive code) it is an outdated feature.
I think that the good way is to override the _init_ method (don’t forget to call the super constructor).
Feel free to make pull requests for old or unclear documentation.

EDIT: I didn’t refresh the page so I didn’t see Manon post. She just forget the super constructor:

def __init__(self, robot, amp=30, freq=0.5):
        self.robot = robot
        self.amp = amp
        self.freq = freq
        pypot.primitive.Primitive.__init__(self, robot)

Arg, it was there, but wrong (I missed the robot argument).

And yes, the documentation should be updated.

Thanks @Manon and @Theo

So if I have a walking primitive, the call should look like :

walk  = walking_primitive(robot,speed=slow)
walk.start()

and to change the speed, I can re-instanciate the object walking_primitive :

walk = walking_primitive(robot,speed=fast)
walk.start()

or I can just change attribut of the primitive :

walk.speed=fast
walk.start()
1 Like

Both methods should work, but the second one is better. Make sure the dance is finished before re starting it.

Yes indeed, this was an old feature of the primitive which is not supported anymore. Mostly because it wasn’t really clear how to use it.

I have raised an issue to update the doc. This will be for the next pizza doc session :smile:

Do not hesitate to directly raise issue if you see something outdated!