Exemple #1
0
def main():
    """Fabrication runner, sets conf, reads json input and runs fabrication process."""
    ############################################################################
    # Docker setup                                                            #
    ############################################################################
    ip = {"ROBOT_IP": ROBOT_IPS[fab_conf["target"].as_str()]}
    compose_up(DOCKER_COMPOSE_PATHS["driver"], check_output=True, env_vars=ip)
    log.debug("Driver services are running.")

    ############################################################################
    # Load fabrication data                                                    #
    ############################################################################
    fab_json_path = fab_conf["paths"]["fab_data_path"].as_path()
    clay_bullets = load_bullets(fab_json_path)

    log.info("Fabrication data read from: {}".format(fab_json_path))
    log.info("{} items in clay_bullets.".format(len(clay_bullets)))

    pick_station_json = fab_conf["paths"]["pick_conf_path"].as_path()
    with pick_station_json.open(mode="r") as fp:
        pick_station_data = json.load(fp)
    pick_station = PickStation.from_data(pick_station_data)

    ############################################################################
    # Create Ros Client                                                        #
    ############################################################################
    ros = RosClient()

    ############################################################################
    # Create ABB Client                                                        #
    ############################################################################
    abb = AbbClient(ros)
    abb.run()
    log.debug("Connected to ROS")

    check_reconnect(
        abb,
        driver_container_name=DRIVER_CONTAINER_NAME,
        timeout_ping=fab_conf["docker"]["timeout_ping"].get(),
        wait_after_up=fab_conf["docker"]["sleep_after_up"].get(),
    )

    ############################################################################
    # setup in_progress JSON                                                   #
    ############################################################################
    if not fab_conf["skip_progress_file"]:
        json_progress_identifier = "IN_PROGRESS-"

        if fab_json_path.name.startswith(json_progress_identifier):
            in_progress_json = fab_json_path
        else:
            in_progress_json = fab_json_path.with_name(
                json_progress_identifier + fab_json_path.name)

    ############################################################################
    # Fabrication loop                                                         #
    ############################################################################

    to_place = setup_fab_data(clay_bullets)

    if not questionary.confirm("Ready to start program?").ask():
        log.critical("Program exited because user didn't confirm start.")
        print("Exiting.")
        sys.exit()

    # Set speed, accel, tool, wobj and move to start pos
    pre_procedure(abb)

    for bullet in to_place:
        bullet.placed = None
        bullet.cycle_time = None

    for i, bullet in enumerate(to_place):
        current_bullet_desc = "Bullet {:03}/{:03} with id {}.".format(
            i,
            len(to_place) - 1, bullet.bullet_id)

        abb.send(PrintText(current_bullet_desc))
        log.info(current_bullet_desc)

        pick_frame = pick_station.get_next_frame(bullet)

        # Pick bullet
        pick_future = pick_bullet(abb, pick_frame)

        # Place bullet
        place_future = place_bullet(abb, bullet)

        bullet.placed = 1  # set placed to temporary value to mark it as "placed"

        # Write progress to json while waiting for robot
        if not fab_conf["skip_progress_file"].get():
            with in_progress_json.open(mode="w") as fp:
                json.dump(clay_bullets, fp, cls=ClayBulletEncoder)
            log.debug("Wrote clay_bullets to {}".format(in_progress_json.name))

        # This blocks until cycle is finished
        cycle_time = pick_future.result() + place_future.result()

        bullet.cycle_time = cycle_time
        log.debug("Cycle time was {}".format(bullet.cycle_time))
        bullet.placed = time.time()
        log.debug("Time placed was {}".format(bullet.placed))

    ############################################################################
    # Shutdown procedure                                                       #
    ############################################################################

    # Write progress of last run of loop
    if not fab_conf["skip_progress_file"].get():
        with in_progress_json.open(mode="w") as fp:
            json.dump(clay_bullets, fp, cls=ClayBulletEncoder)
        log.debug("Wrote clay_bullets to {}".format(in_progress_json.name))

    if (len([bullet for bullet in clay_bullets if bullet.placed is None]) == 0
            and not fab_conf["skip_progress_file"].get()):
        done_file_name = fab_json_path.name.replace(json_progress_identifier,
                                                    "")
        done_json = fab_conf["paths"]["json_dir"].as_path(
        ) / "00_done" / done_file_name

        in_progress_json.rename(done_json)

        with done_json.open(mode="w") as fp:
            json.dump(clay_bullets, fp, cls=ClayBulletEncoder)

        log.debug("Saved placed bullets to 00_Done.")
    elif not fab_conf["skip_progress_file"].get():
        log.debug("Bullets without placed timestamp still present, keeping {}".
                  format(in_progress_json.name))

    log.info("Finished program with {} bullets.".format(len(to_place)))

    post_procedure(abb)
Exemple #2
0
def std_move_to_frame(
    frame,
    tool="tool0",
    wobj="wobj0",
    motion_type=Motion.LINEAR,
    speed=200,
    accel=100,
    zone=Zone.FINE,
    timeout=None,
):
    """Move robot arm to target or targets.

    Parameters
    ----------
    frame : :class:`compas.geometry.Frame` or :obj:`list` of :class:`compas.geometry.Frame`
        Target frame or frames.
    tool : :obj:`str`
        Name of tool as named in RAPID code on controller to use for TCP data.
    wobj : :obj:`str`
        Name of work object as named in RAPID code on controller to use for
        coordinate system.
    motion_type : :class:`compas_rrc.Motion`
        Motion type, either linear (:class:`~compas_rrc.Motion.LINEAR`) or
        joint (:class:`~compas_rrc.Motion.JOINT`).
    speed : :obj:`float`
        TCP speed in mm/s. Limited by hard coded max speed in this function as
        well as safety systems on controller.
    accel : :obj:`float`
        Acceleration in percentage of standard acceleration.
    zone : :class:`compas_rrc.Zone`
        Set zone value of movement, (acceptable deviation from target).
    timeout : :obj:`float`
        Time to wait for indication of finished movement. If not defined no
        feedback will be requested.
    """  # noqa: E501
    if not isinstance(frame, Sequence):
        frames = [frame]
    else:
        frames = frame

    with RosClient() as ros:
        # Create ABB Client
        abb = AbbClient(ros)
        abb.run(timeout=5)

        abb.send(SetTool(tool))
        abb.send(SetWorkObject(wobj))

        # Set acceleration data
        ramp = 100  # % Higher values makes the acceleration ramp longer
        abb.send(SetAcceleration(accel, ramp))

        # Set speed override and max speed
        speed_override = 100  # %
        max_tcp_speed = 500  # mm/s
        abb.send(SetMaxSpeed(speed_override, max_tcp_speed))

        # Move to Frame
        for f in frames:
            abb.send(
                PrintText(" Moving to {:.3f}, {:.3f}, {:.3f}.".format(
                    *f.point.data)))
            abb.send(MoveToFrame(f, speed, zone, motion_type))

        if timeout:
            abb.send_and_wait(Noop(), timeout=timeout)