25.2
Extensions

Extensions

Use functions to extend Wandelscript to support other programming languages and integrate new devices, e.g. welding power sources, palletizing patterns. The use of plugins compared to API changes respects the single-responsibility principle and thus only affects the specific component, e.g. new motion type, blending.

Extension TypeDescription
Embedded FunctionsA function in Wandelscript that can be reused within the same skill.
Plugin written in WandelscriptPlugin in separate .ws files that can be registered with and called from within the application. Keeps skills small and avoids redundancies.
Plugin written in PythonPlugin registered with the application. Fulfills special tooling, framework and language features not supported by Wandelscript.

Functions

Wandelscript support the definition of functions that can be reused in the robot program. Functions can be called only within the skill but don't need to be registered additionally. They are defined with the following syntax:

def <function_name>(<parameters>):
    <code_block>

Functions can use the complete Wandelscript feature set: control flows, variables, calculations, call external services or other functions, set I/Os, robot movements.

return <expression> makes the result available to the outside. One function can include multiple return statements and different return data types.

def is_one(a):
  if a == 1:
    return 1
  else:
    return "Is not one"

Register plugins with the application

  1. Install the wandelscript Python package.
  2. Import the decorator register_builtin_func via from Wandelscript.metamodel import register_builtin_func.
  3. Use register_builtin_func to write a function.
  4. Call the function from within Wandelscript.
@register_builtin_func
def sin(x: float) -> float:
    return math.sin(x)
ℹ️

Currently, namespaces for distinguishing plugins are not available. We're working on it.

get_controller

get_controller is used to assign a variable to a controller id or a controller id and a motion group. Use the function to work around Wandelscript naming restrictions (special characters like . and -) and customize controller and motion groups names.

Controller

Assigning a variable to the controller id ur-controller without specifying one of the two attached robot arms (motion groups): <variable> = get_controller("controller_id")

fluffy_cat = get_controller("ur-controller")
 
do with fluffy_cat[0]:
    move frame("Flange") via p2p() to home
 
do with fluffy_cat[1]:
    move frame("Flange") via p2p() to home

Robot arm (motion group)

Assigning a variable to each of the two robot arms (motion groups) attached to the ur-controller: <variable> = get_controller("controller_id")[motion_group_id]

tcp("Flange")
orange_cat = get_controller("ur-controller")[0]
black_cat = get_controller("ur-controller")[1]
 
do with orange_cat:
    move via p2p() to home
 
do with black_cat:
    move via p2p() to home

distance

Distance between two poses in [mm].

pose1 = (0, 0, 10, 0, pi, 0)
pose2 = (0, 0, 100, 0, pi, 0)
d = distance(pose1, pose2)  # 90

convert_to_int

Converts float to int. Full definition of integers here (opens in a new tab).

int(5.63)  # 5
int("5")  # 5

convert_to_string

Convert any value to a string.

string(5)  # "5"

time

Returns the system time of the instance in [ms].

t = time()  # e.g. t = 1631610000000

divmod

Return a tuple containing the quotient and the remainder when argument1 (dividend) is divided by argument2 (divisor).

divmod(5, 2)  # (2, 1)

modulo

Modulo operator.

modulo(5, 2)  # 1

intdiv

intdiv(5, 2)  # 2

power

Returns a raised to the power of b.

power(2, 3)  # 8

abs

Returns the absolute value of a.

abs(-4)  # 4

round

Returns a rounded to the nearest integer.

round(4.2)  # 4
round(4.9)  # 4

ceil

Returns the smallest integer greater than or equal to a.

ceil(4.2)  # 5

floor

Returns the largest integer less than or equal to a.

floor(4.2)  # 4

len

Returns the number of elements in a.

len([1, 2, 3])  # 3

assoc

Generic function for vectors vec, poses pose and record. Replace _ with the desired type.

Example for vector and pose:

a = (4, 5, 6, 1, 2, 3)
a_new_y = assoc(a, 1, 0)  # a_new_y == (4, 0, 6, 1, 2, 3)

