Пример #1
0
def post_procedure(client):
    """Post fabrication procedure, end pose and closing and termination of client.

    Uses ``fab_conf`` set up using
    :func:`compas_rcf.fab_data.interactive_conf_setup` for fabrication settings.

    Parameters
    ----------
    client : :class:`compas_rrc.AbbClient`
    """
    grip_and_release(
        client,
        fab_conf["tool"]["io_needles_pin"].get(),
        fab_conf["tool"]["release_state"].get(),
        wait_before=fab_conf["tool"]["wait_before_io"].get(),
        wait_after=fab_conf["tool"]["wait_after_io"].get(),
    )

    client.send(
        MoveToJoints(
            fab_conf["safe_joint_positions"]["end"].get(),
            EXTERNAL_AXIS_DUMMY,
            fab_conf["movement"]["speed_travel"].as_number(),
            fab_conf["movement"]["zone_travel"].get(ZoneDataTemplate()),
        ))

    client.send_and_wait(PrintText("Finished"))

    # Close client
    client.close()
    client.terminate()
Пример #2
0
    def post_procedure(self):
        """Post fabrication procedure, end pose and closing and termination of client.

        Uses ``fab_conf`` set up using
        :func:`compas_rcf.fab_data.interactive_conf_setup` for fabrication settings.

        Parameters
        ----------
        client : :class:`compas_rrc.AbbClient`
        """
        self.retract_needles()

        self.send(
            MoveToJoints(
                self.set_joint_pos.end,
                self.EXTERNAL_AXIS_DUMMY,
                self.speed.travel,
                self.zone.travel,
            ))

        self.send_and_wait(PrintText("Finished"))
Пример #3
0
def go_to_joint_pos(args: argparse.Namespace) -> None:
    """Send instruction to go to joint position.

    Parameters
    ----------
    args : :class:`argparse.Namespace`
    """
    selection_instructions = {
        "Calibration position": CALIBRATION_JOINT_POSITION,
        "Travel position": TRAVEL_JOINT_POSITION,
    }

    compose_up_driver(args.controller)

    selection = questionary.select(
        "Select joint position to go to", selection_instructions.keys()
    ).ask()

    log.debug(f"{selection} selected.")

    with AbbRcfClient(ros_port=9090) as client:
        client.ensure_connection()

        client.send(SetAcceleration(ACCEL, ACCEL_RAMP))
        client.send(SetMaxSpeed(SPEED_OVERRIDE, SPEED_MAX_TCP))

        client.confirm_start()

        log_msg = f"Moving to {selection.lower()}."
        client.send(PrintText(log_msg))
        log.info(log_msg)

        client.send(
            MoveToJoints(
                selection_instructions[selection],
                client.EXTERNAL_AXES_DUMMY,
                SPEED,
                ZONE,
            )
        )
