Animation don't move with an Amature

I program a code WriteAmatureAnimation :

def writeAnimationAmature(ident,
                    used_UV,
                     dico,
                     key_tab,
                     tab,
                     key2_tab_anim_texture,
                     tab_anim_texture,
                     mesh_id_coords,
                     name_obj,
                     scene,
                     frame_rate):
        print("dicoAma : ", dico)
       
        if use_animation:
            name_obj = (name_obj[1:(len(name_obj)-1)])

            start_frame = scene[0].frame_start
            end_frame = scene[0].frame_end
            fw('%s<TimeSensor DEF="time_%s" cycleInterval="%s" loop="true" enabled="true"></TimeSensor>\n' % (ident, name_obj, (end_frame - start_frame) / frame_rate))
             
            for type_animation in dico.keys():
                new_name_obj=""
                debut = type_animation.find('"') + 1
                fin = type_animation.find('"', debut) 
                if debut != -1 and fin != -1:
                    new_name_obj = type_animation[debut:fin]
                    new_name_obj =new_name_obj.replace('.', '_')
                print('le nouveau nom', new_name_obj)
                if 'location' in type_animation :
                    fw('\n%s<PositionInterpolator DEF="location_%s" key="' % (ident, new_name_obj))

                    for key in dico[type_animation].keys():
                        fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
                    fw('" keyValue="')
                    counter =0

                    #sub_value = dico[type_animation].values()
                    #print("sub_value : MIAOU : ",sub_value) 
                    #list_sub_value = list(sub_value)
                    fw('0.5 0.5 0.5 1 1 1 2 2 2 3 3 3')
                    fw(' ')
                
                    fw('"></PositionInterpolator>\n')
                    fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="location_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, new_name_obj))
                    fw('%s<ROUTE fromNode="location_%s" fromField="value_changed" toNode="%s" toField="translation"></ROUTE>\n' % (ident, new_name_obj, new_name_obj))
                print("type_animation123" , type(type_animation))
                if 'rotation_euler' in type_animation or 'rotation_axis_angle' in type_animation or 'rotation_quaternion' in type_animation :
                    print("rotation_euler rotation_axis_angle ok")
                    fw('\n%s<OrientationInterpolator DEF="rotation_%s" key="' % (ident, new_name_obj))

                    for key in dico[type_animation].keys():
                        fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
                    fw('" keyValue="')
                    counter =0

                    #sub_value = dico[type_animation].values()
                    #print('subissons ',sub_value)
                    #list_sub_value = list(sub_value)
                    fw('0.5 0.5 0.5 0.5 0.5 1 1 1 1 2 2 2 2 3 3 3 3')
                    fw(' ')

                    fw('"></OrientationInterpolator>\n')
                    fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="rotation_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, new_name_obj))
                    fw('%s<ROUTE fromNode="rotation_%s" fromField="value_changed" toNode="%s" toField="set_rotation"></ROUTE>\n' % (ident, new_name_obj, new_name_obj))

                if 'scale' in type_animation:
                    print("scale ok")
                    fw('\n%s<PositionInterpolator DEF="scale_%s" key="' % (ident, new_name_obj))

                    for key in dico[type_animation].keys():
                        fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
                    fw('" keyValue="')
                    counter =0
                    sub_value = dico[type_animation].values()
                    list_sub_value = list(sub_value)
                    
                    for i in range(0, len(list_sub_value),3):
                        tab = list_sub_value[i:i+3]
                        if not (len(tab) < 3 ) :
                            fw('%s %s %s'%(tab[2],tab[1],-tab[0]))
                            fw(' ')

                    fw('"></PositionInterpolator>\n')
                    fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="scale_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, new_name_obj))
                    fw('%s<ROUTE fromNode="scale_%s" fromField="value_changed" toNode="%s" toField="scale"></ROUTE>\n' % (ident, new_name_obj, new_name_obj))

            if key_tab !=0 and tab!=0:
                fw('\n%s<CoordinateInterpolator DEF="coordinateInterpolation_%s" key="' % (ident, name_obj))
                for key  in key_tab:
                    key_int = int(key)
                    print('taille de la key: ', len(key_tab))
                    fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
                    fw('')
                fw('" keyValue="')  
                print('tab_final :  ',tab)
                print ('taille du tab_final : ',len(tab))
                for valeur in tab:
                    fw('%s %s %s'%(valeur[0],valeur[1],valeur[2]))
                    fw(' ')
                fw('"></CoordinateInterpolator>\n')
                fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="coordinateInterpolation_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, name_obj))
                fw('%s<ROUTE fromNode="coordinateInterpolation_%s" fromField="value_changed" toNode=%s toField="point"></ROUTE>\n' % (ident, name_obj, mesh_id_coords))

            if key2_tab_anim_texture !=0 and tab_anim_texture !=0: 
                
                iteration =0
                for uv in used_UV:
                    fw('\n%s<CoordinateInterpolator2D DEF="coordinateInterpolaton2D_%s" key="' % (ident, uv))
                    
                    for key  in key2_tab_anim_texture:
                        key_int = int(key)
                        print('taille de la key: ', len(key2_tab_anim_texture))
                        fw('%s ' % ((key - start_frame)/(end_frame - start_frame)))
                        fw('')
                    fw('" keyValue="')
                    print('putin t es grand : ', len(tab_anim_texture))
                    for i in range( int((len(tab_anim_texture)/len(used_UV)))*iteration,(int(len(tab_anim_texture)/len(used_UV)))*(1+iteration)):
                        print("valeur de i : ",i , 'avec comme iteration : ',iteration) 
                        valeur = tab_anim_texture[i]
                        fw('%s %s '%(valeur[0],valeur[1]))
                        fw(' ')
                    iteration = iteration +1
                    fw('"></CoordinateInterpolator2D>\n')
                    fw('%s<ROUTE fromNode="time_%s" fromField="fraction_changed" toNode="coordinateInterpolaton2D_%s" toField="set_fraction"></ROUTE>\n' % (ident, name_obj, uv))
                    fw('%s<ROUTE fromNode="coordinateInterpolaton2D_%s" fromField="value_changed" toNode="%s" toField="point"></ROUTE>\n' % (ident, uv,uv))                    
              

