Ejemplo n.º 1
0
def simulate_controlled_drivetrain(show_plot=True):
    """ Download and simulate ControlledDrivetrain.ssp

    Parameters:
        show_plot     plot the results
    """

    ssp_filename = r'ControlledDrivetrain.ssp'

    download_file('https://github.com/CATIA-Systems/FMPy/releases/download/v0.1.1/' + ssp_filename, checksum='45e667ed')

    print("Simulating %s..." % ssp_filename)
    result = simulate_ssp(ssp_filename, stop_time=4, step_size=1e-3)

    if show_plot:
        print("Plotting results...")
        plot_result(result, names=['reference.y', 'drivetrain.w', 'controller.y'], window_title=ssp_filename)

    print('Done.')

    return result
Ejemplo n.º 2
0
def simulate_coupled_clutches(
        fmi_version='2.0',
        fmi_type='ModelExchange',
        output=['outputs[1]', 'outputs[2]', 'outputs[3]', 'outputs[4]'],
        solver='CVode',
        fmi_logging=False,
        show_plot=True):

    # download the FMU and input file
    for filename in ['CoupledClutches.fmu', 'CoupledClutches_in.csv']:
        download_test_file(fmi_version, fmi_type, 'MapleSim', '2016.2',
                           'CoupledClutches', filename)

    print("Loading input...")
    input = np.genfromtxt('CoupledClutches_in.csv', delimiter=',', names=True)

    print("Simulating CoupledClutches.fmu (FMI %s, %s, %s)..." %
          (fmi_version, fmi_type, solver))
    result = simulate_fmu(filename='CoupledClutches.fmu',
                          start_time=0,
                          stop_time=1.5,
                          solver=solver,
                          step_size=1e-2,
                          output_interval=2e-2,
                          start_values={'CoupledClutches1_freqHz': 0.4},
                          input=input,
                          output=output,
                          validate=False,
                          fmi_logging=fmi_logging)

    if show_plot:
        print("Plotting results...")
        from fmpy.util import plot_result
        plot_result(result=result,
                    window_title="CoupledClutches.fmu (FMI %s, %s, %s)" %
                    (fmi_version, fmi_type, solver))

    print("Done.")

    return result
