Para que Mathematica al simplificar use implícitamente el hecho de que nuestros parámetros son números reales, decimos esto:

$Assumptions={s,t}∈Reals;

Una hélice

Nuestra querida hélice:

hélice = {Cos[2π t], Sin[2 π t], t};

Calculamos la norma de la velocidad, ‖σ'(t)‖

Simplify@ Norm@ D[hélice, t]

Como ‖σ'(t)‖ no es idénticamente 1, calculamos v = (∫_0^t)‖σ'(ξ)‖dξ como función de t

v = Integrate[Evaluate@ Simplify@ Norm@D[hélice, t], t]

Ahora escribimos la ecuación s=v y despejamos t en función de s

param = Solve[s == v, t][[1]]

Y redefimos la curva, ahora parametrizada por la longitud de arco s

hélice = hélice /. param

Ahora la curva está parametrizada por longitud de arco:

Simplify@ Norm@ D[hélice, s]

Un dibujo

ParametricPlot3D[hélice, {s, 0, 4π}, Axes -> False]

Calculemos el triedro de Frenet-Serret. Empezamos por el vector normal:

𝒯 = Simplify@ D[hélice, s]

La curvatura:

κ = Simplify@ Norm@D[𝒯, s]

El vector normal y el binormal:

𝒩 = ((D[𝒯, s])/κ)
ℬ = Simplify[𝒯\[Cross]𝒩]

Y, finalmente, la torsión de nuestra curva:

τ = Simplify[- D[ℬ, s] . 𝒩]

Hagamos un dibujo.

Definimos primero tres funciones que "dibujan" flechas de un punto de la hélice en la dirección de 𝒯, 𝒩, ℬ, respectivamente:

{tangente, normal, binormal} = Map[Arrow[{hélice, hélice + #}]&, {𝒯, 𝒩, ℬ}];

Y hacemos el mismo dibujo que antes pero agregándole el triedro en s = 2.

Show[
ParametricPlot3D[hélice, {s, 0, 4π}, Axes -> False],
Graphics3D[{Thick,Blue,tangente,Red,normal,Purple,binormal}] /. s->1,
PlotRange -> {{-2,2}, {-2,2}, {0, 2}}
]

Un poco más efectivo es hacer una animación del triedro desplazándose a lo largo de la curva:

Manipulate[
Evaluate@ Show[
ParametricPlot3D[hélice, {s, 0, 8π}, Axes -> False],
Graphics3D[{Thick,Blue,tangente,Red,normal,Purple,binormal}],
PlotRange -> {{-2,2},{-2,2},{0,5}}
],
{s, 0, 8π,Appearance->{"Open","Labelled"}}
]

Clear[𝒯, 𝒩, ℬ, κ, τ, tangente, normal, binormal]

La curva de Viviani

La curva de Viviani es la intersección entre la esfera de radio 1 centrada en el origen y el cilindro de ecuación (((x - 1/2))^2)+(y^2)=1/4. No es difícil parametrizarla, y uno obtiene:

viviani = {1+Cos[t], Sin[t], 2Sin[t/2]}/2;

Podemos verificar que esta curva está tanto en la esfera como en el cilindro:

Simplify[1==Norm@viviani]
Simplify[(((viviani[[1]]-1/2))^2)+((viviani[[2]])^2)==1/4]

Lo mejor es hacer un dibujo:

Show[Graphics3D[{
Opacity[0.25],
FaceForm[Blue], Sphere[{0,0,0}, 1],
FaceForm[Green], Cylinder[{{1/2,0,-2}, {1/2,0,2}}, 1/2]
}],
ParametricPlot3D[viviani, {t, 0, 4π}, PlotStyle -> {Yellow, Thick}],
Axes -> False
]

Podemos calcular la función v = (∫_0^t)‖σ '(ξ)‖dξ

v = Integrate[Evaluate[Simplify@ Norm@ D[viviani, t]], t]

Esta función es lo que se llama una función elíptica completa; no puede expresarse en términos de las funciones usuales. Cuando intentamos despejar t en función de s en la ecuación s= (∫_0^t)‖σ '(ξ)‖dξ no tenemos éxito: la ecuación no puede ser resulta...

Solve[s == v, t, Reals]

Para calcular el triedro de Frenet-Serret, entonces, vamos a usar las fórmulas correspondientes a curvas no necesariamente parametrizadas por longitud de arco.

𝒯 = Simplify@ Normalize@ D[viviani, t]

ℬ = Simplify@ Normalize[D[viviani, t]\[Cross]D[viviani, t, t]]

𝒩 = Simplify[ℬ\[Cross]𝒯]

κ[t_] = Simplify[Norm[D[viviani, t]\[Cross]D[viviani, t, t]]/((Norm[D[viviani, t]])^3)]

τ[t_] = Simplify[((Det[{D[viviani, t], D[viviani, t, t],D[viviani, t, t, t]}])/((Norm[D[viviani, t]\[Cross]D[viviani, t, t]])^3))]

Podemos hacer un dibujo similar al que hicimos con la hélice:

{tangente, normal, binormal} = Map[Arrow[{viviani, viviani + #}]&, {𝒯, 𝒩, ℬ}];

Manipulate[
Evaluate@ Show[
ParametricPlot3D[viviani, {t, 0, 4π}, Axes -> False],
Graphics3D[{Thick,Blue,tangente,Red,normal,Purple,binormal}],
PlotRange -> 2{{-1,1},{-1,1},{-1,1}}
],
{t, 0, 4π,Appearance->{"Open","Labelled"}}
]

Otra cosa que podemos hacer es dibujar la curva pintándola de forma que la curvatura (o la torsión) queden de manifiesto.

Primero definimos una función que manda números de [0,1] a colores del azul al rojo.

heat = ColorData["TemperatureMap"];

Grid[Transpose[{#, heat[#]}&/@Range[0, 1, 0.1]], Dividers->All]

En segundo lugar, calculamos el máximo y el mínimo de la curvatura en el intervalo en el que vamos a hacer el dibujo

κmin = NMinValue[{κ[t], 0≤t≤4π}, t];
κmax = NMaxValue[{κ[t], 0≤t≤4π}, t];

τmin = NMinValue[{τ[t], 0≤t≤4π}, t];
τmax = NMaxValue[{τ[t], 0≤t≤4π}, t];

Y ahora dibujamos la curva otra vez, pero pintandola de la curvatura normalizada y la torsión normalizadas

Module[{gs},
gs = {ParametricPlot3D[viviani, {t, 0, 4π}, 
ColorFunction ->Function[{x,y,z,t}, heat[((κ[t]-κmin)/(κmax-κmin))]],
PlotStyle ->Thickness[0.01],
ColorFunctionScaling->False,
PlotRange -> {{-2,2},{-2,2},{-2,2}},
Axes -> False
],
ParametricPlot3D[viviani, {t, 0, 4π}, 
ColorFunction ->Function[{x,y,z,t}, heat[((τ[t]-τmin)/(τmax-τmin))]],
PlotStyle ->Thickness[0.01],
ColorFunctionScaling->False,
PlotRange -> {{-2,2},{-2,2},{-2,2}},
Axes -> False
]};
Manipulate[gs[[i]],{{i, 1}, {1 -> "κ", 2->"τ"}}]
]

Nudo

Unaa curva un poco más complicada:

knot = KnotData["Trefoil","SpaceCurve"][t]

ParametricPlot3D[knot,{t,0,2Pi},PlotStyle->Thick, Axes->False]

𝒯 = Simplify@ Normalize@ D[knot, t];
ℬ = Simplify@ Normalize[D[knot, t]\[Cross]D[knot, t, t]];
𝒩 = Simplify[ℬ\[Cross]𝒯];
κ[t_] = Simplify[Norm[D[knot, t]\[Cross]D[knot, t, t]]/((Norm[D[knot, t]])^3)];
τ[t_] = Simplify[((Det[{D[knot, t], D[knot, t, t],D[knot, t, t, t]}])/((Norm[D[knot, t]\[Cross]D[knot, t, t]])^3))] ;

{tangent,normal,binormal}=Map[Arrow[{knot,knot+#}]&,{𝒯, 𝒩, ℬ}];

Manipulate[
Evaluate@ Show[
ParametricPlot3D[knot,{t,0,2Pi},PlotStyle->Thick], 
Graphics3D[{Thick,Blue,tangent,Red,normal,Purple,binormal}],
PlotRange->3, Boxed -> True, Axes -> None, ImageSize -> Large
],
{t,0,2Pi,Appearance->{"Open","Labelled"}}]

κmin = NMinValue[{κ[t], 0≤t≤4π}, t];
κmax = NMaxValue[{κ[t], 0≤t≤4π}, t];
τmin = NMinValue[{τ[t], 0≤t≤4π}, t];
τmax = NMaxValue[{τ[t], 0≤t≤4π}, t];

Module[{gs},
gs = {ParametricPlot3D[knot, {t, 0, 4π}, 
ColorFunction ->Function[{x,y,z,t}, heat[((κ[t]-κmin)/(κmax-κmin))]],
PlotStyle ->Thickness[0.01],
ColorFunctionScaling->False,
PlotRange -> 2{{-2,2},{-2,2},{-2,2}},
Axes -> False
],
ParametricPlot3D[knot, {t, 0, 4π}, 
ColorFunction ->Function[{x,y,z,t}, heat[((τ[t]-τmin)/(τmax-τmin))]],
PlotStyle ->Thickness[0.01],
ColorFunctionScaling->False,
PlotRange -> 2{{-2,2},{-2,2},{-2,2}},
Axes -> False
]};
Manipulate[gs[[i]],{{i, 1}, {1 -> "κ", 2->"τ"}}]
]

El problema inverso

Ahora vamos a ir en la dirección inversa: vamos a prefijar la curvatura y la torsión y vamos a resolver el sistema de ecuaciones diferenciales que determina la curva.

κ = Cos[t];
τ = Sin[t];
Module[{curva, tangente, normal, binormal, α, 𝒯, 𝒩, ℬ, solucion},
(* primero le ponemos nombres a las coordenadas de la curva y de los tres vectores de FS correspondientes *)
curva = α[#][t]&/@Range[3];
normal = 𝒩[#][t]&/@Range[3];
tangente = 𝒯[#][t]&/@Range[3];
binormal = ℬ[#][t]&/@Range[3];

(* ahora planteamos el problemas de valores iniciales *)
solucion = curva  /. NDSolve[Flatten[Thread/@{
(* queremos que la tangente sea la derivada de la curva *)
D[curva, t] == tangente,
(* que el triedro satisfaga las ecuaciones de FS *)
D[tangente, t]==κ normal,
D[normal, t] == -κ tangente+τ binormal,
D[binormal, t] == -τ normal,
(* que la curva arranque en el origen *)
(curva /. t->0) == {0,0,0},
(* y, finalmente, que el triedro arranque en el triedro canónico de (ℝ^3) *)
(tangente /. t-> 0) == {1,0,0},
(normal /. t-> 0) == {0,1,0},
(binormal /. t-> 0) == {0,0,1}
}], Flatten[{curva}], {t,0,10}
][[1]];
ParametricPlot3D[solucion, {t, 0, 10}, Axes -> False]
]