def test_speeds():
    with RosClient() as ros:
        client = compas_rrc.AbbClient(ros)
        client.run()

        # Confirm start on flexpendant
        client.send(PrintText("Confirm start by pressing play."))
        client.send(compas_rrc.Stop())

        # The speed and acceleration values are then overriden here
        client.send(compas_rrc.SetMaxSpeed(SPEED_OVERRIDE, SPEED_MAX_TCP))
        client.send(compas_rrc.SetAcceleration(ACCELERATION,
                                               ACCELERATION_RAMP))
        client.send(PrintText(f"Speed override: {SPEED_OVERRIDE} %"))
        client.send(PrintText(f"Max TCP speed: {SPEED_OVERRIDE} mm/s"))
        client.send(PrintText(f"Acceleration: {ACCELERATION} %"))
        client.send(PrintText(f"Acceleration ramp: {ACCELERATION_RAMP} %"))

        client.send(compas_rrc.SetTool(client.pick_place_tool.name))
        client.send(compas_rrc.SetWorkObject("wobj0"))
        client.send(PrintText(f"Tool: {TOOL}"))
        client.send(PrintText(f"wobj: {WOBJ}"))

        if TEST_JOINT_POS:
            for i in range(N_TIMES_REPEAT_LISTS):
                speed = START_SPEED + SPEED_INCREMENTS * i
                client.send(
                    PrintText(f"Speed: {speed} mm/s, Zone: {ZONE} mm.", ))

                client.send(compas_rrc.StartWatch())
                for pos in JOINT_POS:
                    client.send(
                        MoveToJoints(pos, client.EXTERNAL_AXES_DUMMY, speed,
                                     ZONE))

                # Block until finished and print cycle time
                client.send(compas_rrc.StopWatch())
                cycle_time = client.send_and_wait(compas_rrc.ReadWatch(),
                                                  timeout=TIMEOUT)
                client.send(PrintText(f"Cycle took {cycle_time} s."))

        if TEST_FRAMES:
            for i in range(N_TIMES_REPEAT_LISTS):
                speed = START_SPEED + SPEED_INCREMENTS * i
                client.send(
                    PrintText(f"Speed: {speed} mm/s, Zone: {ZONE} mm.", ))

                client.send(compas_rrc.StartWatch())
                for frame in FRAMES:
                    client.send(
                        MoveToFrame(
                            frame,
                            speed,
                            ZONE,
                            motion_type=MOTION_TYPE,
                        ))

                # Block until finished and print cycle time
                client.send(compas_rrc.StopWatch())
                cycle_time = client.send_and_wait(compas_rrc.ReadWatch(),
                                                  timeout=TIMEOUT)
                client.send(PrintText(f"Cycle took {cycle_time} s."))

        client.close()
