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
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