Ejemplo n.º 3
0
def main():

    import argparse
    import textwrap

    description = """\
    Validate and simulate Functional Mock-up Units (FMUs)

    Get information about an FMU:
       
        fmpy info Rectifier.fmu
     
    Simulate an FMU:
     
        fmpy simulate Rectifier.fmu --show-plot
        
    Compile a source code FMU:
    
        fmpy compile Rectifier.fmu
        
    Create a Jupyter Notebook
    
        fmpy create-jupyter-notebook Rectifier.fmu
    """

    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=textwrap.dedent(description))

    parser.add_argument('command',
                        choices=[
                            'info', 'validate', 'simulate', 'compile',
                            'add-cswrapper', 'add-remoting',
                            'create-cmake-project', 'create-jupyter-notebook'
                        ],
                        help="Command to execute")
    parser.add_argument('fmu_filename', help="filename of the FMU")

    parser.add_argument('--validate',
                        action='store_true',
                        help="validate the FMU")
    parser.add_argument('--start-time',
                        type=float,
                        help="start time for the simulation")
    parser.add_argument('--stop-time',
                        type=float,
                        help="stop time for the simulation")
    parser.add_argument('--solver',
                        choices=['Euler', 'CVode'],
                        default='CVode',
                        help="solver to use for Model Exchange")
    parser.add_argument('--step-size',
                        type=float,
                        help="step size for fixed-step solvers")
    parser.add_argument(
        '--relative-tolerance',
        type=float,
        help=
        "relative tolerance for the 'CVode' solver and FMI 2.0 co-simulation FMUs"
    )
    parser.add_argument(
        '--dont-record-events',
        action='store_true',
        help="dont't record outputs at events (model exchange only)")
    parser.add_argument('--start-values',
                        nargs='+',
                        help="name-value pairs of start values")
    parser.add_argument(
        '--apply-default-start-values',
        action='store_true',
        help="apply the start values from the model description")
    parser.add_argument('--output-interval',
                        type=float,
                        help="interval for sampling the output")
    parser.add_argument('--input-file', help="CSV file to use as input")
    parser.add_argument('--output-variables',
                        nargs='+',
                        help="Variables to record")
    parser.add_argument('--output-file', help="CSV to store the results")
    parser.add_argument('--timeout',
                        type=float,
                        help="max. time to wait for the simulation to finish")
    parser.add_argument('--debug-logging',
                        action='store_true',
                        help="enable the FMU's debug logging")
    parser.add_argument('--visible',
                        action='store_true',
                        help="enable interactive mode")
    parser.add_argument('--fmi-logging',
                        action='store_true',
                        help="enable FMI logging")
    parser.add_argument('--show-plot',
                        action='store_true',
                        help="plot the results")
    parser.add_argument('--cmake-project-dir',
                        help="Directory for the CMake project")
    parser.add_argument('--target-platform',
                        help="The target platform to compile the binary for")

    args = parser.parse_args()

    if args.command == 'info':

        from fmpy import dump
        dump(args.fmu_filename)

    elif args.command == 'validate':

        import sys
        from fmpy.validation import validate_fmu

        problems = validate_fmu(args.fmu_filename)

        if len(problems) == 0:
            print('No problems found.')
        else:
            print('%d problems were found:' % len(problems))
            for message in problems:
                print()
                print(message)

        sys.exit(len(problems))

    elif args.command == 'compile':

        from fmpy.util import compile_platform_binary
        compile_platform_binary(args.fmu_filename,
                                target_platform=args.target_platform)

    elif args.command == 'add-cswrapper':

        from fmpy.cswrapper import add_cswrapper
        add_cswrapper(args.fmu_filename)

    elif args.command == 'add-remoting':

        from fmpy.util import add_remoting
        from fmpy import supported_platforms

        platforms = supported_platforms(args.fmu_filename)

        if 'win32' in platforms and 'win64' not in platforms:
            add_remoting(args.fmu_filename, 'win64', 'win32')
        elif 'win64' in platforms and 'linux64' not in platforms:
            add_remoting(args.fmu_filename, 'linux64', 'win64')
        else:
            print("Failed to add remoting binaries.")

    elif args.command == 'create-cmake-project':

        import os
        from fmpy.util import create_cmake_project

        project_dir = args.cmake_project_dir

        if project_dir is None:
            project_dir = os.path.basename(args.fmu_filename)
            project_dir, _ = os.path.splitext(project_dir)
            print("Creating CMake project in %s" %
                  os.path.abspath(project_dir))

        create_cmake_project(args.fmu_filename, project_dir)

    elif args.command == 'create-jupyter-notebook':

        from fmpy.util import create_jupyter_notebook

        create_jupyter_notebook(args.fmu_filename)

    elif args.command == 'simulate':

        from fmpy import simulate_fmu
        from fmpy.util import read_csv, write_csv, plot_result

        if args.start_values:
            if len(args.start_values) % 2 != 0:
                raise Exception("Start values must be name-value pairs.")
            start_values = {
                k: v
                for k, v in zip(args.start_values[::2],
                                args.start_values[1::2])
            }
        else:
            start_values = {}

        input = read_csv(args.input_file) if args.input_file else None

        if args.fmi_logging:
            fmi_call_logger = lambda s: print('[FMI] ' + s)
        else:
            fmi_call_logger = None

        result = simulate_fmu(
            args.fmu_filename,
            validate=args.validate,
            start_time=args.start_time,
            stop_time=args.stop_time,
            solver=args.solver,
            step_size=args.step_size,
            relative_tolerance=args.relative_tolerance,
            output_interval=args.output_interval,
            record_events=not args.dont_record_events,
            fmi_type=None,
            start_values=start_values,
            apply_default_start_values=args.apply_default_start_values,
            input=input,
            output=args.output_variables,
            timeout=args.timeout,
            debug_logging=args.debug_logging,
            visible=args.visible,
            fmi_call_logger=fmi_call_logger)

        if args.output_file:
            write_csv(filename=args.output_file, result=result)

        if args.show_plot:
            plot_result(result=result, window_title=args.fmu_filename)