Example for record:

rec = { a: 1, b: 2 }
rec_new = assoc(rec, "b", 5)  # rec_new == { a: 1, b: 5 }

to position

Extract the position from a pose.

pose = (0, 0, 10, 0, pi, 0)
pos = to_position(pose)  # (0, 0, 10)

to orientation

Extract the orientation from a pose.

pose = (0, 0, 10, 0, pi, 0)
ori = to_orientation(pose)  # (..., 0, pi, 0)

to pose

Convert a position to a pose.

pos = (0, 0, 10)
pose = to_pose(pos)  # (0, 0, 10, 0, 0, 0)

solve_point_forward

Returns the pose of the robot based on the joint positions and TCP

joints = solve_point_forward(<motion_group>, <joints>, <tcp>)

Arguments:

  • motion_group (MotionGroup): The motion group for which the pose is calculated.
  • joints (list[float]): The joint positions for which the pose is calculated.
  • tcp (str): The tool center point name (e.g., "Flange").

Returns the calculated pose of the motion group.

Example:

home = (508.1, -4.2, 567.6, 0.1545, -3.1086, 0.0014)
joints = [0.7254, -3.0115, 0.2917, -0.5732, -1.5709, 0.9005]
pose = solve_point_forward(kuka[0], joints, "Flange")

solve_point_inverse

Returns the joint positions of the robot based on the pose and TCP.

joints = solve_point_inverse(<motion_group>, <pose>, <tcp>, <reference_joints>)

Arguments:

  • motion_group (MotionGroup): The motion group for which the joints are calculated
  • pose (Pose): The pose for which the joint positions are calculated
  • tcp (str): The tool center point name (e.g., "Flange")
  • reference_joints (list[float]): The reference joints

Returns the calculated joint positions of the motion group.

home = (508.1, -4.2, 567.6, 0.1545, -3.1086, 0.0014)
reference_joints = [0.7254, -3.0115, 0.2917, -0.5732, -1.5709, 0.9005]
home_joints = solve_point_inverse(kuka[0], home, "Flange", reference_joints)

HTTP Fetch

Use response = fetch(url, options) to make HTTP requests to external services. It is designed to perform common HTTP operations such as GET, POST, PUT, and DELETE and returns the response in a structured format.

Parameters

ParametersDescriptionFormatRequired?Default
urlURL to fetch data fromstringRequired-
optionsrecord of additional options to customize HTTP requests. Supports method, body and headers as fields.recordOptionalNone
options.methodThe HTTP method to use (e.g., "GET", "POST", "PUT", "DELETE").stringOptional"GET"
options.bodyThe body of the request, typically used with methods like POST and PUT.recordOptionalNone
options.headersAdditional HTTP headers to include in the request.recordOptionalNone

Examples

Get request:

res_get = fetch("https://httpbin.org/get")

Post request:

res_post = fetch("https://httpbin.org/post", {
    method: "POST",
    body: { name: "JohnDoe" },
})

Return

The fetch function returns a record with the following fields:

Return fieldDescriptionFormat
dataResponse dataParsed JSON object, text, raw binary data
status_codeHTTP status codeinteger

In case of an error, the returned record will include:

Return fieldDescriptionFormat
errorDescription of the errorstring
status_codeThe HTTP status code if available (e.g., 404), or 500 for severe internal errorsinteger

Example

{
    data: {
        "name": "JohnDoe",
        "message": "Request successful"
    },
    status_code: 200
}

Supported HTTP Methods

The fetch function supports the following HTTP methods:

  • GET: Used to retrieve data from a server.
  • POST: Used to send data to a server.
  • PUT: Used to update data on a server.
  • DELETE: Used to delete data on a server.

If an unsupported method is provided, the function will raise a ValueError.

  • The function uses the httpx library internally for making asynchronous HTTP requests.
  • For POST, PUT, and DELETE requests, the body is serialized to JSON if provided as a record.