Пример #5
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)
Пример #6
0
def run(run_conf, run_data):
    """Fabrication runner, sets conf, reads json input and runs fabrication process."""
    ############################################################################
    # Docker setup                                                            #
    ############################################################################
    # Publish TF static transform for transformation by ROS
    if run_conf.publish_tf_xform:
        if run_data.get("xform_path"):
            log.debug(f"Loading matrix from {run_data['xform_path']}")
            with open(run_data["xform_path"], mode="r") as fp:
                xform = json.load(fp)
        else:
            # Publish identity matrix (zero matrix)
            log.debug("Publishing zero matrix")
            xform = Transformation()

        publish_static_transform(xform,
                                 scale_factor=1000)  # mm to m scale factor

    ip = {"ROBOT_IP": ROBOT_IPS[run_conf.robot_client.controller]}
    compose_up(DOCKER_COMPOSE_PATHS["driver"], check_output=True, env_vars=ip)
    log.debug("Driver services are running.")

    ############################################################################
    # Load fabrication data                                                    #
    ############################################################################
    clay_cylinders = [
        ClayBullet.from_data(data) for data in run_data["fab_data"]
    ]
    log.info("Fabrication data read.")

    log.info(f"{len(clay_cylinders)} items in clay_cylinders.")

    # Integrate into AbbRcfClient?
    with run_conf.pick_conf.open(mode="r") as fp:
        pick_station = PickStation.from_data(json.load(fp))

    ############################################################################
    # setup in_progress JSON                                                   #
    ############################################################################
    json_progress_identifier = "-IN_PROGRESS"

    run_data_path = run_conf.run_data_path

    if run_data_path.stem.endswith(
            json_progress_identifier) or run_data_path.stem.endswith(
                json_progress_identifier + ".json"):
        progress_file = run_data_path
    else:
        progress_file = run_data_path.with_name(run_data_path.stem +
                                                json_progress_identifier +
                                                run_data_path.suffix)

    i = 1
    while progress_file.exists():
        progress_file = progress_file / ".{:02}".format(i)

    done_file = progress_file.with_name(
        str(progress_file.name).replace(json_progress_identifier, "-DONE"))

    # Create Ros Client                                                        #
    with RosClient() as ros:

        # Create AbbRcf client (subclass of AbbClient)
        rob_client = AbbRcfClient(ros, run_conf.robot_client)

        rob_client.check_reconnect()

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

        to_place = setup_fab_data(clay_cylinders)

        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
        rob_client.pre_procedure()

        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)

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

            pick_frame = pick_station.get_next_frame(bullet)

            # Pick bullet
            pick_future = rob_client.pick_bullet(pick_frame)

            # Place bullet
            place_future = rob_client.place_bullet(bullet)

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

            # Write progress to json while waiting for robot
            run_data["fab_data"] = [
                cylinder.to_data() for cylinder in clay_cylinders
            ]
            with progress_file.open(mode="w") as fp:
                json.dump(run_data, fp, cls=ClayBulletEncoder)
            log.debug("Wrote clay_bullets to {}".format(progress_file.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
        run_data["fab_data"] = [
            cylinder.to_data() for cylinder in clay_cylinders
        ]
        with progress_file.open(mode="w") as fp:
            json.dump(run_data, fp, cls=ClayBulletEncoder)
        log.debug("Wrote run_data to {}".format(progress_file.name))

        if len([bullet for bullet in clay_cylinders
                if bullet.placed is None]) == 0:
            progress_file.rename(done_file)
            log.debug(f"Saved placed bullets to {done_file}.")

        rob_client.post_procedure()
Пример #7
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)
Пример #8
0
def fab_run(run_conf, run_data):
    """Fabrication runner, sets conf, reads json input and runs fabrication process."""
    # Publish TF static transform for transformation by ROS
    if run_conf.publish_tf_xform:
        _publish_tf_static_xform(xform=run_data.get("xform"))

    compose_up_driver(run_conf.robot_client.controller)

    # setup fab data
    fab_elements = [
        ClayBullet.from_data(data) for data in run_data["fab_data"]
    ]
    log.info("Fabrication data read.")

    log.info(f"{len(fab_elements)} fabrication elements..")

    # Setup pick station
    with run_conf.pick_conf.open(mode="r") as fp:
        pick_station = PickStation.from_data(json.load(fp))
    log.info(f"Pick station setup read from {run_conf.pick_conf}")

    run_data_path = run_conf.run_data_path

    # setup in_progress JSON
    progress_identifier = "-IN_PROGRESS"

    progress_identifier_regex = re.compile(progress_identifier + r"\d{0,2}")

    if progress_identifier in run_data_path.stem:
        progress_file = run_data_path
        i = 1
        # Add number and increment it if needed.
        while progress_file.exists():
            # strip suffix
            stem = progress_file.stem

            # Match IN_PROGRESS with or without digits after and add/replace digits
            new_name = re.sub(progress_identifier_regex,
                              progress_identifier + f"{i:02}", stem)

            new_name += progress_file.suffix

            progress_file = progress_file.with_name(new_name)

            i += 1
    else:
        progress_file = run_data_path.with_name(run_data_path.stem +
                                                progress_identifier +
                                                run_data_path.suffix)

    log.info(f"Progress will be saved to {progress_file}.")

    done_file_name = re.sub(progress_identifier_regex, "-DONE",
                            progress_file.name)
    done_file = progress_file.with_name(done_file_name)

    # Fabrication loop
    _edit_fab_data(fab_elements, run_conf)

    # Create Ros Client
    with RosClient(port=9090) as ros:

        # Create AbbRcf client (subclass of AbbClient)
        rob_client = AbbRcfClient(ros, run_conf.robot_client)

        confirm_start()

        rob_client.check_reconnect()

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

        # Initialize this before first run, it gets set after placement
        cycle_time_msg = None

        for i, elem in enumerate(fab_elements):
            if elem.placed:
                continue
            current_elem_desc = f"{i}/{len(fab_elements) - 1}, id {elem.bullet_id}."
            log.info(current_elem_desc)

            pendant_msg = ""

            if cycle_time_msg:
                pendant_msg += cycle_time_msg + " "
            pendant_msg += current_elem_desc

            # TP write limited to 40 char / line
            rob_client.send(PrintText(pendant_msg[:40]))

            pick_frame = pick_station.get_next_frame(elem)

            # Send instructions and store feedback obj
            pick_future = rob_client.pick_bullet(pick_frame)
            place_future = rob_client.place_bullet(elem)

            elem.placed = True  # set placed to temporary value to mark it as "placed"

            # Write progress to json while waiting for robot
            run_data["fab_data"] = fab_elements
            with progress_file.open(mode="w") as fp:
                json.dump(run_data, fp, cls=CompasObjEncoder)
            log.debug(f"Wrote fabrication data to {progress_file.name}")

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

            elem.cycle_time = cycle_time
            # format float to int to save characters on teach pendant
            cycle_time_msg = f"Last cycle time: {elem.cycle_time:0.0f}"
            log.info(cycle_time_msg)

            elem.time_placed = time.time()
            log.debug(f"Time placed was {elem.time_placed}")

        # Write progress of last run of loop
        run_data["fab_data"] = fab_elements
        with done_file.open(mode="w") as fp:
            json.dump(run_data, fp, cls=CompasObjEncoder)
        log.info("Wrote final run_data to {}".format(done_file.name))

        rob_client.post_procedure()
Пример #9
0
def fab_run(run_conf, run_data):
    """Fabrication runner placing elements according to fab_data and conf."""

    _compose_up_driver(run_conf.robot_client.controller)

    # setup fab data
    fab_elements = [FabricationElement.from_data(data) for data in run_data["fab_data"]]
    log.info("Fabrication data read.")

    log.info(f"{len(fab_elements)} fabrication elements.")

    # Setup pick station
    with run_conf.pick_conf.open(mode="r") as fp:
        pick_station = PickStation.from_data(json.load(fp))
    log.info(f"Pick station setup read from {run_conf.pick_conf}")

    progress_file, done_file = _setup_file_paths(run_conf.run_data_path)

    _edit_fab_data(fab_elements, run_conf)

    # Fabrication loop

    # Create Ros Client
    with RosClient(port=9090) as ros:

        # Create AbbRcf client (subclass of AbbClient)
        rob_client = AbbRcfClient(ros, run_conf.robot_client)

        rob_client.check_reconnect()

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

        # Confirm start on flexpendant
        rob_client.confirm_start()

        # Initialize this before first run, it gets set after placement
        cycle_time_msg = None

        for i, elem in enumerate(fab_elements):
            if elem.placed:  # Don't place elements marked as placed
                continue

            # Setup log message and flex pendant message
            current_elem_desc = f"{i}/{len(fab_elements) - 1}, id {elem.id_}."
            log.info(current_elem_desc)

            pendant_msg = ""

            if cycle_time_msg:
                pendant_msg += cycle_time_msg + " "
            pendant_msg += current_elem_desc

            # TP write limited to 40 char / line
            rob_client.send(PrintText(pendant_msg[:40]))

            pick_element = pick_station.get_next_pick_elem(elem)

            # Send instructions and store feedback obj
            pick_future = rob_client.pick_element(pick_element)
            place_future = rob_client.place_element(elem)

            # set placed to temporary value to mark it as "placed"
            elem.placed = True

            # Write progress to json while waiting for robot
            run_data["fab_data"] = fab_elements
            with progress_file.open(mode="w") as fp:
                json.dump(run_data, fp, cls=CompasObjEncoder)
            log.debug(f"Wrote fabrication data to {progress_file.name}")

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

            elem.cycle_time = cycle_time
            # format float to int to save characters on teach pendant
            cycle_time_msg = f"Last cycle time: {elem.cycle_time:0.0f}"
            log.info(cycle_time_msg)

            elem.time_placed = time.time()
            log.debug(f"Time placed was {elem.time_placed}")

        # Write progress of last run of loop
        run_data["fab_data"] = fab_elements
        with done_file.open(mode="w") as fp:
            json.dump(run_data, fp, cls=CompasObjEncoder)
        log.info("Wrote final run_data to {}".format(done_file.name))

        # Send robot to safe end position and close connection
        rob_client.post_procedure()