Ejemplo n.º 4
0
def simulate_custom_input(show_plot=True):

    # define the model name and simulation parameters
    fmu_filename = 'CoupledClutches.fmu'
    start_time = 0.0
    threshold = 2.0
    stop_time = 2.0
    step_size = 1e-3

    # download the FMU
    download_test_file('2.0', 'CoSimulation', 'MapleSim', '2016.2', 'CoupledClutches', fmu_filename)

    # read the model description
    model_description = read_model_description(fmu_filename)

    # collect the value references
    vrs = {}
    for variable in model_description.modelVariables:
        vrs[variable.name] = variable.valueReference

    # get the value references for the variables we want to get/set
    vr_inputs   = vrs['inputs']      # normalized force on the 3rd clutch
    vr_outputs4 = vrs['outputs[4]']  # angular velocity of the 4th inertia

    # extract the FMU
    unzipdir = extract(fmu_filename)

    fmu = FMU2Slave(guid=model_description.guid,
                    unzipDirectory=unzipdir,
                    modelIdentifier=model_description.coSimulation.modelIdentifier,
                    instanceName='instance1')

    # initialize
    fmu.instantiate()
    fmu.setupExperiment(startTime=start_time)
    fmu.enterInitializationMode()
    fmu.exitInitializationMode()

    time = start_time

    rows = []  # list to record the results

    # simulation loop
    while time < stop_time:

        # NOTE: the FMU.get*() and FMU.set*() functions take lists of
        # value references as arguments and return lists of values

        # set the input
        fmu.setReal([vr_inputs], [0.0 if time < 0.9 else 1.0])

        # perform one step
        fmu.doStep(currentCommunicationPoint=time, communicationStepSize=step_size)

        # get the values for 'inputs' and 'outputs[4]'
        inputs, outputs4 = fmu.getReal([vr_inputs, vr_outputs4])

        # use the threshold to terminate the simulation
        if outputs4 > threshold:
            print("Threshold reached at t = %g s" % time)
            break

        # append the results
        rows.append((time, inputs, outputs4))

        # advance the time
        time += step_size

    fmu.terminate()
    fmu.freeInstance()

    # clean up
    shutil.rmtree(unzipdir)

    # convert the results to a structured NumPy array
    result = np.array(rows, dtype=np.dtype([('time', np.float64), ('inputs', np.float64), ('outputs[4]', np.float64)]))

    # plot the results
    if show_plot:
        plot_result(result)

    return time
