2019.04.22
幾何学DIYプラレール行き詰まり中。プラレールそのものの動作メカニズムに関する課題と、現実で組み上げる時のレール間の隙間について
う〜ん、どうやっても最外周部のこの部分が安定して通れず脱線してしまいます。上記写真は色々な試行錯誤の一環でレールの幅を2mm狭めたカスタムレールですがダメでした。プラレールの車輪はまっすぐしか走れない構造で、曲がるときは「壁づたいネズミ」方式で曲がっているだけなので、カーブ時に分岐があるとすぐにひっかかってしまいます。困った。。。。
もうこのパーツの基本構造を変更して、パーツの起点と終点の傾きと位置だけ維持して、間をまっすぐ×2本の交差に改良するしかないのか・・・・・ここまではカーブの曲がり方は市販されている半径21.4cmのカーブレールを忠実に再現していたので、こだわりたいところではありますが・・・・
あくまで「市販パーツで出来る幾何学構造をカスタムパーツで走れるようにする」ってこのプロジェクトのコンセプトに反する気がするんだよなー。
あと外周部のパーツはけっこう無理やりハメる必要があるのですが、その理由も分かってきた気がします。下記のレールは今作っている幾何学レールの全体像ですが
中心部の六角形的に組みあがっているパーツを中心に円の外側に4層のパーツが配置されています。計算上ではパーツとパーツは隙間無く連結されていくはずですが、実物はそうはいきませんね。結合部で恐らく0.5〜1mm程度(予想)の隙間があってつながっているはずです。これは4層で最外周部の設計半径が少なくとも2mm程度狂うことを意味しています。半径で2mm違えば、円周方向で12mm以上狂うことを意味しています。12mm違えばつながりませんよね。それが設計通りに出力したパーツであっても組み立て時に無理してハメこむことになる理由かと予想します。解決方法としては全てのパーツを0.5mm〜1mmずつぐらい短めに出力させれば解決するのかなと考えています。う〜ん、0.5mmにするか1mmにするかが問題だ
個人的メモも兼ねてここに現在の最適設計図を残します。現在のレール分割は(1)R30-(2)R15-(3)R20-(4)R12.5-(5)R35-(6)R45-(7)R35-(8)R7.5-(9)R25-(10)R45-(11)L22.5-(12)L22.5です。(※Rは右カーブレール、Lは左カーブレール、R30は右曲がり30度角の長さのレール)
すなわちオリジナルでR45×6-L45x1の7本を8回繰り返しだったレールを12本×8にしています。
(1)と(10)で通称「交差パーツA」、(3)と(9)で通称「交差パーツB」、(5)と(7)で「交差パーツC」、(11)と(12)で「交差パーツD」を出力します。(4)(6)(8)は交差しないレールです。
以下は元設計図、Perlで幾何学プラレールのレール位置をシミュレーションし、各レールの始まり座標と、進行方向ベクトルを算出、その数字をOpenSCADのスクリプトにコピペし、必要な交差パーツ4種類、短いレール3種類を各8セット出力します。
OpenSCADに移行させる各パーツの位置情報を出力するPerlスクリプト
--------------------------------------------------
#!/usr/bin/perl
#
use GD;
$im = GD::Image->new(1000,1000);
$black=$im->colorAllocate(0,0,0);
$white=$im->colorAllocate(255,255,255);
$red=$im->colorAllocate(255,0,0);
$green=$im->colorAllocate(0,128,0);
$im->line(500,0,500,1000,$green);
$im->line(0,500,1000,500,$green);
my $resolution=0.5;
@result=(0,0,0,1);
$count=1;
for($i=1;$i<=8;$i++){
@result=&right(30,@result); #a
@result=&right(15,@result); #a2
@result=&right(20,@result); #for b
@result=&right(12.5,@result); # free
@result=&right(35,@result); # for c
@result=&right(45,@result); # free
@result=&right(35,@result); # for c
@result=&right(7.5,@result); # free
@result=&right(25,@result); # for b
@result=&right(45,@result); # for a
@result=&left(22.5,@result);# for d
@result=&left(22.5,@result);
}
$png = $im->png;
open (WR,'>outtest6.png');
binmode WR;
print WR $png;
close WR;
exit;
sub right(){
($rad,$x1,$y1,$xa,$ya)=@_;
print $count.',right'.$rad.','.$x1.','.$y1.','.$xa.','.$ya."\n";
$r=214;
$xc=$x1+$ya*$r*sqrt(1/($ya*$ya+$xa*$xa));
$yc=$y1-$xa*$r*sqrt(1/($ya*$ya+$xa*$xa));
$im->filledArc(500+$x1,500+$y1,4,4,0,360,$white);
for ($t=0;$t<=$rad;$t=$t+$resolution){
$x2=$xc+cos($t/360*3.14159*2)*($x1-$xc)+sin($t/360*3.14159*2)*($y1-$yc);
$y2=$yc+cos($t/360*3.14159*2)*($y1-$yc)+sin($t/360*3.14159*2)*(-$x1+$xc);
#bibun
$xv=-sin($t/360*3.14159*2)*($x1-$xc)+cos($t/360*3.14159*2)*($y1-$yc);
$yv=-sin($t/360*3.14159*2)*($y1-$yc)+cos($t/360*3.14159*2)*(-$x1+$xc);
$im->filledArc(500+$x2,500+$y2,2,2,0,360,$red);
};
$im->string(gdMediumBoldFont,500+$x2,500+$y2,$count,$red);
$count++;
return ($x2,$y2,$xv,$yv);
}
sub left(){
($rad,$x1,$y1,$xa,$ya)=@_;
print $count.',left'.$rad.','.$x1.','.$y1.','.$xa.','.$ya."\n";
$r=214;
$xc=$x1-$ya*$r*sqrt(1/($ya*$ya+$xa*$xa));
$yc=$y1+$xa*$r*sqrt(1/($ya*$ya+$xa*$xa));
$im->filledArc(500+$x1,500+$y1,4,4,0,360,$white);
for ($t=0;$t>=-$rad;$t=$t-$resolution){
$x2=$xc+cos($t/360*3.14159*2)*($x1-$xc)+sin($t/360*3.14159*2)*($y1-$yc);
$y2=$yc+cos($t/360*3.14159*2)*($y1-$yc)+sin($t/360*3.14159*2)*(-$x1+$xc);
#bibun
$xv=-sin($t/360*3.14159*2)*($x1-$xc)+cos($t/360*3.14159*2)*($y1-$yc);
$yv=-sin($t/360*3.14159*2)*($y1-$yc)+cos($t/360*3.14159*2)*(-$x1+$xc);
$im->filledArc(500+$x2,500+$y2,2,2,0,360,$green);
};
$im->string(gdMediumBoldFont,500+$x2,500+$y2,$count,$green);
$count++;
return ($x2,$y2,-$xv,-$yv);
}
-----------------------------------------------------------------------
OpenSCADのスクリプトは
-----------------------------------------------------------------------
$fn=10;
split=100;
wall_body=8; // normal=
innerwall_body=8; //normal=8
wall_thickness=1.5; //normal=1.5
wall=8; //normal=8
width=38; //normal=38
//main /////////////////////////////////////////////
difference(){
body1();
body2();
};
module body1(){
//right(360,0,0,1,0,204.5);
// for c parts
//right(35,167.681683914059,208.9272926043,208.9272926043,46.3183160859407,214,"n5");
//right(35,170.531849424112,249.636005310954,197.711225018656,-81.8918280515363,214,"n43");
right(12.5,123.559506136865,193.949779762165,193.949779762165,90.4404938631353,214,"");
}
module body2(){
// for c parts
//rightDelete(35,167.681683914059,208.9272926043,208.9272926043,46.3183160859407,214,"n5");
//rightDelete(35,170.531849424112,249.636005310954,197.711225018656,-81.8918280515363,214,"n43");
}
module right(degree,x1,y1,xa,ya,r,name){
xc=x1+ya*r*sqrt(1/(ya*ya+xa*xa));
yc=y1-xa*r*sqrt(1/(ya*ya+xa*xa));
inDegree=9/(3.14159*2*r)*360;
Apitch=(degree-inDegree)/split;
for (t=[0:Apitch:degree-inDegree-Apitch+0.001]){body(t2xyz(t,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch*2,x1,y1,xa,ya,r,xc,yc));}
in(t2xyz(degree-inDegree,x1,y1,xa,ya,r,xc,yc),t2xyz(degree-inDegree+Apitch,x1,y1,xa,ya,r,xc,yc));
out(t2xyz(0+Apitch,x1,y1,xa,ya,r,xc,yc),t2xyz(0,x1,y1,xa,ya,r,xc,yc));
}
module left(degree,x1,y1,xa,ya,r,name){
xc=x1-ya*r*sqrt(1/(ya*ya+xa*xa));
yc=y1+xa*r*sqrt(1/(ya*ya+xa*xa));
inDegree=9/(3.14159*2*r)*360;
Apitch=(degree-inDegree)/split;
for (t=[0:-Apitch:-(degree-inDegree-Apitch+0.001)]){body(t2xyz(t,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch*2,x1,y1,xa,ya,r,xc,yc));}
in(t2xyz(-(degree-inDegree)+Apitch,x1,y1,xa,ya,r,xc,yc),t2xyz(-(degree-inDegree),x1,y1,xa,ya,r,xc,yc),name);
out(t2xyz(0,x1,y1,xa,ya,r,xc,yc),t2xyz(0+Apitch,x1,y1,xa,ya,r,xc,yc));
}
module rightDelete(degree,x1,y1,xa,ya,r,name){
xc=x1+ya*r*sqrt(1/(ya*ya+xa*xa));
yc=y1-xa*r*sqrt(1/(ya*ya+xa*xa));
inDegree=9/(3.14159*2*r)*360;
Apitch=(degree-inDegree)/split;
for (t=[0:Apitch:degree-inDegree-Apitch+0.001]){bodyDelete(t2xyz(t,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch*2,x1,y1,xa,ya,r,xc,yc),t);}
// for label
//for (t=[0:Apitch:degree-Apitch+0.001]){bodyDelete(t2xyz(t,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch*2,x1,y1,xa,ya,r,xc,yc));}
}
module leftDelete(degree,x1,y1,xa,ya,r,name){
xc=x1-ya*r*sqrt(1/(ya*ya+xa*xa));
yc=y1+xa*r*sqrt(1/(ya*ya+xa*xa));
inDegree=9/(3.14159*2*r)*360;
Apitch=(degree-inDegree)/split;
for (t=[0:-Apitch:-(degree-inDegree-Apitch+0.001)]){bodyDelete(t2xyz(t,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch*2,x1,y1,xa,ya,r,xc,yc),t);}
// for label
//for (t=[0:-Apitch:-(degree-Apitch+0.001)]){bodyDelete(t2xyz(t,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch,x1,y1,xa,ya,r,xc,yc),t2xyz(t+Apitch*2,x1,y1,xa,ya,r,xc,yc));}
}
////////////////////////////////////////////////////
function t2xyz(temp,x1,y1,xa,ya,r,xc,yc)=[xc+cos(temp)*(x1-xc)+sin(temp)*(y1-yc),yc+cos(temp)*(y1-yc)+sin(temp)*(-x1+xc),0];
function XY(angle,Ddis,Vdis)=[
sign(Ddis*angle[0])*sqrt(pow(Ddis,2)/(1+pow(angle[1]/angle[0],2)))+sign(Vdis*-angle[1])*sqrt(pow(Vdis,2)/(1+pow(angle[0]/angle[1],2))),
sign(Ddis)*angle[1]/abs(angle[0])*sqrt(pow(Ddis,2)/(1+pow(angle[1]/angle[0],2)))+sign(Vdis)*angle[0]/abs(angle[1])*sqrt(pow(Vdis,2)/(1+pow(angle[0]/angle[1],2)))];
module body(pos1,pos2,pos3){
Dir1=pos2-pos1;
Dir2=pos3-pos2;
translate([0,0,pos1[2]]){
linear_extrude(height = 1.5,center=true){
polygon(points=[pos1+XY(Dir1,0,width/2),pos1+XY(Dir1,0,9.5),pos2+XY(Dir2,0,9.5),pos2+XY(Dir2,0,width/2)]);
polygon(points=[pos1+XY(Dir1,0,-9.5),pos1+XY(Dir1,0,-width/2),pos2+XY(Dir2,0,-width/2),pos2+XY(Dir2,0,-9.5)]);
polygon(points=[pos1+XY(Dir1,0,8),pos1+XY(Dir1,0,-8),pos2+XY(Dir2,0,-8),pos2+XY(Dir2,0,8)]);
}
linear_extrude(height = wall_body,center=true){
polygon(points=[pos1+XY(Dir1,0,width/2),pos1+XY(Dir1,0,width/2-wall_thickness),pos2+XY(Dir2,0,width/2-wall_thickness),pos2+XY(Dir2,0,width/2)]);
polygon(points=[pos1+XY(Dir1,0,-width/2),pos1+XY(Dir1,0,-width/2+wall_thickness),pos2+XY(Dir2,0,-width/2+wall_thickness),pos2+XY(Dir2,0,-width/2)]);
}
linear_extrude(height = innerwall_body,center=true){
polygon(points=[pos1+XY(Dir1,0,8+wall_thickness),pos1+XY(Dir1,0,8),pos2+XY(Dir2,0,8),pos2+XY(Dir2,0,8+wall_thickness)]);
polygon(points=[pos1+XY(Dir1,0,-8-wall_thickness),pos1+XY(Dir1,0,-8),pos2+XY(Dir2,0,-8),pos2+XY(Dir2,0,-8-wall_thickness)]);
}
}
}
module bodyDelete(pos1,pos2,pos3){
Dir1=pos2-pos1;
Dir2=pos3-pos2;
train=5;
translate([0,0,pos1[2]]){
translate([0,0,(train+1.5)/2]){linear_extrude(height = train,center=true){
polygon(points=[pos1+XY(Dir1,0,width/2-wall_thickness),pos1+XY(Dir1,0,8+wall_thickness),pos2+XY(Dir2,0,8+wall_thickness),pos2+XY(Dir2,0,width/2-wall_thickness)]);
polygon(points=[pos1+XY(Dir1,0,-8-wall_thickness),pos1+XY(Dir1,0,-width/2+wall_thickness),pos2+XY(Dir2,0,-width/2+wall_thickness),pos2+XY(Dir2,0,-8-wall_thickness)]);
}}
translate([0,0,-(train+1.5)/2]){linear_extrude(height = train,center=true){
polygon(points=[pos1+XY(Dir1,0,width/2-wall_thickness),pos1+XY(Dir1,0,8+wall_thickness),pos2+XY(Dir2,0,8+wall_thickness),pos2+XY(Dir2,0,width/2-wall_thickness)]);
polygon(points=[pos1+XY(Dir1,0,-8-wall_thickness),pos1+XY(Dir1,0,-width/2+wall_thickness),pos2+XY(Dir2,0,-width/2+wall_thickness),pos2+XY(Dir2,0,-8-wall_thickness)]);
}}
}
}
module out (pos1,pos2){
//start out
Dir1=pos2-pos1;
//hiraban
translate([pos2[0],pos2[1],pos2[2]]){
linear_extrude(height = 1.5,center=true){
polygon(points=[XY(Dir1,0,-3),XY(Dir1,7.5,-5),XY(Dir1,7.5,-1),XY(Dir1,2.5,-1),XY(Dir1,2.5,1),XY(Dir1,7.5,1),XY(Dir1,7.5,5),XY(Dir1,0,3)]);
}
linear_extrude(height = wall,center=true){
polygon(points=[XY(Dir1,0,3),XY(Dir1,-1.5,3),XY(Dir1,-1.5,8),XY(Dir1,0,8),XY(Dir1,0,4.5),XY(Dir1,9,6.5),XY(Dir1,9,1),XY(Dir1,7.5,1),XY(Dir1,7.5,5)]);
polygon(points=[XY(Dir1,0,-3),XY(Dir1,-1.5,-3),XY(Dir1,-1.5,-8),XY(Dir1,0,-8),XY(Dir1,0,-4.5),XY(Dir1,9,-6.5),XY(Dir1,9,-1),XY(Dir1,7.5,-1),XY(Dir1,7.5,-5)]);
}}
}
module in (pos1,pos2,name){
//start in
Dir1=pos2-pos1;
pos3=[pos1[0]+XY(Dir1,9,0)[0],pos1[1]+XY(Dir1,9,0)[1],pos1[2]];
// pos4=[pos1[0]+XY(Dir1,9+pitch,0)[0],pos1[1]+XY(Dir1,9+pitch,0)[1],pos1[2]];
// Dir2=pos4-pos3;
Dir2=Dir1;
linear_extrude(height = wall,center=true){
polygon(points=[pos3+XY(Dir2,-9,-7),pos3+XY(Dir2,0,-4.5),pos3+XY(Dir2,0,-9.5),pos3+XY(Dir2,-12,-9.5),pos3+XY(Dir2,-12,9.5),pos3+XY(Dir2,0,9.5),pos3+XY(Dir2,0,4.5),pos3+XY(Dir2,-9,7)]);
//soto
polygon(points=[pos3+XY(Dir2,0,width/2-1.5),pos3+XY(Dir2,0,width/2),pos1+XY(Dir1,-1,width/2),pos1+XY(Dir1,-1,width/2-1.5)]);
polygon(points=[pos3+XY(Dir2,0,-width/2+1.5),pos3+XY(Dir2,0,-width/2),pos1+XY(Dir1,-1,-width/2),pos1+XY(Dir1,-1,-width/2+1.5)]);
}
//usui
linear_extrude(height = 1.5,center=true){
polygon(points=[pos1+XY(Dir1,-1,9.5),pos1+XY(Dir1,2.5,9.5),pos1+XY(Dir1,2.5,11),pos3+XY(Dir2,0,11),pos3+XY(Dir2,0,width/2-1.5),pos1+XY(Dir1,-1,width/2-1.5)]);
polygon(points=[pos1+XY(Dir1,-1,-9.5),pos1+XY(Dir1,2.5,-9.5),pos1+XY(Dir1,2.5,-11),pos3+XY(Dir2,0,-11),pos3+XY(Dir2,0,-width/2+1.5),pos1+XY(Dir1,-1,-width/2+1.5)]);
}
// translate(pos1+XY(Dir1,0,width/2-5.5)){
// rotate([0,0,atan2(Dir1[1],Dir1[0])]){
// linear_extrude(height = 2,center=true){
// text(str(name),size=2,font="Arial Black",$fn=16);
// }}
// }
}
-------------------------------------------------------------------
Category:#DIYプラレール
■ ■ ■ コメント ■ ■ ■
いいっすね!=17
001 [04.22 18:20]うむ@OCN:子供かわいい ↑(2)
002 [04.23 08:20]j:最外周部の交差の、片輪がはまるレール溝幅を狭めるしか無いのでは?(オリジナル軌跡じゃなくなるけど)交差する角度が浅くなるほど、車輪に対して壁が無くなる距離が長くなる→脱線 が原因と思います。車輪の半径と、レールの壁高さの関係から、脱線しない最大溝幅が計算できるはず。 ↑(1)
003 [04.23 11:22]ふぇちゅいん(管理人) TW★70:色々試したんだけどねぇ。溝幅狭めるのは、まったくダメだったね。理由としては交差が終わった後のレール幅も狭くなっているから、その点がデメリットになっていて意味が無いっぽい。 ↑(2)
004 [04.23 21:49]あ:交差してる部分に穴あけたらだめかな?穴がレールの壁になってくれたり。やっぱり無理ですかね ↑(2)
005 [04.23 23:11]標準規格から外れるけど@Ucom:レールの外輪側を底上げして列車を傾斜させて曲げやすくするとかはだめかな? ↑(2)
006 [04.24 06:16]通りすがり@Dion:専用車輪を作っちまおう!(ズル) ↑(1)
007 [04.24 11:52]のん@Plala:車輪前方にソリを立てた(というかスケートの金具)ガイドをつけて、車輪を正しい方向へ誘導するとか。レールだけで対応する方針なら不採用だけど。 ↑(1)
008 [04.24 11:53]のん@Plala:車輪前方にソリを立てた(というかスケートの金具)ガイドをつけて、車輪を正しい方向へ誘導するとか。レールだけで対応する方針なら不採用だけど。 ↑(1)
009 [04.24 23:17]7c:壁がなくなってる区間に、横断時には乗り越えられる・縦断時には車輪が引っかかって外に逃げない みたいな微妙な凸をつけるとか? ↑(1)
本カテゴリーで直近コメントが書かれた記事
→カテゴリー:#DIYプラレール(記事数:26)
本カテゴリーの最近の記事(コメント数)