This code is a function called writeAnimationAmature that generates animations for an object using the X3d format. Here is an overview of how this function works:
This code is a function called writeAnimationAmature that generates animations for an object using the X3d format. Here is an overview of how this function works:
Function Parameters:

    ident: indentation for the text output.
    used_UV: UV coordinates used for texture animation.
    dico: dictionary containing animation information (position, rotation, scale).
    key_tab: array of animation keys.
    tab: array of coordinates.
    key2_tab_anim_texture: array of texture animation keys.
    tab_anim_texture: array of texture animation coordinates.
    mesh_id_coords: identifier for the mesh coordinates.
    name_obj: name of the animated object.
    scene: scene containing timeline information.
    frame_rate: frame rate of the animation.

Variable Declaration:
The object’s name is extracted and modified to remove quotation marks.

Animation Setup:
Start and end frames are defined from the scene.
A X3d TimeSensor is created to manage the timing of the animation.

Handling Animation Types:
For each animation type in dico, the code generates X3d interpolators (PositionInterpolator, OrientationInterpolator, etc.) based on the type of animation (position, rotation, scale).

Creating Interpolators:

    Position: Generates keys and values for position interpolation.
    Rotation: Generates keys and values for rotation interpolation.
    Scale: Generates keys and values for scale interpolation.

X3d Routes:
Creates X3d routes linking the interpolators to the TimeSensor and the corresponding fields of objects to animate the transformations (position, rotation, scale).