Ejemplo n.º 5
0
def main():

    import argparse
    import textwrap

    description = """\
    Validate and simulate Functional Mock-up Units (FMUs)

    Get information about an FMU:
       
        fmpy info Rectifier.fmu
     
    Simulate an FMU:
     
        fmpy simulate Rectifier.fmu --show-plot
        
    Compile a source code FMU:
    
        fmpy compile Rectifier.fmu
    """

    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=textwrap.dedent(description))

    parser.add_argument(
        'command',
        choices=['info', 'validate', 'simulate', 'compile', 'add-remoting'],
        help="Command to execute")
    parser.add_argument('fmu_filename', help="filename of the FMU")

    parser.add_argument('--validate',
                        action='store_true',
                        help="validate the FMU")
    parser.add_argument('--start-time',
                        type=float,
                        help="start time for the simulation")
    parser.add_argument('--stop-time',
                        type=float,
                        help="stop time for the simulation")
    parser.add_argument('--solver',
                        choices=['Euler', 'CVode'],
                        default='CVode',
                        help="solver to use for Model Exchange")
    parser.add_argument('--step-size',
                        type=float,
                        help="step size for fixed-step solvers")
    parser.add_argument(
        '--relative-tolerance',
        type=float,
        help=
        "relative tolerance for the 'CVode' solver and FMI 2.0 co-simulation FMUs"
    )
    parser.add_argument(
        '--dont-record-events',
        action='store_true',
        help="dont't record outputs at events (model exchange only)")
    parser.add_argument('--start-values',
                        nargs='+',
                        help="name-value pairs of start values")
    parser.add_argument(
        '--apply-default-start-values',
        action='store_true',
        help="apply the start values from the model description")
    parser.add_argument('--output-interval',
                        type=float,
                        help="interval for sampling the output")
    parser.add_argument('--input-file', help="CSV file to use as input")
    parser.add_argument('--output-variables',
                        nargs='+',
                        help="Variables to record")
    parser.add_argument('--output-file', help="CSV to store the results")
    parser.add_argument('--timeout',
                        type=float,
                        help="max. time to wait for the simulation to finish")
    parser.add_argument('--debug-logging',
                        action='store_true',
                        help="enable the FMU's debug logging")
    parser.add_argument('--visible',
                        action='store_true',
                        help="enable interactive mode")
    parser.add_argument('--fmi-logging',
                        action='store_true',
                        help="enable FMI logging")
    parser.add_argument('--show-plot',
                        action='store_true',
                        help="plot the results")

    args = parser.parse_args()

    if args.command == 'info':

        from fmpy import dump
        dump(args.fmu_filename)

    elif args.command == 'validate':

        import sys
        from fmpy.util import validate_fmu

        messages = validate_fmu(args.fmu_filename)

        if len(messages) == 0:
            print('The validation passed')
        else:
            print('The following errors were found:')
            for message in messages:
                print()
                print(message)
            sys.exit(1)

    elif args.command == 'compile':

        from fmpy.util import compile_platform_binary
        compile_platform_binary(args.fmu_filename)

    elif args.command == 'add-remoting':

        from fmpy.util import add_remoting
        add_remoting(args.fmu_filename)

    elif args.command == 'simulate':

        from fmpy import simulate_fmu
        from fmpy.util import read_csv, write_csv, plot_result

        if args.start_values:
            if len(args.start_values) % 2 != 0:
                raise Exception("Start values must be name-value pairs.")
            start_values = {
                k: v
                for k, v in zip(args.start_values[::2],
                                args.start_values[1::2])
            }
        else:
            start_values = {}

        input = read_csv(args.input_file) if args.input_file else None

        if args.fmi_logging:
            fmi_call_logger = lambda s: print('[FMI] ' + s)
        else:
            fmi_call_logger = None

        result = simulate_fmu(
            args.fmu_filename,
            validate=args.validate,
            start_time=args.start_time,
            stop_time=args.stop_time,
            solver=args.solver,
            step_size=args.step_size,
            relative_tolerance=args.relative_tolerance,
            output_interval=args.output_interval,
            record_events=not args.dont_record_events,
            fmi_type=None,
            start_values=start_values,
            apply_default_start_values=args.apply_default_start_values,
            input=input,
            output=args.output_variables,
            timeout=args.timeout,
            debug_logging=args.debug_logging,
            visible=args.visible,
            fmi_call_logger=fmi_call_logger)

        if args.output_file:
            write_csv(filename=args.output_file, result=result)

        if args.show_plot:
            plot_result(result=result, window_title=args.fmu_filename)
Ejemplo n.º 6
0
def main():

    import argparse
    import textwrap

    description = """\
    Simulate an FMU

    Example: 
        > python -m fmpy.simulate Rectifier.fmu

    """

    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description=textwrap.dedent(description))

    parser.add_argument('command',
                        choices=['info', 'simulate'],
                        help="Command to execute")
    parser.add_argument('fmu_filename', help="filename of the FMU")

    parser.add_argument('--solver',
                        choices=['Euler', 'CVode'],
                        default='CVode',
                        help="solver to use for Model Exchange")
    parser.add_argument('--input-file', help="CSV file to use as input")
    parser.add_argument('--output-variables',
                        nargs='+',
                        help="Variables to record")
    parser.add_argument('--output-file', help="CSV to store the results")
    parser.add_argument('--num-samples',
                        default=500,
                        type=int,
                        help="number of samples to record")
    parser.add_argument('--step-size',
                        type=float,
                        help="step size for fixed-step solvers")
    parser.add_argument('--start-time',
                        type=float,
                        help="start time for the simulation")
    parser.add_argument('--stop-time',
                        type=float,
                        help="stop time for the simulation")
    parser.add_argument('--show-plot',
                        action='store_true',
                        help="plot the results")
    parser.add_argument('--timeout',
                        type=float,
                        help="max. time to wait for the simulation to finish")
    parser.add_argument('--fmi-logging',
                        action='store_true',
                        help="enable FMI logging")
    parser.add_argument('--start-values',
                        nargs='+',
                        help="name-value pairs of start values")

    args = parser.parse_args()

    if args.command == 'info':

        from fmpy import dump
        dump(args.fmu_filename)

    elif args.command == 'simulate':

        from fmpy import simulate_fmu
        from fmpy.util import read_csv, write_csv, plot_result

        if args.start_values:
            if len(args.start_values) % 2 != 0:
                raise Exception("Start values must be name-value pairs.")
            start_values = {
                k: v
                for k, v in zip(args.start_values[::2],
                                args.start_values[1::2])
            }
        else:
            start_values = {}

        input = read_csv(args.input_file) if args.input_file else None

        result = simulate_fmu(args.fmu_filename,
                              validate=True,
                              start_time=args.start_time,
                              stop_time=args.stop_time,
                              solver=args.solver,
                              step_size=args.step_size,
                              output_interval=None,
                              fmi_type=None,
                              start_values=start_values,
                              input=input,
                              output=args.output_variables,
                              timeout=args.timeout,
                              fmi_logging=args.fmi_logging)

        if args.output_file:
            write_csv(args.output_file, result)

        if args.show_plot:
            plot_result(result=result, window_title=args.fmu_filename)
