Ejemplo n.º 1
0
def _check_velocity_of_axes(robot, command_dicts, framerate):
    """
    Check a list of commands for velocity errors. Construct string to return
    printable statement of all exceeded velocities for each axis; ex. range
    [0, 1, 2, 3] will be formatted '0-3'.
    :param robot: name string of the selected robot
    :param command_dicts: A list of list of robot axes
    :param framerate: Maya animation framerate (fps)
    :return:
    """
    frames = [c['Frame'] for c in command_dicts]
    axes_at_each_frame = [c[postproc.AXES] for c in command_dicts]
    velocity_limits = mimic_utils.get_velocity_limits(robot)
    max_velocities = [0 for _ in range(6)]
    max_velocities_frames = [0 for _ in range(6)]
    violations = {}
    _previous_frame = 0
    _previous_axes = []

    for i in range(len(axes_at_each_frame)):
        # Get time and axes right now
        _current_frame = frames[i]
        _current_axes = axes_at_each_frame[i]
        if i > 0:  # skip zeroth
            displacement_time = abs(_current_frame -
                                    _previous_frame) / framerate
            for j in range(len(_current_axes)):
                _previous_axis = _previous_axes[j]
                _current_axis = _current_axes[j]
                displacement = abs(_current_axis - _previous_axis)
                velocity = displacement / displacement_time
                # Record max velocities
                if velocity > max_velocities[j]:
                    max_velocities[j] = velocity
                    max_velocities_frames[j] = _current_frame
                # Check if a limit has been violated
                if velocity > velocity_limits[j]:
                    # Add axis name to violations dict
                    axis_name = 'Axis {}'.format(j + 1)
                    if axis_name not in violations:
                        violations[axis_name] = []
                    # Add time to violations dict
                    violations[axis_name].append(_current_frame)
        _previous_frame = _current_frame
        _previous_axes = _current_axes

    # TODO: This is a hack!
    print 'Max velocities:'
    template_string = '>>> {0:>{padding1}}{1:>{padding2}}{2:>{padding3}}'
    print template_string.format('A',
                                 'Velocity',
                                 'Frame',
                                 padding1=2,
                                 padding2=10,
                                 padding3=10)
    for i in range(6):
        print template_string.format(
            i + 1,
            general_utils.num_to_str(max_velocities[i], precision=3),
            general_utils.num_to_str(max_velocities_frames[i], precision=3),
            padding1=2,
            padding2=10,
            padding3=10)

    # Format a warning
    warning_params = []
    # Get axis keys in order
    axes = violations.keys()
    if axes:
        axes.sort()
        for axis_name in axes:
            # Check if the axis key has values
            times = violations[axis_name]
            time_ranges = general_utils.list_as_range_strings(times)
            time_ranges_formatted = '\n'.join('\t{}'.format(time_range)
                                              for time_range in time_ranges)
            warning_params.append(axis_name)
            warning_params.append(time_ranges_formatted)
        # Create warning
        warning = 'WARNING!\n' \
                  'Velocity limits have been violated!\n' \
                  'See the following frames:\n'
        warning_params.insert(0, warning)
        return '\n'.join(warning_params) + '\n', max_velocities
    else:
        return '', max_velocities