Texture Animation:
If texture animations are present, they are handled similarly with 2D interpolators.
Output:
Information is written using the fw function, it write to a file or output stream.
For the fw('0.5 0.5 0.5 1 1 1 2 2 2 3 3 3) , i write this because i want to try with a numbers to show if my amature move . When i make the true number , i have one number or two number and not 3 number for one keyframe.

And writeAmature :

   def writeAmature(ident ,  obj,   amature):
        
        obj_id = quoteattr(unique_name(amature, OB_ + amature.name, uuid_cache_object, clean_func=clean_def, sep="_"))
        dico_animation = {}
        if amature.animation_data.action != None: 
            scene=bpy.data.scenes
            key_amature = []                
            stop =0
            print('existe un anime : ', amature.animation_data)
            for fc in amature.animation_data.action.fcurves: # ajout des key dans le tableur 2 
                for key in fc.keyframe_points :   
                        if stop == 0:
                            key_amature.append(int(key.co[0]))
                        print('time : ',int(key.co[0]))
                stop =1    
                print('key_amature',key_amature)
                
        armute_all =[]
                    
        print('le type de l objet est : ', amature.type)
        amature1= amature.data
        for joint in amature1.bones:
        
            if not joint.name.endswith("_end"):
                armute_all.append(joint.name)  
        print('armature est de : ',armute_all) 
        key_tab=[]
        tab_finale= []
        
        for fc in amature.animation_data.action.fcurves :
            print("fc : ",fc)
            print("type blblblbl : ", fc.data_path)
            if fc.data_path.endswith(('location','rotation_euler','rotation_quaternion','scale', 'rotation_axis_angle')) or "key_blocks" in fc.data_path:
                print("if 2")
                dico_key = {}
                                
                for key in fc.keyframe_points :
                    print(fc.data_path,": ",key.co)
                    dico_key [key.co[0]] = key.co[1]

                    if fc.data_path not in dico_animation:
                        dico_animation [fc.data_path] = dico_key
        print('dico_animation : ',dico_animation) 
        
        for type_anim in dico_animation.keys():
             for key, value in dico_animation[type_anim].items():
                if type_anim == "location":
                    dico_animation[type_anim][key] = value[1:] + value[:1]

                                
                elif type_anim == "rotation_axis_angle":
                    dico_animation[type_anim][key] = [-value[2]] + [-value[3]] + [-value[1]] + [value[0]]
                                
                elif type_anim == "rotation_euler":
                    euler = mathutils.Euler((value[0], value[1], value[2]), "XYZ")

                    euler = mathutils.Euler((euler.x, euler.z, -euler.y), "XYZ")
                    print("\n\nblender euler: ",euler)
                    quat = euler.to_quaternion()
                    print("blender quaternion:\n",quat_str(quat))
                    print("blender axisangle: ",quat.to_axis_angle())
                    print("my quaternion:\n",quat_str(eulerToQuat(euler.x,euler.y,euler.z)))
                    axis = quat.to_axis_angle()
                    #axis = toAxisAngle(quat) # retourne un vecteur + un angle
                    #axis = toAxisAngle(eulerToQuat(euler.x,euler.y,euler.z))
                    print("Final axisAngle :    x : ", axis[0].x, " y : ", axis[0].y, " z : ", axis[0].z, "angle : ", axis[1])
                    #dico_animation[type_anim][key] = [-axis[0].y] + [-axis[0].z] + [-axis[0].x] + [axis[1]]
                    dico_animation[type_anim][key] = [axis[0].x] + [axis[0].y] + [axis[0].z] + [axis[1]]           
        
        writeAnimationAmature(ident,0, dico_animation,0,0,0,0,0, obj_id, bpy.data.scenes, bpy.context.scene.render.fps)


This code is a function called writeAmature that extracts animation data from an armature object in Blender and prepares it for export in X3d. Here is an overview of how this function works:

Function Parameters:

    ident: indentation for text output.
    obj: 3D object.
    amature: armature of the object.

Variable Preparation:
    obj_id: unique identifier for the armature, obtained using a unique_name function.
    dico_animation: dictionary to store animation data.

Checking for Animation Data:
Checks if the armature has animation data. If so, retrieves scenes and initializes key_amature.

Extracting Keyframes:
Iterates through the armature’s animation curves (fcurves) to extract keyframe points and adds them to key_amature.

Extracting Joint Names:
Iterates through the armature’s bones to extract joint names (excluding those ending in “_end”).

Creating Tables and Extracting Animation Data:
Iterates through the animation curves to identify those related to position (location), rotation (rotation_euler, rotation_quaternion, rotation_axis_angle), and scale (scale).
Stores keyframe data in dico_animation.

Converting Animation Data:
For each animation type, converts the keyframe values into X3d-compatible formats:
Position: Adjusts position values.
Rotation Axis Angle: Converts rotation values into axis-angle format.
Rotation Euler: Converts Euler values into quaternion, then into axis-angle format.

Calling the Writing Function:
Calls writeAnimationAmature to generate X3d animations using the prepared data.

the ‘0’ in writeAnimationAmature when the code call writeAnimationAmature , it is because i don’t finish all parameter , i try the parameter to move , scale and rotate.

So with two functions , when i call there and export on x3D , the amature don’t move and i don’t konw why ?