Cannot get cf.param.set_value to work

Firmware/software/electronics/mechanics
Post Reply
f-rower
Beginner
Posts: 16
Joined: Wed Jun 14, 2017 10:19 am

Cannot get cf.param.set_value to work

Post by f-rower »

Hi,

I know there's a question which is almost the same as mine somewhere on the forum, but it still has not solved my problem...

I am currently trying to change the value of just the attitude pitch kd value, and for that I have been following the instructions provided in the wiki and followed the logic in the basicparam.py example. This is the code that I am currently using (extract of the relevant bits):

Code: Select all

   
    def _param_update_kd(self):

        param_name = "pid_attitude.pitch_kd"
        param_value = "10000"
        self._cf.param.set_value(param_name,param_value)
        self._cf.param.add_update_callback(group = "pid_attitude",name = "pitch_kd",cb =self._readparam)
        self._cf.param.request_param_update("pid_attitude.pitch_kd")
        
        # run cf for 5s to check if parameters have changed
        self._cf.commander.send_setpoint(0, 0, 0, 0)
        the_time = time.time()
        while the_time + 5 > time.time():
            self._cf.commander.send_setpoint(0, 0, 0, 1000)
        # Close link
        
        self._cf.close_link()

    def _readparam(self,name,value):
        print("%s has value %d" % (name,value))
However, for some reason the function readparam is not being called, because I can't see any output on the console, and this is what I suspect is causing the attitude pitch kd parameter not to update. However, the code that runs the cf for 5 seconds still runs. I really have no idea what I'm doing wrong to be honest. Any help/ hints on why this could not be working?

f-
f-rower
Beginner
Posts: 16
Joined: Wed Jun 14, 2017 10:19 am

Re: Cannot get cf.param.set_value to work

Post by f-rower »

Hi, just giving a quick bump on this issue. I have been trying for the past few days and still can't figure out what I'm doing wrong here :(
arnaud
Bitcraze
Posts: 2538
Joined: Tue Feb 06, 2007 12:36 pm

Re: Cannot get cf.param.set_value to work

Post by arnaud »

One thing I see that could cause the problem is that you are setting up the callback after setting the param, have you tried to first setup all the callback and then set the parameters? Ideally the callbacks should be set way earlier, in the 'connected' callback.

If you connect to the Crazyflie with the client after running this script, do you see that the param has changed?
f-rower
Beginner
Posts: 16
Joined: Wed Jun 14, 2017 10:19 am

Re: Cannot get cf.param.set_value to work

Post by f-rower »

Hi Arnaud, thanks for replying :)

Yes, I have tried swapping them around, and sometimes it works, sometimes it doesn't: I think the problem is I can't finish grasping what's the point of using param_add_update_callback, and how to use it. What exactly is its functionality? I thought it just executes the specified callback once the specified parameter has been set with param.set_value. However, if I wrote the following code:

Code: Select all

    def _connected(self, link_uri):

        self._cf.param.add_update_callback(group='pid_attitude', name='pitch_kp',
                                           cb=self._param_kp_callback)
        #self.do_something() #Why is the do_something function executed before self._cf.param.add_update_callback?
This will still execute the self._param_kp_callback function even if I haven't yet used param.set_value. Furthermore, if I uncomment the self.do_something() function, this function will be executed first, and then, once it's done, self._param_kp_callback will be executed, which is confusing me even more :?

Essentially what I want to do is to have my main code running, then at some point change the attitude pid parameters, and then let my code continue with the updated pid parameters. Something like this:

Code: Select all

def main_code():
    #do stuff
    
    if event = True:
        #Now I need to change the attitude PID parameters:
        attitude_pid_change()
    
def attitude_pid_change():
    
    #change attitude PID parameters
    
    if pid_parameters_are_changed = True
        
        #Return to main code with the new PID parameters
kristoffer
Bitcraze
Posts: 630
Joined: Tue Jun 30, 2015 7:47 am

Re: Cannot get cf.param.set_value to work

Post by kristoffer »

A short example that connects to a CF using the SyncCrazyflie class, sets up a listener for pid_attitude updates and then updates pid_attitude.pitch_kd. Hope it helps.

Code: Select all

import logging
import time

import cflib.crtp
from cflib.crazyflie.syncCrazyflie import SyncCrazyflie

logging.basicConfig(level=logging.ERROR)


def _param_change_callback(name, value):
    print(name + ' changed to value ' + value)


if __name__ == '__main__':
    # Initialize the low-level drivers (don't list the debug drivers)
    cflib.crtp.init_drivers(enable_debug_driver=False)

    URI = 'radio://0/70/2M/E7E7E7E7E7'

    with SyncCrazyflie(URI) as scf:
        # Set up a listener to print updates
        scf.cf.param.add_update_callback(group='pid_attitude', name=None,
                                         cb=_param_change_callback)

        time.sleep(1)

        print()
        print("Changing parameter")
        scf.cf.param.set_value('pid_attitude.pitch_kd', '{:.2f}'.format(0.17))

        time.sleep(1)
Post Reply