Ejemplo n.º 2
0
def _check_command_dicts(command_dicts, robot, animation_settings,
                         postproc_settings, user_options):
    """
    Check command dictionary for warnings.
    :param command_dicts: A list of list of robot axes
    :param robot_name: Name of the robot
    :param animation_settings: User-defined animation settings.
    :param postproc_settings: User-defined program settings.
    :param user_options: User-defined postproc options.
    :return: True if warning, False otherwise
    """
    # Check to see if the user has elected to ignore warnings
    ignore_warnings = postproc_settings['Ignore Warnings']
    warning = ''  # Temporary holder

    # Check if limits have been exceeded (i.e. velocity, acceleration)
    if user_options.Include_axes and not user_options.Ignore_motion:
        # TODO: Add UI options to select which violations, max/min/avg user wants to check

        # Check position limits
        position_limits = mimic_utils.get_axis_limits(robot)
        if position_limits['Axis 1']['Min Limit'] is None:
            position_warning = 'Unable to check position limits. Robot rig does not contain position data.\n'
            pm.scrollField(OUTPUT_WINDOW_NAME,
                           insertText=position_warning,
                           edit=True)
        position_violations, position_stats = _check_command_dicts_limits(
            command_dicts,
            limits=position_limits,
            get_min=True,
            get_max=True,
            get_average=True)

        # Check velocity limits
        velocity_limits = mimic_utils.get_velocity_limits(robot)
        velocity_dicts = analysis_utils._generate_derivative_dicts(
            command_dicts, 1)
        if velocity_limits['Axis 1']['Min Limit'] is None:
            velocity_warning = 'Unable to check velocity limits. Robot rig does not contain velocity data.\n'
            pm.scrollField(OUTPUT_WINDOW_NAME,
                           insertText=velocity_warning,
                           edit=True)
        velocity_violations, velocity_stats = _check_command_dicts_limits(
            velocity_dicts,
            limits=velocity_limits,
            get_min=True,
            get_max=True,
            get_average=True)

        # Check acceleration limits
        acceleration_limits = mimic_utils.get_acceleration_limits(robot)
        acceleration_dicts = analysis_utils._generate_derivative_dicts(
            velocity_dicts, 2)
        if acceleration_limits['Axis 1']['Min Limit'] is None:
            acceleration_warning = 'Unable to check acceleration limits. Robot rig does not contain acceleration data.\n'
            pm.scrollField(OUTPUT_WINDOW_NAME,
                           insertText=acceleration_warning,
                           edit=True)
        acceleration_violations, acceleration_stats = _check_command_dicts_limits(
            acceleration_dicts,
            limits=acceleration_limits,
            get_min=True,
            get_max=True,
            get_average=True)

        # Check jerk limits
        jerk_limits = mimic_utils.get_jerk_limits(robot)
        jerk_dicts = analysis_utils._generate_derivative_dicts(
            acceleration_dicts, 3)
        if jerk_limits['Axis 1']['Min Limit'] is None:
            jerk_warning = 'Unable to check jerk limits. Robot rig does not contain jerk data.\n'
            pm.scrollField(OUTPUT_WINDOW_NAME,
                           insertText=jerk_warning,
                           edit=True)
        jerk_violations, jerk_stats = _check_command_dicts_limits(
            jerk_dicts,
            limits=jerk_limits,
            get_min=True,
            get_max=True,
            get_average=True)

        # Format and print axis statistics
        _print_axis_stats(position_stats, "Position")
        _print_axis_stats(velocity_stats, "Velocity")
        _print_axis_stats(acceleration_stats, "Acceleration")
        _print_axis_stats(jerk_stats, "Jerk")

    if user_options.Include_external_axes and not user_options.Ignore_motion:
        # TODO: Implement velocity check for external axes
        # warning = _check_velocity_of_external_axes(robot, command_dicts, animation_settings['Framerate'])
        # if warning != '':
        #     # Print this one always
        #     warning += '\n'
        #     pm.scrollField(OUTPUT_WINDOW_NAME, insertText=warning, edit=True)
        #     if not ignore_warnings:
        #         raise mimic_utils.MimicError(warning)
        pass

    if user_options.Include_pose and not user_options.Ignore_motion:
        # TODO: Implement velocity check for poses
        # warning = _check_velocity_of_pose(robot, command_dicts, animation_settings['Framerate'])
        # if warning != '':
        #     # Print this one always
        #     warning += '\n'
        #     pm.scrollField(OUTPUT_WINDOW_NAME, insertText=warning, edit=True)
        #     if not ignore_warnings:
        #         raise mimic_utils.MimicError(warning)
        pass

    # If all checks passed then we don't have any warnings...
    # Format and print warnings
    violation_exception = False
    violation_warning = False
    if position_violations or velocity_violations or acceleration_violations or jerk_violations:
        # Print this one always
        pm.headsUpMessage('WARNINGS: See Mimic output window for details')
        if position_violations:
            _print_violations(position_violations, position_limits, "Position")
        if velocity_violations:
            _print_violations(velocity_violations, velocity_limits, "Velocity")
        if acceleration_violations:
            _print_violations(acceleration_violations, acceleration_limits,
                              "Acceleration")
        if jerk_violations:
            _print_violations(jerk_violations, jerk_limits, "Jerk")
        if not ignore_warnings:
            violation_exception = True
        violation_warning = True
    else:
        no_warning = 'All checks passed!\n'
        pm.scrollField(OUTPUT_WINDOW_NAME, insertText=no_warning, edit=True)
        pm.headsUpMessage('All Checks Passed!')
        violation_warning = False

    return violation_exception, violation_warning