Sources.KinematicPTP ​
Move as fast as possible from q0 to q1 within given kinematic constraints (point-to-point motion).
For each axis the block emits a minimum-time trajectory that does not exceed the maximum velocity qd_max or maximum acceleration qdd_max. The result is a trapezoidal velocity profile — accelerate at qdd_max, cruise at qd_max, decelerate at qdd_max — or a triangular profile when the move is too short to reach qd_max. The position, velocity, and acceleration are provided directly as outputs q, qd, qdd (one scalar per axis), together with a Boolean moving (true while an axis is still travelling) and the scalar endTime (the instant the movement stops). This matches Modelica.Blocks.Sources.KinematicPTP2.
All axes are phase-synchronized: a single shared normalized path parameter s(t) in [0, 1] (one trapezoidal profile, paced by the bottleneck axis) drives every axis via q[i] = q0[i] + (q1[i] - q0[i]) * s(t). Because they share the same s(t), every axis is at the same fraction of its travel at every instant, so the joint path is a straight line — and they necessarily start and reach their targets together (phase synchronization implies time synchronization). This matches Modelica.Blocks.Sources.KinematicPTP and KinematicPTP2, and the vectorized point_to_point trajectory.
The motion begins at startTime (default 0); before that the outputs hold at the start position with zero velocity and acceleration.
The block is stateless: q, qd, qdd are closed-form functions of time, so no integration or discrete events are involved.
Usage ​
BlockComponents.Sources.KinematicPTP(q0=fill(0.0, nout), q1=fill(1.0, nout), qd_max=fill(1.0, nout), qdd_max=fill(1.0, nout), startTime=0, sd_max=BlockComponents.ptp_sd_max(q0, q1, qd_max), sdd_max=BlockComponents.ptp_sdd_max(q0, q1, qdd_max), moveTime=BlockComponents.ptp_move_time(sd_max, sdd_max), eps0=eps(Float64))
Parameters: ​
| Name | Description | Units | Default value |
|---|---|---|---|
nout | Number of output axes | – | 1 |
q0 | Initial position for each axis | – | fill(0.0, nout) |
q1 | Final position for each axis | – | fill(1.0, nout) |
qd_max | Maximum velocity for each axis | – | fill(1.0, nout) |
qdd_max | Maximum acceleration for each axis | – | fill(1.0, nout) |
startTime | Time instant at which the movement starts | s | 0 |
Connectors ​
q- This connector represents a real signal as an output from a component (RealOutput)qd- This connector represents a real signal as an output from a component (RealOutput)qdd- This connector represents a real signal as an output from a component (RealOutput)moving- This connector represents a boolean signal as an output from a component (BooleanOutput)endTime- This connector represents a real signal as an output from a component (RealOutput)
Behavior ​
Source ​
"""
Move as fast as possible from `q0` to `q1` within given kinematic constraints
(point-to-point motion).
For each axis the block emits a minimum-time trajectory that does not exceed the
maximum velocity `qd_max` or maximum acceleration `qdd_max`. The result is a
trapezoidal velocity profile — accelerate at `qdd_max`, cruise at `qd_max`,
decelerate at `qdd_max` — or a triangular profile when the move is too short to
reach `qd_max`. The position, velocity, and acceleration are provided directly as
outputs `q`, `qd`, `qdd` (one scalar per axis), together with a Boolean `moving`
(true while an axis is still travelling) and the scalar `endTime` (the instant the
movement stops). This matches `Modelica.Blocks.Sources.KinematicPTP2`.
All axes are **phase-synchronized**: a single shared normalized path parameter
`s(t)` in `[0, 1]` (one trapezoidal profile, paced by the bottleneck axis) drives
every axis via `q[i] = q0[i] + (q1[i] - q0[i]) * s(t)`. Because they share the same
`s(t)`, every axis is at the same fraction of its travel at every instant, so the
joint path is a straight line — and they necessarily start and reach their targets
together (phase synchronization implies time synchronization). This matches
`Modelica.Blocks.Sources.KinematicPTP` and `KinematicPTP2`, and the vectorized
`point_to_point` trajectory.
The motion begins at `startTime` (default 0); before that the outputs hold at the
start position with zero velocity and acceleration.
The block is stateless: `q`, `qd`, `qdd` are closed-form functions of time, so no
integration or discrete events are involved.
"""
component KinematicPTP
"Position output for each axis"
q = [RealOutput() for i in 1:nout] {
"Dyad": {
"placement": {"diagram": {"iconName": "output", "x1": 1000, "y1": 20, "x2": 1100, "y2": 120}}
}
}
"Velocity output for each axis"
qd = [RealOutput() for i in 1:nout] {
"Dyad": {
"placement": {
"diagram": {"iconName": "output", "x1": 1000, "y1": 220, "x2": 1100, "y2": 320}
}
}
}
"Acceleration output for each axis"
qdd = [RealOutput() for i in 1:nout] {
"Dyad": {
"placement": {
"diagram": {"iconName": "output", "x1": 1000, "y1": 450, "x2": 1100, "y2": 550}
}
}
}
"= true while axis i is still moving; false once its target is reached (or if it does not move)"
moving = [BooleanOutput() for i in 1:nout] {
"Dyad": {
"placement": {
"diagram": {"iconName": "output", "x1": 1000, "y1": 680, "x2": 1100, "y2": 780}
}
}
}
"Time instant at which the movement stops"
endTime = RealOutput() {
"Dyad": {
"placement": {
"diagram": {"iconName": "output", "x1": 1000, "y1": 880, "x2": 1100, "y2": 980}
}
}
}
"Number of output axes"
structural parameter nout::Integer = 1
"Initial position for each axis"
parameter q0::Real[nout] = fill(0.0, nout)
"Final position for each axis"
parameter q1::Real[nout] = fill(1.0, nout)
"Maximum velocity for each axis"
parameter qd_max::Real[nout] = fill(1.0, nout)
"Maximum acceleration for each axis"
parameter qdd_max::Real[nout] = fill(1.0, nout)
"Time instant at which the movement starts"
parameter startTime::Time = 0
"Shared-knob speed limit (bottleneck axis) for the synchronized profile"
final parameter sd_max::Real = BlockComponents.ptp_sd_max(q0, q1, qd_max)
"Shared-knob acceleration limit (bottleneck axis) for the synchronized profile"
final parameter sdd_max::Real = BlockComponents.ptp_sdd_max(q0, q1, qdd_max)
"Total duration of the (bottleneck) move"
final parameter moveTime::Real = BlockComponents.ptp_move_time(sd_max, sdd_max)
"Machine-epsilon guard for detecting a non-moving axis"
final parameter eps0::Real = eps(Float64)
relations
endTime = startTime + moveTime
for i in 1:nout
moving[i] = (abs(q1[i] - q0[i]) > eps0) and (time < startTime + moveTime)
end
for i in 1:nout
q[i] = q0[i] + (q1[i] - q0[i]) * BlockComponents.ptp_q(time, 0.0, 1.0, sd_max, sdd_max, startTime)
qd[i] = (q1[i] - q0[i]) * BlockComponents.ptp_qd(time, 0.0, 1.0, sd_max, sdd_max, startTime)
qdd[i] = (q1[i] - q0[i]) * BlockComponents.ptp_qdd(time, 0.0, 1.0, sd_max, sdd_max, startTime)
end
metadata {
"Dyad": {
"labels": [
{"label": "$(instance)", "x": 500, "y": 1100, "rot": 0},
{
"label": "q",
"x": 845,
"y": 70,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
},
{
"label": "qd",
"x": 845,
"y": 270,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
},
{
"label": "qdd",
"x": 845,
"y": 500,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
},
{
"label": "moving",
"x": 845,
"y": 730,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
},
{
"label": "endTime",
"x": 845,
"y": 930,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
}
],
"icons": {"default": "dyad://BlockComponents/KinematicPTP.svg"}
}
}
endFlattened Source
"""
Move as fast as possible from `q0` to `q1` within given kinematic constraints
(point-to-point motion).
For each axis the block emits a minimum-time trajectory that does not exceed the
maximum velocity `qd_max` or maximum acceleration `qdd_max`. The result is a
trapezoidal velocity profile — accelerate at `qdd_max`, cruise at `qd_max`,
decelerate at `qdd_max` — or a triangular profile when the move is too short to
reach `qd_max`. The position, velocity, and acceleration are provided directly as
outputs `q`, `qd`, `qdd` (one scalar per axis), together with a Boolean `moving`
(true while an axis is still travelling) and the scalar `endTime` (the instant the
movement stops). This matches `Modelica.Blocks.Sources.KinematicPTP2`.
All axes are **phase-synchronized**: a single shared normalized path parameter
`s(t)` in `[0, 1]` (one trapezoidal profile, paced by the bottleneck axis) drives
every axis via `q[i] = q0[i] + (q1[i] - q0[i]) * s(t)`. Because they share the same
`s(t)`, every axis is at the same fraction of its travel at every instant, so the
joint path is a straight line — and they necessarily start and reach their targets
together (phase synchronization implies time synchronization). This matches
`Modelica.Blocks.Sources.KinematicPTP` and `KinematicPTP2`, and the vectorized
`point_to_point` trajectory.
The motion begins at `startTime` (default 0); before that the outputs hold at the
start position with zero velocity and acceleration.
The block is stateless: `q`, `qd`, `qdd` are closed-form functions of time, so no
integration or discrete events are involved.
"""
component KinematicPTP
"Position output for each axis"
q = [RealOutput() for i in 1:nout] {
"Dyad": {
"placement": {"diagram": {"iconName": "output", "x1": 1000, "y1": 20, "x2": 1100, "y2": 120}}
}
}
"Velocity output for each axis"
qd = [RealOutput() for i in 1:nout] {
"Dyad": {
"placement": {
"diagram": {"iconName": "output", "x1": 1000, "y1": 220, "x2": 1100, "y2": 320}
}
}
}
"Acceleration output for each axis"
qdd = [RealOutput() for i in 1:nout] {
"Dyad": {
"placement": {
"diagram": {"iconName": "output", "x1": 1000, "y1": 450, "x2": 1100, "y2": 550}
}
}
}
"= true while axis i is still moving; false once its target is reached (or if it does not move)"
moving = [BooleanOutput() for i in 1:nout] {
"Dyad": {
"placement": {
"diagram": {"iconName": "output", "x1": 1000, "y1": 680, "x2": 1100, "y2": 780}
}
}
}
"Time instant at which the movement stops"
endTime = RealOutput() {
"Dyad": {
"placement": {
"diagram": {"iconName": "output", "x1": 1000, "y1": 880, "x2": 1100, "y2": 980}
}
}
}
"Number of output axes"
structural parameter nout::Integer = 1
"Initial position for each axis"
parameter q0::Real[nout] = fill(0.0, nout)
"Final position for each axis"
parameter q1::Real[nout] = fill(1.0, nout)
"Maximum velocity for each axis"
parameter qd_max::Real[nout] = fill(1.0, nout)
"Maximum acceleration for each axis"
parameter qdd_max::Real[nout] = fill(1.0, nout)
"Time instant at which the movement starts"
parameter startTime::Time = 0
"Shared-knob speed limit (bottleneck axis) for the synchronized profile"
final parameter sd_max::Real = BlockComponents.ptp_sd_max(q0, q1, qd_max)
"Shared-knob acceleration limit (bottleneck axis) for the synchronized profile"
final parameter sdd_max::Real = BlockComponents.ptp_sdd_max(q0, q1, qdd_max)
"Total duration of the (bottleneck) move"
final parameter moveTime::Real = BlockComponents.ptp_move_time(sd_max, sdd_max)
"Machine-epsilon guard for detecting a non-moving axis"
final parameter eps0::Real = eps(Float64)
relations
endTime = startTime + moveTime
for i in 1:nout
moving[i] = (abs(q1[i] - q0[i]) > eps0) and (time < startTime + moveTime)
end
for i in 1:nout
q[i] = q0[i] + (q1[i] - q0[i]) * BlockComponents.ptp_q(time, 0.0, 1.0, sd_max, sdd_max, startTime)
qd[i] = (q1[i] - q0[i]) * BlockComponents.ptp_qd(time, 0.0, 1.0, sd_max, sdd_max, startTime)
qdd[i] = (q1[i] - q0[i]) * BlockComponents.ptp_qdd(time, 0.0, 1.0, sd_max, sdd_max, startTime)
end
metadata {
"Dyad": {
"labels": [
{"label": "$(instance)", "x": 500, "y": 1100, "rot": 0},
{
"label": "q",
"x": 845,
"y": 70,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
},
{
"label": "qd",
"x": 845,
"y": 270,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
},
{
"label": "qdd",
"x": 845,
"y": 500,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
},
{
"label": "moving",
"x": 845,
"y": 730,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
},
{
"label": "endTime",
"x": 845,
"y": 930,
"rot": 0,
"attrs": {"font-size": "120", "font-family": "sans-serif", "fill": "#939598"}
}
],
"icons": {"default": "dyad://BlockComponents/KinematicPTP.svg"}
}
}
endTest Cases ​
No test cases defined.
Related ​
Examples
Experiments
Analyses
Tests