making a ball roll with drivers
The problem with combining Euler rotations from different axes is that the order of rotations is significant. For example, rotating along the y-axis then the x-axis is not equivalent to rotating along the x-axis then the y-axis.

One way monkey looks to the right the other it points down


Since the final rotation is dependent upon the order of individual rotations, we are unable to absolutely determine the rotation from the x and y coordinates. However, if we assume that rotation only occurs perpendicular to displacement, we can approximate the appearance of an object rolling by rotating it when the location changes.

For this approach, we store the object's previous position in order to calculate the difference in location. We create a rotation matrix with the magnitude for the angle and the normal as its axis. Then, we combine the rotation matrix and extract its Euler rotation. The script makes a modal operator which rolls the active object when it is called.

import bpy
from mathutils import Matrix, Vector

class RollOperator(bpy.types.Operator):
    bl_idname = "transform.roll"
    bl_label = "Roll active object"

    def execute(self, context):
        dx = self.dx / 100
        dy = self.dy / 100

        matrix = Matrix.Rotation((dx**2 + dy**2)**.5, 4, Vector((-dy, dx, 0)))
        matrix *= context.object.matrix_world
        context.object.rotation_euler = matrix.to_euler('XYZ')
        context.object.location.x += dx
        context.object.location.y += dy
        return {'FINISHED'}

    def modal(self, context, event):
        if event.type == 'MOUSEMOVE':  # Apply
            self.dx = event.mouse_x - event.mouse_prev_x
            self.dy = event.mouse_y - event.mouse_prev_y            
            self.execute(context)
        elif event.type == 'LEFTMOUSE':  # Confirm
            return {'FINISHED'}
        elif event.type in ('RIGHTMOUSE', 'ESC'):  # Cancel
            context.object.location = self.location
            context.object.rotation_euler = self.rotation_euler
            return {'CANCELLED'}
        return {'RUNNING_MODAL'}

    def invoke(self, context, event):
        rotation = context.object.rotation_euler
        location = context.object.location
        self.location = location[0], location[1], location[2]
        self.rotation_euler = rotation[0], rotation[1], rotation[2]        
        self.dx = 0
        self.dy = 0        
        self.execute(context)
        context.window_manager.modal_handler_add(self)
        return {'RUNNING_MODAL'}


bpy.utils.register_class(RollOperator)


After running the script, add a shortcut key to start it. This one used ShiftQ in the 3D View.



With the operator, the monkey rolls as it moves.