Ejemplo n.º 7
0
    in_csv  = os.path.join(src_dir, model_name, model_name + '_in.csv')

    if os.path.isfile(in_csv):
        input = read_csv(in_csv)
    else:
        input = None

    result = simulate_fmu(fmu,
                          fmi_type='ModelExchange',
                          # solver='Euler',
                          start_values=start_values,
                          input=input,
                          output_interval=output_interval
                          )

    write_csv(ref_csv, result)
    ref = read_csv(ref_csv)
    plot_result(ref, events=True, filename=ref_png)

    md_file = os.path.join(src_dir, model_name, 'readme.md')
    html_file = os.path.join(src_dir, model_name, 'readme.html')

    md = markdown2.markdown_path(md_file, extras=['tables', 'fenced-code-blocks'])

    with open(html_file, 'w') as html:
        html.write(header1)
        html.write("<title>%s</title>" % model_name)
        html.write(header2)
        html.write(md)
        html.write(footer)
Ejemplo n.º 8
0
def simulateCustomInput(filename, showPlot=True):

    # define the model name and simulation parameters
    startTime = 0.0
    threshold = 2.0
    stopTime = 30.0
    stepSize = (stopTime - startTime) / 500

    # read the model description
    modelDescription = read_model_description(filename)

    # collect the value references
    vrs = {}
    for variable in modelDescription.modelVariables:
        vrs[variable.name] = variable.valueReference

    # get the value references for the variables we want to get/set
    vrInputs = vrs[
        'u']  # These need to be changed per model, or use standardised naming conventions
    vrOutputs = vrs['y']

    unzipdir = extract(filename)

    fmu = FMU2Slave(
        guid=modelDescription.guid,
        unzipDirectory=unzipdir,
        modelIdentifier=modelDescription.coSimulation.modelIdentifier,
        instanceName='instance1')

    # initalize
    fmu.instantiate()
    fmu.setupExperiment(startTime=startTime)
    fmu.enterInitializationMode()
    fmu.exitInitializationMode()

    time = startTime

    rows = []

    # Sim loop
    while time < stopTime:

        # NOTE: the FMU.get*() and FMU.set*() functions take lists of
        # value references as arguments and return lists of values

        # set the input
        fmu.setReal([vrInputs], [0.0 if time < 1.0 else 1.0])

        # perform 1 step
        fmu.doStep(currentCommunicationPoint=time,
                   communicationStepSize=stepSize)

        # get the values for 'inputs' and 'outputs'
        inputs, outputs = fmu.getReal([vrInputs, vrOutputs])

        # Use threshold to terminate sim
        if outputs > threshold:
            print("Threshold reached at t = {:.3f} s".format(time))
            break

        # append the results
        rows.append((time, inputs, outputs))

        # advance the time
        time += stepSize

    fmu.terminate()
    fmu.freeInstance()

    result = np.array(rows,
                      dtype=np.dtype([('time', np.float64),
                                      ('inputs', np.float64),
                                      ('outputs', np.float64)]))

    if showPlot:
        plot_result(result)

    return time